From bb2b1e38bd69941b223af2f55ad44a797a0b355d Mon Sep 17 00:00:00 2001 From: James Powell Date: Thu, 16 Apr 2026 13:48:44 +0700 Subject: [PATCH 1/4] Harden status ping path: cache response, throttle install logging. Add a short-TTL (1s) cache for the remapped legacy status response in both StatusPacketMixin and LegacyPacketHandler so repeated server-list refreshes reuse a prebuilt packet instead of reconstructing each time. Replace per-connection INFO logging for STATUS translator installs with a sampled summary (every 10s with counts) to eliminate log flood from rapid server-list polling without losing visibility. Made-with: Cursor --- .../handler/LegacyPacketHandler.java | 53 ++++++++++++++++--- .../legacylink/mixin/StatusPacketMixin.java | 31 ++++++++--- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java b/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java index 82b9726..36fc401 100644 --- a/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java +++ b/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java @@ -104,6 +104,14 @@ public class LegacyPacketHandler extends ChannelDuplexHandler { private static final String HANDLER_NAME = "legacylink"; private static final EntityType LEGACY_SLIME_TYPE = resolveEntityType("minecraft:slime"); + + private static final long STATUS_LOG_INTERVAL_NS = 10_000_000_000L; // 10 seconds + private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second + private static long statusInstallCount; + private static long statusInstallWindowStart = System.nanoTime(); + private static volatile ClientboundStatusResponsePacket cachedStatusResponse; + private static volatile long statusCacheBuiltAt; + private static final Map LEGACY_PARTICLE_FALLBACKS = Map.of( "minecraft:noxious_gas", ParticleTypes.SMOKE, "minecraft:noxious_gas_cloud", ParticleTypes.CLOUD, @@ -204,12 +212,33 @@ public static void install(Connection connection, String phase) { + "; refusing addLast fallback (legacy translation would not run correctly)."); } pipeline.addAfter(HandlerNames.PACKET_HANDLER, HANDLER_NAME, new LegacyPacketHandler()); - LegacyLinkMod.LOGGER.info( - "[LegacyLink] Outbound translator placed after '{}' (phase={}) for {}", - HandlerNames.PACKET_HANDLER, - phase, - anonymizeAddress(connection.getRemoteAddress()) - ); + + if ("status".equals(phase)) { + logStatusInstall(); + } else { + LegacyLinkMod.LOGGER.info( + "[LegacyLink] Outbound translator placed after '{}' (phase={}) for {}", + HandlerNames.PACKET_HANDLER, + phase, + anonymizeAddress(connection.getRemoteAddress()) + ); + } + } + + private static synchronized void logStatusInstall() { + statusInstallCount++; + long now = System.nanoTime(); + long elapsed = now - statusInstallWindowStart; + if (elapsed >= STATUS_LOG_INTERVAL_NS) { + long elapsedSeconds = elapsed / 1_000_000_000L; + LegacyLinkMod.LOGGER.info( + "[LegacyLink] STATUS translator installed {} time(s) in the last {}s", + statusInstallCount, + elapsedSeconds + ); + statusInstallCount = 0; + statusInstallWindowStart = now; + } } private static String anonymizeAddress(@Nullable Object remoteAddress) { @@ -524,7 +553,12 @@ public ClientboundBundlePacket remapBundlePacket(ClientboundBundlePacket bundleP return new ClientboundBundlePacket(rewritten); } - private ClientboundStatusResponsePacket remapStatusResponse(ClientboundStatusResponsePacket packet) { + private static ClientboundStatusResponsePacket remapStatusResponse(ClientboundStatusResponsePacket packet) { + long now = System.nanoTime(); + ClientboundStatusResponsePacket cached = cachedStatusResponse; + if (cached != null && (now - statusCacheBuiltAt) < STATUS_CACHE_TTL_NS) { + return cached; + } ServerStatus status = packet.status(); ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version("26.1.2", LegacyLinkConstants.PROTOCOL_26_1_2); ServerStatus remapped = new ServerStatus( @@ -534,7 +568,10 @@ private ClientboundStatusResponsePacket remapStatusResponse(ClientboundStatusRes status.favicon(), status.enforcesSecureChat() ); - return new ClientboundStatusResponsePacket(remapped); + ClientboundStatusResponsePacket built = new ClientboundStatusResponsePacket(remapped); + cachedStatusResponse = built; + statusCacheBuiltAt = now; + return built; } private ClientboundRegistryDataPacket filterRegistryData(ClientboundRegistryDataPacket packet) { diff --git a/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java b/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java index 671c937..f8781cb 100644 --- a/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java +++ b/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java @@ -19,6 +19,12 @@ @Mixin(ServerStatusPacketListenerImpl.class) public abstract class StatusPacketMixin { + private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second + + private static volatile ClientboundStatusResponsePacket cachedLegacyResponse; + private static volatile long cachedAtNanos; + private static volatile ServerStatus cachedSourceStatus; + @Shadow @Final private Connection connection; @Shadow @Final private ServerStatus status; @Shadow private boolean hasRequestedStatus; @@ -33,18 +39,31 @@ public abstract class StatusPacketMixin { } this.hasRequestedStatus = true; + this.connection.send(getOrBuildCachedResponse(this.status)); + ci.cancel(); + } + + private static ClientboundStatusResponsePacket getOrBuildCachedResponse(ServerStatus current) { + long now = System.nanoTime(); + ClientboundStatusResponsePacket cached = cachedLegacyResponse; + if (cached != null && cachedSourceStatus == current && (now - cachedAtNanos) < STATUS_CACHE_TTL_NS) { + return cached; + } ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version( "26.1.2", LegacyLinkConstants.PROTOCOL_26_1_2 ); ServerStatus remapped = new ServerStatus( - this.status.description(), - this.status.players(), + current.description(), + current.players(), Optional.of(forcedLegacyVersion), - this.status.favicon(), - this.status.enforcesSecureChat() + current.favicon(), + current.enforcesSecureChat() ); - this.connection.send(new ClientboundStatusResponsePacket(remapped)); - ci.cancel(); + ClientboundStatusResponsePacket built = new ClientboundStatusResponsePacket(remapped); + cachedLegacyResponse = built; + cachedSourceStatus = current; + cachedAtNanos = now; + return built; } } From 465324bc1444d234cfb814ff2eea2ff2b91a0a55 Mon Sep 17 00:00:00 2001 From: James Powell Date: Thu, 16 Apr 2026 14:11:17 +0700 Subject: [PATCH 2/4] Refresh prebuilt legacylink jar from status-hardening build. Made-with: Cursor --- prebuilt/legacylink-0.1.1.jar | Bin 1215889 -> 1216825 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/prebuilt/legacylink-0.1.1.jar b/prebuilt/legacylink-0.1.1.jar index c82e5edef3119bf29252aa97c500c979ff4f5bfb..5e08968c0ef002c112e8c2b434e9b1d1b2a5f2ed 100644 GIT binary patch delta 24960 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 delta 24128 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 Date: Thu, 16 Apr 2026 14:25:26 +0700 Subject: [PATCH 3/4] Harden status cache atomicity and sampling window init. Made-with: Cursor --- prebuilt/legacylink-0.1.1.jar | Bin 1216825 -> 1218280 bytes .../handler/LegacyPacketHandler.java | 29 ++++++++++++------ .../legacylink/mixin/StatusPacketMixin.java | 26 ++++++++++------ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/prebuilt/legacylink-0.1.1.jar b/prebuilt/legacylink-0.1.1.jar index 5e08968c0ef002c112e8c2b434e9b1d1b2a5f2ed..12f0458a216b1ff2df8aced63b36b2f620f46155 100644 GIT binary patch delta 26323 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 diff --git a/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java b/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java index 36fc401..2596ac8 100644 --- a/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java +++ b/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java @@ -108,9 +108,18 @@ public class LegacyPacketHandler extends ChannelDuplexHandler { private static final long STATUS_LOG_INTERVAL_NS = 10_000_000_000L; // 10 seconds private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second private static long statusInstallCount; - private static long statusInstallWindowStart = System.nanoTime(); - private static volatile ClientboundStatusResponsePacket cachedStatusResponse; - private static volatile long statusCacheBuiltAt; + private static long statusInstallWindowStart; + private static volatile StatusCache statusCache; + + private static final class StatusCache { + private final ClientboundStatusResponsePacket response; + private final long builtAt; + + private StatusCache(ClientboundStatusResponsePacket response, long builtAt) { + this.response = response; + this.builtAt = builtAt; + } + } private static final Map LEGACY_PARTICLE_FALLBACKS = Map.of( "minecraft:noxious_gas", ParticleTypes.SMOKE, @@ -226,8 +235,11 @@ public static void install(Connection connection, String phase) { } private static synchronized void logStatusInstall() { - statusInstallCount++; long now = System.nanoTime(); + if (statusInstallCount == 0L) { + statusInstallWindowStart = now; + } + statusInstallCount++; long elapsed = now - statusInstallWindowStart; if (elapsed >= STATUS_LOG_INTERVAL_NS) { long elapsedSeconds = elapsed / 1_000_000_000L; @@ -555,9 +567,9 @@ public ClientboundBundlePacket remapBundlePacket(ClientboundBundlePacket bundleP private static ClientboundStatusResponsePacket remapStatusResponse(ClientboundStatusResponsePacket packet) { long now = System.nanoTime(); - ClientboundStatusResponsePacket cached = cachedStatusResponse; - if (cached != null && (now - statusCacheBuiltAt) < STATUS_CACHE_TTL_NS) { - return cached; + StatusCache cached = statusCache; + if (cached != null && (now - cached.builtAt) < STATUS_CACHE_TTL_NS) { + return cached.response; } ServerStatus status = packet.status(); ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version("26.1.2", LegacyLinkConstants.PROTOCOL_26_1_2); @@ -569,8 +581,7 @@ private static ClientboundStatusResponsePacket remapStatusResponse(ClientboundSt status.enforcesSecureChat() ); ClientboundStatusResponsePacket built = new ClientboundStatusResponsePacket(remapped); - cachedStatusResponse = built; - statusCacheBuiltAt = now; + statusCache = new StatusCache(built, now); return built; } diff --git a/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java b/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java index f8781cb..b15f27a 100644 --- a/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java +++ b/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java @@ -21,9 +21,19 @@ public abstract class StatusPacketMixin { private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second - private static volatile ClientboundStatusResponsePacket cachedLegacyResponse; - private static volatile long cachedAtNanos; - private static volatile ServerStatus cachedSourceStatus; + private static volatile LegacyStatusCache cachedStatus; + + private static final class LegacyStatusCache { + private final ClientboundStatusResponsePacket packet; + private final ServerStatus sourceStatus; + private final long timestamp; + + private LegacyStatusCache(ClientboundStatusResponsePacket packet, ServerStatus sourceStatus, long timestamp) { + this.packet = packet; + this.sourceStatus = sourceStatus; + this.timestamp = timestamp; + } + } @Shadow @Final private Connection connection; @Shadow @Final private ServerStatus status; @@ -45,9 +55,9 @@ public abstract class StatusPacketMixin { private static ClientboundStatusResponsePacket getOrBuildCachedResponse(ServerStatus current) { long now = System.nanoTime(); - ClientboundStatusResponsePacket cached = cachedLegacyResponse; - if (cached != null && cachedSourceStatus == current && (now - cachedAtNanos) < STATUS_CACHE_TTL_NS) { - return cached; + LegacyStatusCache cached = cachedStatus; + if (cached != null && cached.sourceStatus == current && (now - cached.timestamp) < STATUS_CACHE_TTL_NS) { + return cached.packet; } ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version( "26.1.2", @@ -61,9 +71,7 @@ private static ClientboundStatusResponsePacket getOrBuildCachedResponse(ServerSt current.enforcesSecureChat() ); ClientboundStatusResponsePacket built = new ClientboundStatusResponsePacket(remapped); - cachedLegacyResponse = built; - cachedSourceStatus = current; - cachedAtNanos = now; + cachedStatus = new LegacyStatusCache(built, current, now); return built; } } From f81238cb76fe91382d6debe345ab0ebe92c3f950 Mon Sep 17 00:00:00 2001 From: James Powell Date: Thu, 16 Apr 2026 14:36:19 +0700 Subject: [PATCH 4/4] Unify legacy status response caching behind a shared manager. Consolidate the mixin and outbound handler status remap caches so both paths use identical TTL and keying behavior from a single utility. Made-with: Cursor --- .../handler/LegacyPacketHandler.java | 33 +------- .../legacylink/mixin/StatusPacketMixin.java | 40 +-------- .../status/LegacyStatusCacheManager.java | 83 +++++++++++++++++++ 3 files changed, 87 insertions(+), 69 deletions(-) create mode 100644 src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java diff --git a/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java b/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java index 2596ac8..55acd43 100644 --- a/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java +++ b/src/main/java/dev/ohno/legacylink/handler/LegacyPacketHandler.java @@ -23,6 +23,7 @@ import dev.ohno.legacylink.mapping.LegacyAttributeWireTable; import dev.ohno.legacylink.mapping.RegistryRemapper; import dev.ohno.legacylink.runtime.LegacyRuntimeContext; +import dev.ohno.legacylink.status.LegacyStatusCacheManager; import dev.ohno.legacylink.telemetry.TranslationStats; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; @@ -65,7 +66,6 @@ import net.minecraft.network.protocol.game.ClientboundUpdateAdvancementsPacket; import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; -import net.minecraft.network.protocol.status.ServerStatus; import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; @@ -91,7 +91,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.lang.reflect.Constructor; import java.util.Set; @@ -106,20 +105,8 @@ public class LegacyPacketHandler extends ChannelDuplexHandler { private static final EntityType LEGACY_SLIME_TYPE = resolveEntityType("minecraft:slime"); private static final long STATUS_LOG_INTERVAL_NS = 10_000_000_000L; // 10 seconds - private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second private static long statusInstallCount; private static long statusInstallWindowStart; - private static volatile StatusCache statusCache; - - private static final class StatusCache { - private final ClientboundStatusResponsePacket response; - private final long builtAt; - - private StatusCache(ClientboundStatusResponsePacket response, long builtAt) { - this.response = response; - this.builtAt = builtAt; - } - } private static final Map LEGACY_PARTICLE_FALLBACKS = Map.of( "minecraft:noxious_gas", ParticleTypes.SMOKE, @@ -566,23 +553,7 @@ public ClientboundBundlePacket remapBundlePacket(ClientboundBundlePacket bundleP } private static ClientboundStatusResponsePacket remapStatusResponse(ClientboundStatusResponsePacket packet) { - long now = System.nanoTime(); - StatusCache cached = statusCache; - if (cached != null && (now - cached.builtAt) < STATUS_CACHE_TTL_NS) { - return cached.response; - } - ServerStatus status = packet.status(); - ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version("26.1.2", LegacyLinkConstants.PROTOCOL_26_1_2); - ServerStatus remapped = new ServerStatus( - status.description(), - status.players(), - Optional.of(forcedLegacyVersion), - status.favicon(), - status.enforcesSecureChat() - ); - ClientboundStatusResponsePacket built = new ClientboundStatusResponsePacket(remapped); - statusCache = new StatusCache(built, now); - return built; + return LegacyStatusCacheManager.getOrBuildForOutboundHandler(packet.status()); } private ClientboundRegistryDataPacket filterRegistryData(ClientboundRegistryDataPacket packet) { diff --git a/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java b/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java index b15f27a..0c82755 100644 --- a/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java +++ b/src/main/java/dev/ohno/legacylink/mixin/StatusPacketMixin.java @@ -1,7 +1,7 @@ package dev.ohno.legacylink.mixin; -import dev.ohno.legacylink.LegacyLinkConstants; import dev.ohno.legacylink.connection.LegacyTracker; +import dev.ohno.legacylink.status.LegacyStatusCacheManager; import net.minecraft.network.Connection; import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; import net.minecraft.network.protocol.status.ServerStatus; @@ -14,27 +14,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Optional; - @Mixin(ServerStatusPacketListenerImpl.class) public abstract class StatusPacketMixin { - private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second - - private static volatile LegacyStatusCache cachedStatus; - - private static final class LegacyStatusCache { - private final ClientboundStatusResponsePacket packet; - private final ServerStatus sourceStatus; - private final long timestamp; - - private LegacyStatusCache(ClientboundStatusResponsePacket packet, ServerStatus sourceStatus, long timestamp) { - this.packet = packet; - this.sourceStatus = sourceStatus; - this.timestamp = timestamp; - } - } - @Shadow @Final private Connection connection; @Shadow @Final private ServerStatus status; @Shadow private boolean hasRequestedStatus; @@ -54,24 +36,6 @@ private LegacyStatusCache(ClientboundStatusResponsePacket packet, ServerStatus s } private static ClientboundStatusResponsePacket getOrBuildCachedResponse(ServerStatus current) { - long now = System.nanoTime(); - LegacyStatusCache cached = cachedStatus; - if (cached != null && cached.sourceStatus == current && (now - cached.timestamp) < STATUS_CACHE_TTL_NS) { - return cached.packet; - } - ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version( - "26.1.2", - LegacyLinkConstants.PROTOCOL_26_1_2 - ); - ServerStatus remapped = new ServerStatus( - current.description(), - current.players(), - Optional.of(forcedLegacyVersion), - current.favicon(), - current.enforcesSecureChat() - ); - ClientboundStatusResponsePacket built = new ClientboundStatusResponsePacket(remapped); - cachedStatus = new LegacyStatusCache(built, current, now); - return built; + return LegacyStatusCacheManager.getOrBuildForStatusListener(current); } } diff --git a/src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java b/src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java new file mode 100644 index 0000000..5c5cb8b --- /dev/null +++ b/src/main/java/dev/ohno/legacylink/status/LegacyStatusCacheManager.java @@ -0,0 +1,83 @@ +package dev.ohno.legacylink.status; + +import dev.ohno.legacylink.LegacyLinkConstants; +import net.minecraft.network.protocol.status.ClientboundStatusResponsePacket; +import net.minecraft.network.protocol.status.ServerStatus; + +import java.util.Optional; + +/** + * Centralized status remap cache so all status pathways share identical TTL and keying rules. + */ +public final class LegacyStatusCacheManager { + private static final long STATUS_CACHE_TTL_NS = 1_000_000_000L; // 1 second + + private static volatile CacheEntry listenerCache; + private static volatile CacheEntry outboundHandlerCache; + + private LegacyStatusCacheManager() {} + + public static ClientboundStatusResponsePacket getOrBuildForStatusListener(ServerStatus current) { + return getOrBuild(current, CacheScope.LISTENER); + } + + public static ClientboundStatusResponsePacket getOrBuildForOutboundHandler(ServerStatus current) { + return getOrBuild(current, CacheScope.OUTBOUND_HANDLER); + } + + private static ClientboundStatusResponsePacket getOrBuild(ServerStatus current, CacheScope scope) { + long now = System.nanoTime(); + CacheEntry cached = read(scope); + if (cached != null && cached.sourceStatus == current && (now - cached.builtAtNanos) < STATUS_CACHE_TTL_NS) { + return cached.response; + } + + ClientboundStatusResponsePacket built = buildLegacyStatusResponse(current); + write(scope, new CacheEntry(built, current, now)); + return built; + } + + private static CacheEntry read(CacheScope scope) { + return scope == CacheScope.LISTENER ? listenerCache : outboundHandlerCache; + } + + private static void write(CacheScope scope, CacheEntry entry) { + if (scope == CacheScope.LISTENER) { + listenerCache = entry; + } else { + outboundHandlerCache = entry; + } + } + + private static ClientboundStatusResponsePacket buildLegacyStatusResponse(ServerStatus current) { + ServerStatus.Version forcedLegacyVersion = new ServerStatus.Version( + "26.1.2", + LegacyLinkConstants.PROTOCOL_26_1_2 + ); + ServerStatus remapped = new ServerStatus( + current.description(), + current.players(), + Optional.of(forcedLegacyVersion), + current.favicon(), + current.enforcesSecureChat() + ); + return new ClientboundStatusResponsePacket(remapped); + } + + private enum CacheScope { + LISTENER, + OUTBOUND_HANDLER + } + + private static final class CacheEntry { + private final ClientboundStatusResponsePacket response; + private final ServerStatus sourceStatus; + private final long builtAtNanos; + + private CacheEntry(ClientboundStatusResponsePacket response, ServerStatus sourceStatus, long builtAtNanos) { + this.response = response; + this.sourceStatus = sourceStatus; + this.builtAtNanos = builtAtNanos; + } + } +}