3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-12-28 09:00:11 +01:00

Fixed some Scoreboard bugs and ScoreboardUpdater is now global

Dieser Commit ist enthalten in:
Tim203 2020-12-17 01:36:35 +01:00
Ursprung 988fd66a85
Commit 36c41b8dc7
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 064EE9F5BF7C3EE8
9 geänderte Dateien mit 383 neuen und 231 gelöschten Zeilen

Datei anzeigen

@ -56,6 +56,7 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
import org.geysermc.connector.network.translators.collision.CollisionTranslator;
import org.geysermc.connector.network.translators.world.block.entity.SkullBlockEntityTranslator;
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
import org.geysermc.connector.utils.DimensionUtils;
import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.connector.utils.LocaleUtils;
@ -147,6 +148,7 @@ public class GeyserConnector {
RecipeRegistry.init();
SoundRegistry.init();
SoundHandlerRegistry.init();
ScoreboardUpdater.init();
ResourcePack.loadPacks();

Datei anzeigen

@ -31,37 +31,35 @@ import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.scoreboard.Objective;
import org.geysermc.connector.scoreboard.Scoreboard;
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
import org.geysermc.connector.scoreboard.ScoreboardUpdater.ScoreboardSession;
@Getter
public class WorldCache {
private final GeyserSession session;
private final ScoreboardSession scoreboardSession;
@Setter
private Difficulty difficulty = Difficulty.EASY;
private boolean showCoordinates = true;
private Scoreboard scoreboard;
private final ScoreboardUpdater scoreboardUpdater;
public WorldCache(GeyserSession session) {
this.session = session;
this.scoreboard = new Scoreboard(session);
scoreboardUpdater = new ScoreboardUpdater(this);
scoreboardUpdater.start();
scoreboardSession = new ScoreboardSession(session);
}
public void removeScoreboard() {
if (scoreboard != null) {
for (Objective objective : scoreboard.getObjectives().values()) {
scoreboard.despawnObjective(objective);
for (Objective objective : scoreboard.getObjectives()) {
scoreboard.deleteObjective(objective);
}
scoreboard = new Scoreboard(session);
}
}
public int increaseAndGetScoreboardPacketsPerSecond() {
int pendingPps = scoreboardUpdater.incrementAndGetPacketsPerSecond();
int pps = scoreboardUpdater.getPacketsPerSecond();
int pendingPps = scoreboardSession.getPendingPacketsPerSecond().incrementAndGet();
int pps = scoreboardSession.getPacketsPerSecond();
return Math.max(pps, pendingPps);
}

Datei anzeigen

@ -25,12 +25,11 @@
package org.geysermc.connector.network.translators.java.scoreboard;
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerDisplayScoreboardPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerDisplayScoreboardPacket;
@Translator(packet = ServerDisplayScoreboardPacket.class)
public class JavaDisplayScoreboardTranslator extends PacketTranslator<ServerDisplayScoreboardPacket> {

Datei anzeigen

@ -25,30 +25,38 @@
package org.geysermc.connector.network.translators.java.scoreboard;
import com.github.steveice10.mc.protocol.data.game.scoreboard.ObjectiveAction;
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.GeyserLogger;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.session.cache.WorldCache;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.scoreboard.Objective;
import org.geysermc.connector.scoreboard.Scoreboard;
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
import org.geysermc.connector.network.translators.chat.MessageTranslator;
import com.github.steveice10.mc.protocol.data.game.scoreboard.ObjectiveAction;
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
import org.geysermc.connector.scoreboard.UpdateType;
@Translator(packet = ServerScoreboardObjectivePacket.class)
public class JavaScoreboardObjectiveTranslator extends PacketTranslator<ServerScoreboardObjectivePacket> {
private final GeyserLogger logger = GeyserConnector.getInstance().getLogger();
@Override
public void translate(ServerScoreboardObjectivePacket packet, GeyserSession session) {
WorldCache worldCache = session.getWorldCache();
Scoreboard scoreboard = worldCache.getScoreboard();
Objective objective = scoreboard.getObjective(packet.getName());
int pps = worldCache.increaseAndGetScoreboardPacketsPerSecond();
if (objective == null && packet.getAction() != ObjectiveAction.REMOVE) {
objective = scoreboard.registerNewObjective(packet.getName(), false);
Objective objective = scoreboard.getObjective(packet.getName());
if (objective != null && objective.getUpdateType() != UpdateType.REMOVE && packet.getAction() == ObjectiveAction.ADD) {
logger.warning("An objective with the same name '" + packet.getName() + "' already exists! Ignoring packet");
return;
}
if ((objective == null || objective.getUpdateType() == UpdateType.REMOVE) && packet.getAction() != ObjectiveAction.REMOVE) {
objective = scoreboard.registerNewObjective(packet.getName());
}
switch (packet.getAction()) {

Datei anzeigen

@ -66,7 +66,7 @@ public class JavaUpdateScoreTranslator extends PacketTranslator<ServerUpdateScor
if (objective != null) {
objective.removeScore(packet.getEntry());
} else {
for (Objective objective1 : scoreboard.getObjectives().values()) {
for (Objective objective1 : scoreboard.getObjectives()) {
objective1.removeScore(packet.getEntry());
}
}

Datei anzeigen

@ -26,6 +26,7 @@
package org.geysermc.connector.scoreboard;
import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition;
import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
import lombok.Getter;
import lombok.Setter;
@ -48,6 +49,7 @@ public final class Objective {
private int type = 0; // 0 = integer, 1 = heart
private Map<String, Score> scores = new ConcurrentHashMap<>();
// todo add a 'to add' map so that we don't have to use a concurrentHashMap
private Objective(Scoreboard scoreboard) {
this.id = scoreboard.getNextId().getAndIncrement();
@ -69,7 +71,7 @@ public final class Objective {
public Objective(Scoreboard scoreboard, String objectiveName, ScoreboardPosition displaySlot, String displayName, int type) {
this(scoreboard);
this.objectiveName = objectiveName;
this.displaySlot = correctDisplaySlot(displaySlot);
this.displaySlot = displaySlot;
this.displaySlotName = translateDisplaySlot(displaySlot);
this.displayName = displayName;
this.type = type;
@ -86,17 +88,6 @@ public final class Objective {
}
}
private static ScoreboardPosition correctDisplaySlot(ScoreboardPosition displaySlot) {
switch (displaySlot) {
case BELOW_NAME:
return ScoreboardPosition.BELOW_NAME;
case PLAYER_LIST:
return ScoreboardPosition.PLAYER_LIST;
default:
return ScoreboardPosition.SIDEBAR;
}
}
public void registerScore(String id, int score) {
if (!scores.containsKey(id)) {
long scoreId = scoreboard.getNextId().getAndIncrement();
@ -151,12 +142,74 @@ public final class Objective {
public void setActive(ScoreboardPosition displaySlot) {
if (!active) {
active = true;
this.displaySlot = correctDisplaySlot(displaySlot);
this.displaySlot = displaySlot;
displaySlotName = translateDisplaySlot(displaySlot);
}
}
public void deactivate() {
active = false;
}
public ScoreboardPosition getPositionCategory() {
switch (displaySlot) {
case PLAYER_LIST:
return ScoreboardPosition.PLAYER_LIST;
case BELOW_NAME:
return ScoreboardPosition.BELOW_NAME;
default:
return ScoreboardPosition.SIDEBAR;
}
}
public boolean hasTeamColor() {
return displaySlot != ScoreboardPosition.PLAYER_LIST &&
displaySlot != ScoreboardPosition.BELOW_NAME &&
displaySlot != ScoreboardPosition.SIDEBAR;
}
public TeamColor getTeamColor() {
switch (displaySlot) {
case SIDEBAR_TEAM_RED:
return TeamColor.RED;
case SIDEBAR_TEAM_AQUA:
return TeamColor.AQUA;
case SIDEBAR_TEAM_BLUE:
return TeamColor.BLUE;
case SIDEBAR_TEAM_GOLD:
return TeamColor.GOLD;
case SIDEBAR_TEAM_GRAY:
return TeamColor.GRAY;
case SIDEBAR_TEAM_BLACK:
return TeamColor.BLACK;
case SIDEBAR_TEAM_GREEN:
return TeamColor.GREEN;
case SIDEBAR_TEAM_WHITE:
return TeamColor.WHITE;
case SIDEBAR_TEAM_YELLOW:
return TeamColor.YELLOW;
case SIDEBAR_TEAM_DARK_RED:
return TeamColor.DARK_RED;
case SIDEBAR_TEAM_DARK_AQUA:
return TeamColor.DARK_AQUA;
case SIDEBAR_TEAM_DARK_BLUE:
return TeamColor.DARK_BLUE;
case SIDEBAR_TEAM_DARK_GRAY:
return TeamColor.DARK_GRAY;
case SIDEBAR_TEAM_DARK_GREEN:
return TeamColor.DARK_GREEN;
case SIDEBAR_TEAM_DARK_PURPLE:
return TeamColor.DARK_PURPLE;
case SIDEBAR_TEAM_LIGHT_PURPLE:
return TeamColor.LIGHT_PURPLE;
default:
return null;
}
}
public void removed() {
active = false;
updateType = UpdateType.REMOVE;
scores = null;
}
}

Datei anzeigen

@ -42,14 +42,16 @@ import java.util.concurrent.atomic.AtomicLong;
import static org.geysermc.connector.scoreboard.UpdateType.*;
@Getter
public final class Scoreboard {
private final GeyserSession session;
private final GeyserLogger logger;
@Getter
private final AtomicLong nextId = new AtomicLong(0);
private final Map<String, Objective> objectives = new ConcurrentHashMap<>();
private final Map<String, Team> teams = new HashMap<>();
private final Map<String, Objective> objectives = new HashMap<>();
private final Map<ScoreboardPosition, Objective> objectiveSlots = new HashMap<>();
private final Map<String, Team> teams = new ConcurrentHashMap<>(); // updated on multiple threads
// todo add a 'to add' map so that we don't have to use a concurrentHashMap
private int lastAddScoreCount = 0;
private int lastRemoveScoreCount = 0;
@ -59,11 +61,17 @@ public final class Scoreboard {
this.logger = GeyserConnector.getInstance().getLogger();
}
public Objective registerNewObjective(String objectiveId, boolean active) {
public Objective registerNewObjective(String objectiveId) {
Objective objective = objectives.get(objectiveId);
if (active || objective != null) {
return objective;
if (objective != null) {
// we have no other choice, or we have to make a new map?
// if the objective hasn't been deleted, we have to force it
if (objective.getUpdateType() != REMOVE) {
return null;
}
deleteObjective(objective);
}
objective = new Objective(this, objectiveId);
objectives.put(objectiveId, objective);
return objective;
@ -71,32 +79,24 @@ public final class Scoreboard {
public Objective displayObjective(String objectiveId, ScoreboardPosition displaySlot) {
Objective objective = objectives.get(objectiveId);
if (objective != null) {
if (!objective.isActive()) {
objective.setActive(displaySlot);
removeOldObjectives(objective);
return objective;
}
despawnObjective(objective);
if (objective == null) {
return null;
}
objective = new Objective(this, objectiveId, displaySlot, "unknown", 0);
objectives.put(objectiveId, objective);
removeOldObjectives(objective);
if (!objective.isActive()) {
objective.setActive(displaySlot);
// for reactivated objectives
objective.setUpdateType(ADD);
}
Objective storedObjective = objectiveSlots.get(displaySlot);
if (storedObjective != null) {
deactivateObjective(storedObjective);
}
objectiveSlots.put(displaySlot, objective);
return objective;
}
private void removeOldObjectives(Objective newObjective) {
for (Objective next : objectives.values()) {
if (next.getId() == newObjective.getId()) {
continue;
}
if (next.getDisplaySlot() == newObjective.getDisplaySlot()) {
next.setUpdateType(REMOVE);
}
}
}
public Team registerNewTeam(String teamName, Set<String> players) {
Team team = teams.get(teamName);
if (team != null) {
@ -113,6 +113,10 @@ public final class Scoreboard {
return objectives.get(objectiveName);
}
public Collection<Objective> getObjectives() {
return objectives.values();
}
public Team getTeam(String teamName) {
return teams.get(teamName);
}
@ -121,6 +125,7 @@ public final class Scoreboard {
Objective objective = getObjective(objectiveName);
if (objective != null) {
objective.setUpdateType(REMOVE);
objective.deactivate();
}
}
@ -132,114 +137,38 @@ public final class Scoreboard {
}
public void onUpdate() {
List<ScoreInfo> addScores = new ArrayList<>(getLastAddScoreCount());
List<ScoreInfo> removeScores = new ArrayList<>(getLastRemoveScoreCount());
List<ScoreInfo> addScores = new ArrayList<>(lastAddScoreCount);
List<ScoreInfo> removeScores = new ArrayList<>(lastRemoveScoreCount);
List<Objective> removedObjectives = new ArrayList<>();
Team playerTeam = getTeamFor(session.getPlayerEntity().getUsername());
Objective correctSidebar = null;
for (Objective objective : objectives.values()) {
if (!objective.isActive()) {
logger.debug("Ignoring non-active Scoreboard Objective '" + objective.getObjectiveName() + '\'');
continue;
}
// hearts can't hold teams, so we treat them differently
if (objective.getType() == 1) {
for (Score score : objective.getScores().values()) {
boolean update = score.shouldUpdate();
if (update) {
score.update(objective.getObjectiveName());
}
if (score.getUpdateType() != REMOVE && update) {
addScores.add(score.getCachedInfo());
}
if (score.getUpdateType() != ADD && update) {
removeScores.add(score.getCachedInfo());
}
}
continue;
}
boolean objectiveUpdate = objective.getUpdateType() == UPDATE;
boolean objectiveAdd = objective.getUpdateType() == ADD;
boolean objectiveRemove = objective.getUpdateType() == REMOVE;
for (Score score : objective.getScores().values()) {
Team team = score.getTeam();
boolean add = objectiveAdd || objectiveUpdate;
boolean remove = false;
if (team != null) {
if (team.getUpdateType() == REMOVE || !team.hasEntity(score.getName())) {
score.setTeam(null);
add = true;
remove = true;
}
}
add |= score.shouldUpdate();
remove |= score.shouldUpdate();
if (score.getUpdateType() == REMOVE || objectiveRemove) {
add = false;
}
if (score.getUpdateType() == ADD || objectiveRemove) {
remove = false;
}
if (objectiveRemove && score.getCachedData() != null) {
// This score has been sent to the client and needs to be removed since the objective is being removed
remove = true;
} else if (score.shouldUpdate()) {
score.update(objective.getObjectiveName());
}
if (add) {
addScores.add(score.getCachedInfo());
}
if (remove) {
removeScores.add(score.getCachedInfo());
}
// score is pending to be removed, so we can remove it from the objective
if (score.getUpdateType() == REMOVE) {
objective.removeScore0(score.getName());
}
score.setUpdateType(NOTHING);
}
if (objectiveRemove) {
// objective has been deleted
if (objective.getUpdateType() == REMOVE) {
removedObjectives.add(objective);
continue;
}
if (objectiveUpdate) {
RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket();
removeObjectivePacket.setObjectiveId(objective.getObjectiveName());
session.sendUpstreamPacket(removeObjectivePacket);
if (playerTeam != null && playerTeam.getColor() == objective.getTeamColor()) {
correctSidebar = objective;
}
if ((objectiveAdd || objectiveUpdate) && !objectiveRemove) {
SetDisplayObjectivePacket displayObjectivePacket = new SetDisplayObjectivePacket();
displayObjectivePacket.setObjectiveId(objective.getObjectiveName());
displayObjectivePacket.setDisplayName(objective.getDisplayName());
displayObjectivePacket.setCriteria("dummy");
displayObjectivePacket.setDisplaySlot(objective.getDisplaySlotName());
displayObjectivePacket.setSortOrder(1); // ??
session.sendUpstreamPacket(displayObjectivePacket);
}
objective.setUpdateType(NOTHING);
}
if (correctSidebar == null) {
correctSidebar = objectiveSlots.get(ScoreboardPosition.SIDEBAR);
}
handleObjective(objectiveSlots.get(ScoreboardPosition.PLAYER_LIST), addScores, removeScores, removedObjectives);
handleObjective(correctSidebar, addScores, removeScores, removedObjectives);
handleObjective(objectiveSlots.get(ScoreboardPosition.BELOW_NAME), addScores, removeScores, removedObjectives);
Iterator<Team> teamIterator = teams.values().iterator();
while (teamIterator.hasNext()) {
Team current = teamIterator.next();
switch (current.getUpdateType()) {
switch (current.getCachedUpdateType()) {
case ADD:
case UPDATE:
current.markUpdated();
@ -265,15 +194,156 @@ public final class Scoreboard {
// prevents crashes in some cases
for (Objective objective : removedObjectives) {
despawnObjective(objective);
deleteObjective(objective);
}
lastAddScoreCount = addScores.size();
lastRemoveScoreCount = removeScores.size();
}
public void despawnObjective(Objective objective) {
private void handleObjective(Objective objective, List<ScoreInfo> addScores, List<ScoreInfo> removeScores, List<Objective> removedObjectives) {
if (objective == null) {
return;
}
// objective has been removed when scores is null
if (objective.getScores() == null) {
objectiveSlots.remove(objective.getDisplaySlot());
return;
}
if (!objective.isActive()) {
deactivateObjective(objective);
objectiveSlots.remove(objective.getDisplaySlot());
return;
}
// hearts can't hold teams, so we treat them differently
if (objective.getType() == 1) {
for (Score score : objective.getScores().values()) {
boolean update = score.shouldUpdate();
if (update) {
score.update(objective.getObjectiveName());
}
if (score.getUpdateType() != REMOVE && update) {
addScores.add(score.getCachedInfo());
}
if (score.getUpdateType() != ADD && update) {
removeScores.add(score.getCachedInfo());
}
}
return;
}
boolean objectiveUpdate = objective.getUpdateType() == UPDATE;
boolean objectiveAdd = objective.getUpdateType() == ADD;
boolean objectiveRemove = objective.getUpdateType() == REMOVE;
for (Score score : objective.getScores().values()) {
Team team = score.getTeam();
boolean add = objectiveAdd || objectiveUpdate;
boolean remove = false;
if (team != null) {
if (team.getUpdateType() == REMOVE || !team.hasEntity(score.getName())) {
score.setTeam(null);
add = true;
remove = true;
}
}
add |= score.shouldUpdate();
remove |= score.shouldUpdate();
if (score.getUpdateType() == REMOVE || objectiveRemove) {
add = false;
}
if (score.getUpdateType() == ADD || objectiveRemove) {
remove = false;
}
if (objectiveRemove && score.getCachedData() != null) {
// This score has been sent to the client and needs to be removed since the objective is being removed
remove = true;
} else if (score.shouldUpdate()) {
score.update(objective.getObjectiveName());
}
if (add) {
addScores.add(score.getCachedInfo());
}
if (remove) {
removeScores.add(score.getCachedInfo());
}
// score is pending to be removed, so we can remove it from the objective
if (score.getUpdateType() == REMOVE) {
objective.removeScore0(score.getName());
}
score.setUpdateType(NOTHING);
}
if (objectiveRemove) {
removedObjectives.add(objective);
}
if (objectiveUpdate) {
RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket();
removeObjectivePacket.setObjectiveId(objective.getObjectiveName());
session.sendUpstreamPacket(removeObjectivePacket);
}
if ((objectiveAdd || objectiveUpdate) && !objectiveRemove) {
SetDisplayObjectivePacket displayObjectivePacket = new SetDisplayObjectivePacket();
displayObjectivePacket.setObjectiveId(objective.getObjectiveName());
displayObjectivePacket.setDisplayName(objective.getDisplayName());
displayObjectivePacket.setCriteria("dummy");
displayObjectivePacket.setDisplaySlot(objective.getDisplaySlotName());
displayObjectivePacket.setSortOrder(1); // ??
session.sendUpstreamPacket(displayObjectivePacket);
}
objective.setUpdateType(NOTHING);
}
private void deactivateObjective(Objective objective) {
// Scoreboard has been removed already
if (objective.getScores() == null) {
return;
}
List<ScoreInfo> removedScores = new ArrayList<>(objective.getScores().size());
for (Score score : objective.getScores().values()) {
removedScores.add(score.getCachedInfo());
}
objective.deactivate();
SetScorePacket scorePacket = new SetScorePacket();
scorePacket.setAction(SetScorePacket.Action.REMOVE);
scorePacket.setInfos(removedScores);
session.sendUpstreamPacket(scorePacket);
RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket();
removeObjectivePacket.setObjectiveId(objective.getObjectiveName());
session.sendUpstreamPacket(removeObjectivePacket);
}
public void deleteObjective(Objective objective) {
objectives.remove(objective.getObjectiveName());
Objective storedSlot = objectiveSlots.get(objective.getDisplaySlot());
if (storedSlot != null && storedSlot.getId() == objective.getId()) {
deactivateObjective(objective);
objective.removed();
return;
}
objective.removed();
RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket();

Datei anzeigen

@ -25,6 +25,8 @@
package org.geysermc.connector.scoreboard;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.network.session.GeyserSession;
@ -34,91 +36,107 @@ import org.geysermc.connector.utils.LanguageUtils;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ScoreboardUpdater extends Thread {
public class ScoreboardUpdater implements Runnable {
public static final int FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD;
public static final int SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD = 250;
private static final int FIRST_MILLIS_BETWEEN_UPDATES = 250; // 4 updates per second
private static final int SECOND_MILLIS_BETWEEN_UPDATES = 1000 * 3; // 1 update per 3 seconds
private static final int SECOND_MILLIS_BETWEEN_UPDATES = 1000 * 3; // 1 update per seconds
private static final boolean DEBUG_ENABLED;
private final WorldCache worldCache;
private final GeyserSession session;
private int millisBetweenUpdates = FIRST_MILLIS_BETWEEN_UPDATES;
private long lastUpdate = System.currentTimeMillis();
private long lastLog = -1;
private long lastPacketsPerSecondUpdate = System.currentTimeMillis();
private final AtomicInteger packetsPerSecond = new AtomicInteger(0);
private final AtomicInteger pendingPacketsPerSecond = new AtomicInteger(0);
public ScoreboardUpdater(WorldCache worldCache) {
super("Scoreboard Updater");
this.worldCache = worldCache;
session = worldCache.getSession();
}
@Override
public void run() {
if (!session.isClosed()) {
long currentTime = System.currentTimeMillis();
// reset score-packets per second every second
if (currentTime - lastPacketsPerSecondUpdate > 1000) {
lastPacketsPerSecondUpdate = currentTime;
packetsPerSecond.set(pendingPacketsPerSecond.get());
pendingPacketsPerSecond.set(0);
}
if (currentTime - lastUpdate > millisBetweenUpdates) {
lastUpdate = currentTime;
int pps = packetsPerSecond.get();
if (pps >= FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD) {
boolean reachedSecondThreshold = pps >= SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD;
if (reachedSecondThreshold) {
millisBetweenUpdates = SECOND_MILLIS_BETWEEN_UPDATES;
} else {
millisBetweenUpdates = FIRST_MILLIS_BETWEEN_UPDATES;
}
worldCache.getScoreboard().onUpdate();
if (DEBUG_ENABLED && (currentTime - lastLog > 60000)) { // one minute
int threshold = reachedSecondThreshold ?
SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD :
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD;
GeyserConnector.getInstance().getLogger().info(
LanguageUtils.getLocaleStringLog("geyser.scoreboard.updater.threshold_reached.log", session.getName(), threshold, pps) +
LanguageUtils.getLocaleStringLog("geyser.scoreboard.updater.threshold_reached", (millisBetweenUpdates / 1000.0))
);
lastLog = currentTime;
}
}
}
session.getConnector().getGeneralThreadPool().schedule(this, 50, TimeUnit.MILLISECONDS);
}
}
public int getPacketsPerSecond() {
return packetsPerSecond.get();
}
/**
* Increase the Scoreboard Packets Per Second and return the updated value
*/
public int incrementAndGetPacketsPerSecond() {
return pendingPacketsPerSecond.incrementAndGet();
}
private static GeyserConnector connector;
static {
GeyserConfiguration config = GeyserConnector.getInstance().getConfig();
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD = Math.min(config.getScoreboardPacketThreshold(), SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD);
DEBUG_ENABLED = config.isDebugMode();
}
private long lastUpdate = System.currentTimeMillis();
private long lastPacketsPerSecondUpdate = System.currentTimeMillis();
public static void init() {
connector = GeyserConnector.getInstance();
ScoreboardUpdater updater = new ScoreboardUpdater();
updater.run();
}
public void run() {
long timeTillAction = getTimeTillNextAction();
if (timeTillAction > 0) {
connector.getGeneralThreadPool().schedule(this, timeTillAction, TimeUnit.MILLISECONDS);
return;
}
long currentTime = System.currentTimeMillis();
// reset score-packets per second every second
if (currentTime - lastPacketsPerSecondUpdate > 1000) {
lastPacketsPerSecondUpdate = currentTime;
for (GeyserSession session : connector.getPlayers()) {
ScoreboardSession scoreboardSession = session.getWorldCache().getScoreboardSession();
scoreboardSession.packetsPerSecond = scoreboardSession.getPendingPacketsPerSecond().get();
scoreboardSession.pendingPacketsPerSecond.set(0);
}
}
if (currentTime - lastUpdate > FIRST_MILLIS_BETWEEN_UPDATES) {
lastUpdate = currentTime;
for (GeyserSession session : connector.getPlayers()) {
WorldCache worldCache = session.getWorldCache();
ScoreboardSession scoreboardSession = worldCache.getScoreboardSession();
int pps = scoreboardSession.getPacketsPerSecond();
if (pps >= FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD) {
boolean reachedSecondThreshold = pps >= SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD;
if (reachedSecondThreshold) {
scoreboardSession.millisBetweenUpdates = SECOND_MILLIS_BETWEEN_UPDATES;
} else {
scoreboardSession.millisBetweenUpdates = FIRST_MILLIS_BETWEEN_UPDATES;
}
if (currentTime - scoreboardSession.lastUpdate > scoreboardSession.millisBetweenUpdates) {
worldCache.getScoreboard().onUpdate();
if (DEBUG_ENABLED && (currentTime - scoreboardSession.lastLog > 60000)) { // one minute
int threshold = reachedSecondThreshold ?
SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD :
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD;
GeyserConnector.getInstance().getLogger().info(
LanguageUtils.getLocaleStringLog("geyser.scoreboard.updater.threshold_reached.log", session.getName(), threshold, pps) +
LanguageUtils.getLocaleStringLog("geyser.scoreboard.updater.threshold_reached", (scoreboardSession.millisBetweenUpdates / 1000.0))
);
scoreboardSession.lastLog = currentTime;
}
}
}
}
}
connector.getGeneralThreadPool().schedule(this, getTimeTillNextAction(), TimeUnit.MILLISECONDS);
}
private long getTimeTillNextAction() {
long currentTime = System.currentTimeMillis();
long timeUntilNextUpdate = FIRST_MILLIS_BETWEEN_UPDATES - (currentTime - lastUpdate);
long timeUntilPacketReset = 1000 - (currentTime - lastPacketsPerSecondUpdate);
return Math.min(timeUntilNextUpdate, timeUntilPacketReset);
}
@RequiredArgsConstructor
@Getter
public static class ScoreboardSession {
private final GeyserSession session;
private final AtomicInteger pendingPacketsPerSecond = new AtomicInteger(0);
private int packetsPerSecond;
private int millisBetweenUpdates = FIRST_MILLIS_BETWEEN_UPDATES;
private long lastUpdate;
private long lastLog;
}
}

Datei anzeigen

@ -66,7 +66,7 @@ public final class Team {
}
// we don't have to change the updateType,
// because the scores itself need updating, not the team
for (Objective objective : scoreboard.getObjectives().values()) {
for (Objective objective : scoreboard.getObjectives()) {
for (String addedEntity : added) {
Score score = objective.getScores().get(addedEntity);
if (score != null) {
@ -169,6 +169,10 @@ public final class Team {
}
public UpdateType getUpdateType() {
return currentData.updateType;
}
public UpdateType getCachedUpdateType() {
return cachedData != null ? cachedData.updateType : currentData.updateType;
}