diff --git a/pom.xml b/pom.xml
index 0b4ef14..3f8909f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -52,13 +52,13 @@
net.kyori
adventure-api
- 5.1.1
+ 5.2.0
provided
net.kyori
adventure-text-serializer-legacy
- 5.1.1
+ 5.2.0
provided
diff --git a/src/main/java/fr/mrmicky/fastboard/FastBoard.java b/src/main/java/fr/mrmicky/fastboard/FastBoard.java
index 53b9b04..5cc67f0 100644
--- a/src/main/java/fr/mrmicky/fastboard/FastBoard.java
+++ b/src/main/java/fr/mrmicky/fastboard/FastBoard.java
@@ -66,7 +66,7 @@ public FastBoard(Player player) {
public void updateTitle(String title) {
Objects.requireNonNull(title, "title");
- if (!VersionType.V1_13.isHigherOrEqual() && title.length() > 32) {
+ if (!VersionType.V1_13.isCurrentAtLeast() && title.length() > 32) {
throw new IllegalArgumentException("Title is longer than 32 chars");
}
@@ -82,7 +82,7 @@ public void updateTitle(String title) {
public void updateLines(String... lines) {
Objects.requireNonNull(lines, "lines");
- if (!VersionType.V1_13.isHigherOrEqual()) {
+ if (!VersionType.V1_13.isCurrentAtLeast()) {
int lineCount = 0;
for (String s : lines) {
if (s != null && s.length() > 30) {
@@ -95,6 +95,9 @@ public void updateLines(String... lines) {
super.updateLines(lines);
}
+ /**
+ * {@inheritDoc}
+ */
@Override
protected void sendLineChange(int score) throws Throwable {
int maxLength = hasLinesMaxLength() ? 16 : 1024;
@@ -130,7 +133,12 @@ protected void sendLineChange(int score) throws Throwable {
suffix = suffix.substring(0, Math.min(maxLength, suffix.length()));
}
- sendTeamPacket(score, TeamMode.UPDATE, prefix, suffix);
+ if (VersionType.V1_20_3.isCurrentAtLeast()) {
+ sendModernScorePacket(score, ScoreboardAction.CHANGE);
+ } else {
+ sendScorePacket(score, ScoreboardAction.CHANGE);
+ sendTeamPacket(score, TeamMode.UPDATE, prefix, suffix);
+ }
}
@Override
@@ -160,6 +168,6 @@ protected String emptyLine() {
* @return true if scoreboard lines are limited by the legacy prefix/suffix length
*/
protected boolean hasLinesMaxLength() {
- return !VersionType.V1_13.isHigherOrEqual();
+ return !VersionType.V1_13.isCurrentAtLeast();
}
}
diff --git a/src/main/java/fr/mrmicky/fastboard/FastBoardBase.java b/src/main/java/fr/mrmicky/fastboard/FastBoardBase.java
index e2b215d..c8a8a85 100644
--- a/src/main/java/fr/mrmicky/fastboard/FastBoardBase.java
+++ b/src/main/java/fr/mrmicky/fastboard/FastBoardBase.java
@@ -85,7 +85,9 @@ public abstract class FastBoardBase {
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
- if (FastReflection.isRepackaged()) {
+ if (FastReflection.nmsOptionalClass("network.chat.numbers", "NumberFormat").isPresent()) {
+ VERSION_TYPE = VersionType.V1_20_3;
+ } else if (FastReflection.isRepackaged()) {
VERSION_TYPE = VersionType.V1_17;
} else if (FastReflection.nmsOptionalClass(null, "ScoreboardServer$Action").isPresent()
|| FastReflection.nmsOptionalClass(null, "ServerScoreboard$Method").isPresent()) {
@@ -105,8 +107,9 @@ public abstract class FastBoardBase {
Class> packetSbObjClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardObjective", "ClientboundSetObjectivePacket");
Class> packetSbDisplayObjClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardDisplayObjective", "ClientboundSetDisplayObjectivePacket");
Class> packetSbScoreClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardScore", "ClientboundSetScorePacket");
- Class> packetSbTeamClass = FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardTeam", "ClientboundSetPlayerTeamPacket");
- Class> sbTeamClass = VersionType.V1_17.isHigherOrEqual()
+ Class> packetSbTeamClass = VersionType.V1_20_3.isCurrentAtLeast()
+ ? null : FastReflection.nmsClass(gameProtocolPackage, "PacketPlayOutScoreboardTeam", "ClientboundSetPlayerTeamPacket");
+ Class> sbTeamClass = VersionType.V1_17.isCurrentAtLeast() && !VersionType.V1_20_3.isCurrentAtLeast()
? FastReflection.innerClass(packetSbTeamClass, innerClass -> !innerClass.isEnum()) : null;
Field playerConnectionField = Arrays.stream(entityPlayerClass.getFields())
.filter(field -> field.getType().isAssignableFrom(playerConnectionClass))
@@ -126,29 +129,30 @@ public abstract class FastBoardBase {
SEND_PACKET = lookup.unreflect(sendPacketMethod);
Class> scoreboardClass = FastReflection.nmsClass("world.scores", "Scoreboard");
- Class> playerTeamClass = FastReflection.nmsClass("world.scores", "ScoreboardTeam", "PlayerTeam");
+ Class> playerTeamClass = VersionType.V1_20_3.isCurrentAtLeast() ?
+ null : FastReflection.nmsClass("world.scores", "ScoreboardTeam", "PlayerTeam");
Class> objectiveClass = FastReflection.nmsClass("world.scores", "ScoreboardObjective", "Objective");
Class> objectiveCriteriaClass = FastReflection.nmsClass("world.scores.criteria", "IScoreboardCriteria", "ObjectiveCriteria");
- PLAYER_TEAM = lookup.unreflectConstructor(playerTeamClass.getConstructor(scoreboardClass, String.class));
Class> objectiveRenderTypeClass = FastReflection.nmsOptionalClass("world.scores.criteria", "IScoreboardCriteria$EnumScoreboardHealthDisplay", "ObjectiveCriteria$RenderType").orElse(null);
- Optional> numberFormat = FastReflection.nmsOptionalClass("network.chat.numbers", "NumberFormat");
MethodHandle packetSbSetScore;
MethodHandle packetSbResetScore = null;
MethodHandle fixedFormatConstructor = null;
+ MethodHandle packetSbSerializableTeam = null;
+ MethodHandle packetSbTeam = null;
+ MethodHandle playerTeam = null;
Object blankNumberFormat = null;
boolean scoreOptionalComponents = false;
- if (numberFormat.isPresent()) { // 1.20.3
- OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass, CHAT_COMPONENT_CLASS, objectiveRenderTypeClass, boolean.class, numberFormat.get()));
- PACKET_SB_OBJ = lookup.unreflectConstructor(packetSbObjClass.getConstructor(objectiveClass, int.class));
- PACKET_SB_DISPLAY_OBJ = lookup.unreflectConstructor(packetSbDisplayObjClass.getConstructor(DISPLAY_SLOT_TYPE, objectiveClass));
+ if (VersionType.V1_20_3.isCurrentAtLeast()) {
+ Class> numberFormatClass = FastReflection.nmsClass("network.chat.numbers", "NumberFormat");
+ OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass, CHAT_COMPONENT_CLASS, objectiveRenderTypeClass, boolean.class, numberFormatClass));
Class> blankFormatClass = FastReflection.nmsClass("network.chat.numbers", "BlankFormat");
Class> fixedFormatClass = FastReflection.nmsClass("network.chat.numbers", "FixedFormat");
Class> resetScoreClass = FastReflection.nmsClass(gameProtocolPackage, "ClientboundResetScorePacket");
- MethodType scoreType = MethodType.methodType(void.class, String.class, String.class, int.class, CHAT_COMPONENT_CLASS, numberFormat.get());
+ MethodType scoreType = MethodType.methodType(void.class, String.class, String.class, int.class, CHAT_COMPONENT_CLASS, numberFormatClass);
MethodType scoreTypeOptional = MethodType.methodType(void.class, String.class, String.class, int.class, Optional.class, Optional.class);
MethodType removeScoreType = MethodType.methodType(void.class, String.class, String.class);
MethodType fixedFormatType = MethodType.methodType(void.class, CHAT_COMPONENT_CLASS);
@@ -161,49 +165,54 @@ public abstract class FastBoardBase {
scoreOptionalComponents = optionalScorePacket.isPresent();
packetSbResetScore = lookup.findConstructor(resetScoreClass, removeScoreType);
blankNumberFormat = blankField.isPresent() ? blankField.get().get(null) : null;
- } else if (VersionType.V1_17.isHigherOrEqual()) {
- Class> enumSbAction = FastReflection.nmsClass("server", "ScoreboardServer$Action", "ServerScoreboard$Method");
- MethodType scoreType = MethodType.methodType(void.class, enumSbAction, String.class, String.class, int.class);
- packetSbSetScore = lookup.findConstructor(packetSbScoreClass, scoreType);
- OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass, CHAT_COMPONENT_CLASS, objectiveRenderTypeClass));
- PACKET_SB_OBJ = lookup.unreflectConstructor(packetSbObjClass.getConstructor(objectiveClass, int.class));
- PACKET_SB_DISPLAY_OBJ = lookup.unreflectConstructor(packetSbDisplayObjClass.getConstructor(int.class, objectiveClass));
} else {
- packetSbSetScore = lookup.findConstructor(packetSbScoreClass, MethodType.methodType(void.class));
- if (VersionType.V1_13.isHigherOrEqual()) {
+ Constructor> packetSbTeamConstructor = sbTeamClass != null ? packetSbTeamClass.getDeclaredConstructor(String.class, int.class, Optional.class, Collection.class) : packetSbTeamClass.getDeclaredConstructor();
+ packetSbTeamConstructor.setAccessible(true);
+ packetSbTeam = lookup.unreflectConstructor(packetSbTeamConstructor);
+ packetSbSerializableTeam = sbTeamClass != null ? lookup.unreflectConstructor(sbTeamClass.getConstructor(playerTeamClass)) : null;
+
+ playerTeam = lookup.unreflectConstructor(playerTeamClass.getConstructor(scoreboardClass, String.class));
+ if (VersionType.V1_17.isCurrentAtLeast()) {
+ Class> enumSbAction = FastReflection.nmsClass("server", "ScoreboardServer$Action", "ServerScoreboard$Method");
+ MethodType scoreType = MethodType.methodType(void.class, enumSbAction, String.class, String.class, int.class);
+ packetSbSetScore = lookup.findConstructor(packetSbScoreClass, scoreType);
OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass, CHAT_COMPONENT_CLASS, objectiveRenderTypeClass));
} else {
- OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass));
+ packetSbSetScore = lookup.findConstructor(packetSbScoreClass, MethodType.methodType(void.class));
+ if (VersionType.V1_13.isCurrentAtLeast()) {
+ OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass, CHAT_COMPONENT_CLASS, objectiveRenderTypeClass));
+ } else {
+ OBJECTIVE = lookup.unreflectConstructor(objectiveClass.getConstructor(scoreboardClass, String.class, objectiveCriteriaClass));
+ }
+ }
+
+ for (Class> clazz : Arrays.asList(packetSbScoreClass, packetSbTeamClass, sbTeamClass, playerTeamClass, objectiveClass)) {
+ if (clazz == null) {
+ continue;
+ }
+ Field[] fields = Arrays.stream(clazz.getDeclaredFields())
+ .filter(field -> !Modifier.isStatic(field.getModifiers()))
+ .toArray(Field[]::new);
+ for (Field field : fields) {
+ field.setAccessible(true);
+ }
+ PACKETS.put(clazz, fields);
}
- PACKET_SB_OBJ = lookup.unreflectConstructor(packetSbObjClass.getConstructor(objectiveClass, int.class));
- PACKET_SB_DISPLAY_OBJ = lookup.unreflectConstructor(packetSbDisplayObjClass.getConstructor(int.class, objectiveClass));
}
+ PACKET_SB_OBJ = lookup.unreflectConstructor(packetSbObjClass.getConstructor(objectiveClass, int.class));
+ PACKET_SB_DISPLAY_OBJ = lookup.unreflectConstructor(packetSbDisplayObjClass.getConstructor(DISPLAY_SLOT_TYPE, objectiveClass));
PACKET_SB_SET_SCORE = packetSbSetScore;
PACKET_SB_RESET_SCORE = packetSbResetScore;
- Constructor> packetSbTeamConstructor = sbTeamClass != null ? packetSbTeamClass.getDeclaredConstructor(String.class, int.class, Optional.class, Collection.class) : packetSbTeamClass.getDeclaredConstructor();
- packetSbTeamConstructor.setAccessible(true);
- PACKET_SB_TEAM = lookup.unreflectConstructor(packetSbTeamConstructor);
- PACKET_SB_SERIALIZABLE_TEAM = sbTeamClass != null ? lookup.unreflectConstructor(sbTeamClass.getConstructor(playerTeamClass)) : null;
+ PACKET_SB_TEAM = packetSbTeam;
+ PACKET_SB_SERIALIZABLE_TEAM = packetSbSerializableTeam;
FIXED_NUMBER_FORMAT = fixedFormatConstructor;
BLANK_NUMBER_FORMAT = blankNumberFormat;
SCORE_OPTIONAL_COMPONENTS = scoreOptionalComponents;
+ PLAYER_TEAM = playerTeam;
- for (Class> clazz : Arrays.asList(packetSbScoreClass, packetSbTeamClass, sbTeamClass, playerTeamClass, objectiveClass)) {
- if (clazz == null) {
- continue;
- }
- Field[] fields = Arrays.stream(clazz.getDeclaredFields())
- .filter(field -> !Modifier.isStatic(field.getModifiers()))
- .toArray(Field[]::new);
- for (Field field : fields) {
- field.setAccessible(true);
- }
- PACKETS.put(clazz, fields);
- }
-
- if (VersionType.V1_8.isHigherOrEqual()) {
- String enumSbActionClass = VersionType.V1_13.isHigherOrEqual()
+ if (VersionType.V1_8.isCurrentAtLeast()) {
+ String enumSbActionClass = VersionType.V1_13.isCurrentAtLeast()
? "ScoreboardServer$Action"
: "PacketPlayOutScoreboardScore$EnumScoreboardAction";
ENUM_SB_HEALTH_DISPLAY = FastReflection.nmsClass("world.scores.criteria", "IScoreboardCriteria$EnumScoreboardHealthDisplay", "ObjectiveCriteria$RenderType");
@@ -218,7 +227,7 @@ public abstract class FastBoardBase {
ENUM_SB_ACTION_CHANGE = null;
ENUM_SB_ACTION_REMOVE = null;
}
- if (VersionType.V1_13.isHigherOrEqual()) {
+ if (VersionType.V1_13.isCurrentAtLeast()) {
DUMMY_SCOREBOARD_CRITERIA = null;
} else {
DUMMY_SCOREBOARD_CRITERIA = FastReflection.nmsClass("world.scores.criteria", "ScoreboardBaseCriteria").getConstructor(String.class).newInstance("dummy");
@@ -347,11 +356,6 @@ public synchronized void updateLine(int line, T score, T scoreText) {
this.scores.set(line, scoreText);
sendLineChange(getScoreByLine(line));
-
- if (customScoresSupported()) {
- sendScorePacket(getScoreByLine(line), ScoreboardAction.CHANGE);
- }
-
return;
}
@@ -449,11 +453,13 @@ public synchronized void updateLines(Collection lines, Collection scores)
if (oldLines.size() > linesSize) {
for (int i = oldLinesCopy.size(); i > linesSize; i--) {
- sendTeamPacket(i - 1, TeamMode.REMOVE);
+ if (!VersionType.V1_20_3.isCurrentAtLeast()) {
+ sendTeamPacket(i - 1, TeamMode.REMOVE);
+ }
sendScorePacket(i - 1, ScoreboardAction.REMOVE);
oldLines.remove(0);
}
- } else {
+ } else if (!VersionType.V1_20_3.isCurrentAtLeast()) {
for (int i = oldLinesCopy.size(); i < linesSize; i++) {
sendScorePacket(i, ScoreboardAction.CHANGE);
sendTeamPacket(i, TeamMode.CREATE, null, null);
@@ -462,11 +468,14 @@ public synchronized void updateLines(Collection lines, Collection scores)
}
for (int i = 0; i < linesSize; i++) {
- if (!Objects.equals(getLineByScore(oldLines, i), getLineByScore(i))) {
- sendLineChange(i);
- }
- if (!Objects.equals(getLineByScore(oldScores, i), getLineByScore(this.scores, i))) {
- sendScorePacket(i, ScoreboardAction.CHANGE);
+ boolean isNewTextDifferentFromOld = !Objects.equals(getLineByScore(oldLines, i), getLineByScore(i));
+ boolean isNewFormatDifferentFromOld = !Objects.equals(getLineByScore(oldScores, i), getLineByScore(this.scores, i));
+ if (VersionType.V1_20_3.isCurrentAtLeast() && (isNewTextDifferentFromOld || isNewFormatDifferentFromOld)) {
+ sendModernScorePacket(i, ScoreboardAction.CHANGE);
+ } else {
+ if (isNewTextDifferentFromOld) {
+ sendLineChange(i);
+ }
}
}
} catch (Throwable t) {
@@ -489,8 +498,8 @@ public synchronized void updateScore(int line, T score) {
this.scores.set(line, score);
try {
- if (customScoresSupported()) {
- sendScorePacket(getScoreByLine(line), ScoreboardAction.CHANGE);
+ if (VersionType.V1_20_3.isCurrentAtLeast()) {
+ sendModernScorePacket(getScoreByLine(line), ScoreboardAction.CHANGE);
}
} catch (Throwable e) {
throw new RuntimeException("Unable to update line score", e);
@@ -544,8 +553,8 @@ public synchronized void updateScores(Collection scores) {
this.scores.set(i, newScores.get(i));
try {
- if (customScoresSupported()) {
- sendScorePacket(getScoreByLine(i), ScoreboardAction.CHANGE);
+ if (VersionType.V1_20_3.isCurrentAtLeast()) {
+ sendModernScorePacket(getScoreByLine(i), ScoreboardAction.CHANGE);
}
} catch (Throwable e) {
throw new RuntimeException("Unable to update scores", e);
@@ -580,15 +589,6 @@ public boolean isDeleted() {
return this.deleted;
}
- /**
- * Returns whether the server supports custom scoreboard scores (1.20.3+ servers only).
- *
- * @return true if the server supports custom scores
- */
- public boolean customScoresSupported() {
- return BLANK_NUMBER_FORMAT != null;
- }
-
/**
* Returns the scoreboard size (the number of lines).
*
@@ -609,7 +609,11 @@ public synchronized void delete() {
try {
for (int i = 0; i < this.lines.size(); i++) {
- sendTeamPacket(i, TeamMode.REMOVE);
+ if (VersionType.V1_20_3.isCurrentAtLeast()) {
+ sendScorePacket(i, ScoreboardAction.REMOVE);
+ } else {
+ sendTeamPacket(i, TeamMode.REMOVE);
+ }
}
sendObjectivePacket(ObjectiveMode.REMOVE);
@@ -620,6 +624,11 @@ public synchronized void delete() {
this.deleted = true;
}
+ /**
+ * Sends a line update packet for the specified internal score.
+ *
+ * @param score the position to update
+ */
protected abstract void sendLineChange(int score) throws Throwable;
protected abstract Object toMinecraftComponent(T value) throws Throwable;
@@ -666,15 +675,7 @@ protected Object sendObjectivePacket(ObjectiveMode mode) throws Throwable {
false, // Auto-update, unused
null // Number format
);
- } else if (VersionType.V1_17.isHigherOrEqual()) {
- objective = OBJECTIVE.invoke(
- null, // Scoreboard, unused
- this.id, // Objective name
- null, // Criteria, unused
- toMinecraftComponent(this.title), // Display name
- ENUM_SB_HEALTH_DISPLAY_INTEGER // Render type
- );
- } else if (VersionType.V1_13.isHigherOrEqual()) {
+ } else if (VersionType.V1_13.isCurrentAtLeast()) {
objective = OBJECTIVE.invoke(
null, // Scoreboard, unused
this.id, // Objective name
@@ -705,7 +706,7 @@ protected void sendDisplayObjectivePacket(Object objective) throws Throwable {
}
protected void sendScorePacket(int score, ScoreboardAction action) throws Throwable {
- if (VersionType.V1_17.isHigherOrEqual()) {
+ if (VersionType.V1_17.isCurrentAtLeast()) {
sendModernScorePacket(score, action);
return;
}
@@ -714,7 +715,7 @@ protected void sendScorePacket(int score, ScoreboardAction action) throws Throwa
setField(packet, String.class, COLOR_CODES[score], 0); // Player Name
- if (VersionType.V1_8.isHigherOrEqual()) {
+ if (VersionType.V1_8.isCurrentAtLeast()) {
Object enumAction = action == ScoreboardAction.REMOVE
? ENUM_SB_ACTION_REMOVE : ENUM_SB_ACTION_CHANGE;
setField(packet, ENUM_SB_ACTION, enumAction);
@@ -730,7 +731,7 @@ protected void sendScorePacket(int score, ScoreboardAction action) throws Throwa
sendPacket(packet);
}
- private void sendModernScorePacket(int score, ScoreboardAction action) throws Throwable {
+ protected void sendModernScorePacket(int score, ScoreboardAction action) throws Throwable {
String objName = COLOR_CODES[score];
Object enumAction = action == ScoreboardAction.REMOVE
? ENUM_SB_ACTION_REMOVE : ENUM_SB_ACTION_CHANGE;
@@ -745,13 +746,14 @@ private void sendModernScorePacket(int score, ScoreboardAction action) throws Th
return;
}
- T scoreFormat = getLineByScore(this.scores, score);
- Object format = scoreFormat != null
- ? FIXED_NUMBER_FORMAT.invoke(toMinecraftComponent(scoreFormat))
+ Object text = toMinecraftComponent(getLineByScore(score));
+ T rawFormat = getLineByScore(this.scores, score);
+ Object format = rawFormat != null
+ ? FIXED_NUMBER_FORMAT.invoke(toMinecraftComponent(rawFormat))
: BLANK_NUMBER_FORMAT;
Object scorePacket = SCORE_OPTIONAL_COMPONENTS
- ? PACKET_SB_SET_SCORE.invoke(objName, this.id, score, Optional.empty(), Optional.of(format))
- : PACKET_SB_SET_SCORE.invoke(objName, this.id, score, null, format);
+ ? PACKET_SB_SET_SCORE.invoke(objName, this.id, score, Optional.of(text), Optional.of(format))
+ : PACKET_SB_SET_SCORE.invoke(objName, this.id, score, text, format);
sendPacket(scorePacket);
}
@@ -768,7 +770,7 @@ protected void sendTeamPacket(int score, TeamMode mode, T prefix, T suffix)
Object packet;
if (mode == TeamMode.REMOVE) {
- if (VersionType.V1_17.isHigherOrEqual()) {
+ if (VersionType.V1_17.isCurrentAtLeast()) {
packet = PACKET_SB_TEAM.invoke(
this.id + ':' + score, // Team name
mode.ordinal(), // Update mode
@@ -784,7 +786,7 @@ protected void sendTeamPacket(int score, TeamMode mode, T prefix, T suffix)
return;
}
- if (VersionType.V1_17.isHigherOrEqual()) {
+ if (VersionType.V1_17.isCurrentAtLeast()) {
Object team = PLAYER_TEAM.invoke(null, this.id + ':' + score);
setComponentField(team, null, 1); // Display name
setComponentField(team, prefix, 2); // Prefix
@@ -840,7 +842,7 @@ private void setField(Object packet, Class> fieldType, Object value, int count
}
private void setComponentField(Object packet, T value, int count) throws Throwable {
- if (!VersionType.V1_13.isHigherOrEqual()) {
+ if (!VersionType.V1_13.isCurrentAtLeast()) {
String line = value != null ? serializeLine(value) : "";
setField(packet, String.class, line, count);
return;
@@ -866,10 +868,10 @@ public enum ScoreboardAction {
CHANGE, REMOVE
}
- enum VersionType {
- V1_7, V1_8, V1_13, V1_17;
+ public enum VersionType {
+ V1_7, V1_8, V1_13, V1_17, V1_20_3;
- public boolean isHigherOrEqual() {
+ public boolean isCurrentAtLeast() {
return VERSION_TYPE.ordinal() >= ordinal();
}
}
diff --git a/src/main/java/fr/mrmicky/fastboard/adventure/FastBoard.java b/src/main/java/fr/mrmicky/fastboard/adventure/FastBoard.java
index 77b3b12..6717ba7 100644
--- a/src/main/java/fr/mrmicky/fastboard/adventure/FastBoard.java
+++ b/src/main/java/fr/mrmicky/fastboard/adventure/FastBoard.java
@@ -75,15 +75,18 @@ public FastBoard(Player player) {
}
/**
- * Sends a line update packet for the specified internal score.
- *
- * @param score the internal score of the line to update
+ * {@inheritDoc}
*/
@Override
protected void sendLineChange(int score) throws Throwable {
Component line = getLineByScore(score);
- sendTeamPacket(score, FastBoardBase.TeamMode.UPDATE, line, null);
+ if (VersionType.V1_20_3.isCurrentAtLeast()) {
+ sendModernScorePacket(score, ScoreboardAction.CHANGE);
+ } else {
+ sendScorePacket(score, ScoreboardAction.CHANGE);
+ sendTeamPacket(score, TeamMode.UPDATE, line, null);
+ }
}
@Override