From c36cc89eafe7f2d5f5337bcfe43c7803936356b0 Mon Sep 17 00:00:00 2001 From: bobhenl <18662086+bobhenl@users.noreply.github.com> Date: Fri, 30 Oct 2026 17:02:37 +0100 Subject: [PATCH] Cache boss bar title conversions for 1.8 clients --- .../viaversion/viarewind/ViaRewindConfig.java | 7 ++++++ .../viarewind/api/ViaRewindConfig.java | 8 +++++++ .../rewriter/PlayerPacketRewriter1_9.java | 7 ++++-- .../viaversion/viarewind/utils/ChatUtil.java | 23 +++++++++++++++++++ .../resources/assets/viarewind/config.yml | 6 ++++- 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/com/viaversion/viarewind/ViaRewindConfig.java b/common/src/main/java/com/viaversion/viarewind/ViaRewindConfig.java index 38d7d497c..ce0f5fab8 100644 --- a/common/src/main/java/com/viaversion/viarewind/ViaRewindConfig.java +++ b/common/src/main/java/com/viaversion/viarewind/ViaRewindConfig.java @@ -40,6 +40,7 @@ public class ViaRewindConfig extends Config implements com.viaversion.viarewind. private String offhandCommand; private boolean emulateLevitationEffect; private boolean handlePlayerCombatPacket; + private boolean cacheBossBarTextConversion; public ViaRewindConfig(File configFile, Logger logger) { super(configFile, logger); @@ -64,6 +65,7 @@ private void loadFields() { offhandCommand = getString("offhand-command", "/offhand"); emulateLevitationEffect = getBoolean("emulate-levitation-effect", true); handlePlayerCombatPacket = getBoolean("handle-player-combat-packet", true); + cacheBossBarTextConversion = getBoolean("cache-bossbar-text-conversion", true); } @Override @@ -126,6 +128,11 @@ public boolean handlePlayerCombatPacket() { return handlePlayerCombatPacket; } + @Override + public boolean cacheBossBarTextConversion() { + return cacheBossBarTextConversion; + } + @Override public URL getDefaultConfigURL() { return getClass().getClassLoader().getResource("assets/viarewind/config.yml"); diff --git a/common/src/main/java/com/viaversion/viarewind/api/ViaRewindConfig.java b/common/src/main/java/com/viaversion/viarewind/api/ViaRewindConfig.java index 3a6dbf773..7339e95f7 100644 --- a/common/src/main/java/com/viaversion/viarewind/api/ViaRewindConfig.java +++ b/common/src/main/java/com/viaversion/viarewind/api/ViaRewindConfig.java @@ -114,6 +114,14 @@ public interface ViaRewindConfig extends Config { */ boolean handlePlayerCombatPacket(); + /** + * Caches the legacy text conversion of boss bar titles for 1.8 players. + * Plugins often resend the same title to every online player, so most conversions can be reused. + * + * @return true if enabled + */ + boolean cacheBossBarTextConversion(); + enum CooldownIndicator { TITLE, ACTION_BAR, BOSS_BAR, DISABLED } diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/PlayerPacketRewriter1_9.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/PlayerPacketRewriter1_9.java index b0629e21d..3b2716abe 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/PlayerPacketRewriter1_9.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_9to1_8/rewriter/PlayerPacketRewriter1_9.java @@ -80,7 +80,7 @@ protected void registerPackets() { wrapper.read(Types.VAR_INT); // Division wrapper.read(Types.UNSIGNED_BYTE); // Flags - bossbar.add(uuid, ChatUtil.jsonToLegacy(title), health); + bossbar.add(uuid, bossBarTitleToLegacy(title), health); } else if (action == 1 /* remove */) { bossbar.remove(uuid); } else if (action == 2 /* update health */) { @@ -88,7 +88,7 @@ protected void registerPackets() { bossbar.updateHealth(uuid, health); } else if (action == 3 /* update title */) { final JsonElement title = wrapper.read(Types.COMPONENT); - bossbar.updateTitle(uuid, ChatUtil.jsonToLegacy(title)); + bossbar.updateTitle(uuid, bossBarTitleToLegacy(title)); } }); @@ -604,4 +604,7 @@ public void register() { }); } + private static String bossBarTitleToLegacy(final JsonElement title) { + return ViaRewind.getConfig().cacheBossBarTextConversion() ? ChatUtil.cachedJsonToLegacy(title) : ChatUtil.jsonToLegacy(title); + } } diff --git a/common/src/main/java/com/viaversion/viarewind/utils/ChatUtil.java b/common/src/main/java/com/viaversion/viarewind/utils/ChatUtil.java index 920e7640e..0d080f9b6 100644 --- a/common/src/main/java/com/viaversion/viarewind/utils/ChatUtil.java +++ b/common/src/main/java/com/viaversion/viarewind/utils/ChatUtil.java @@ -26,6 +26,8 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13; import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter; import com.viaversion.viaversion.util.ComponentUtil; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.regex.Pattern; @@ -41,6 +43,8 @@ protected void handleTranslate(JsonObject object, String translate) { } } }; + private static final int LEGACY_CACHE_SIZE = 2048; + private static final Map LEGACY_CACHE = new ConcurrentHashMap<>(); public static String jsonToLegacy(String json) { if (json == null || json.equals("null") || json.isEmpty()) { @@ -79,6 +83,25 @@ public static String jsonToLegacy(JsonElement component) { } } + /** + * Same as {@link #jsonToLegacy(JsonElement)}, but caches the result by the serialized component. + * The conversion does not depend on the connection, so the result is shared between all players. + * Once full, the cache is cleared as a whole. + */ + public static String cachedJsonToLegacy(JsonElement component) { + // Use the serialized text as key, JsonPrimitive#equals treats e.g. 1 and 1.0 as equal + final String key = component.toString(); + String legacy = LEGACY_CACHE.get(key); + if (legacy == null) { + legacy = jsonToLegacy(component); + if (LEGACY_CACHE.size() >= LEGACY_CACHE_SIZE) { + LEGACY_CACHE.clear(); + } + LEGACY_CACHE.put(key, legacy); + } + return legacy; + } + public static String removeUnusedColor(String legacy, char last) { if (legacy == null) return null; legacy = UNUSED_COLOR_PATTERN.matcher(legacy).replaceAll("$1$2"); diff --git a/common/src/main/resources/assets/viarewind/config.yml b/common/src/main/resources/assets/viarewind/config.yml index ea1ede16d..7527844bf 100644 --- a/common/src/main/resources/assets/viarewind/config.yml +++ b/common/src/main/resources/assets/viarewind/config.yml @@ -41,4 +41,8 @@ offhand-command: '/offhand' emulate-levitation-effect: true # # If enabled, 1.8 players will handle the player combat packet added in 1.9 by showing the custom death message above the hotbar. -handle-player-combat-packet: true \ No newline at end of file +handle-player-combat-packet: true +# +# Caches the text conversion of boss bar titles for 1.8 players. +# Plugins often resend the same title to every online player, so this saves a lot of work. Disable if you see wrong boss bar titles. +cache-bossbar-text-conversion: true \ No newline at end of file