protocol: hello carries five fields; the released client reads no serverName
Build / build (push) Successful in 1m18s
Build / build (push) Successful in 1m18s
Upstream's git HEAD appends serverName to server_installed, but the shipped 1.0.4 client (fabric-26.2) decodes exactly version/lastGen/interval/mode/ ticks and vanilla disconnects the player with "8 bytes extra" on the first hello. Verified with javap on the release jar; the other three codecs match. Drops the server-name option (a leftover key now only warns). Claude-Session: https://claude.ai/code/session_011FePLXwBsCGLTzaSkk1Z6V
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
group = lv.janhouse
|
||||
version = 0.1.0
|
||||
version = 0.1.1
|
||||
|
||||
# Paper dev bundle (Mojang-mapped server + API) the plugin compiles against.
|
||||
# Must match the server it is deployed on: Paper 26.2 on JDK 25. The renderer
|
||||
|
||||
@@ -34,8 +34,6 @@ public final class Settings {
|
||||
public final int clientPollIntervalTicks;
|
||||
public final int helloDelayTicks;
|
||||
|
||||
public final String serverName;
|
||||
|
||||
public final WorldSettings defaultWorld;
|
||||
public final Map<String, WorldSettings> worlds;
|
||||
|
||||
@@ -66,7 +64,9 @@ public final class Settings {
|
||||
clientPollIntervalTicks = clamp(c.getInt("sync.client-poll-interval-ticks", 6000), 1200, 72000, "sync.client-poll-interval-ticks", warn);
|
||||
helloDelayTicks = clamp(c.getInt("sync.hello-delay-ticks", 100), 1, 1200, "sync.hello-delay-ticks", warn);
|
||||
|
||||
serverName = c.getString("server-name", "");
|
||||
if (c.contains("server-name")) {
|
||||
warn.accept("server-name is ignored: the released MapSyncer client cannot read that hello field.");
|
||||
}
|
||||
|
||||
ConfigurationSection ws = c.getConfigurationSection("worlds");
|
||||
WorldSettings def = new WorldSettings(true, TrackedWorld.Layers.AUTO);
|
||||
|
||||
@@ -74,16 +74,20 @@ public final class Protocol {
|
||||
|
||||
// -------------------------------------------------------------- encoders
|
||||
|
||||
/**
|
||||
* Five fields, no more. Upstream's git HEAD appends a sixth (serverName), but
|
||||
* the released 1.0.4 client reads exactly five and vanilla disconnects on
|
||||
* "8 bytes extra" if anything follows — verified against the shipped jar.
|
||||
*/
|
||||
public static byte[] encodeServerInstalled(String version, long lastGenerationTimestamp,
|
||||
int autoSyncIntervalMinutes, UpdateMode mode,
|
||||
int incrementalUpdateIntervalTicks, String serverName) {
|
||||
int incrementalUpdateIntervalTicks) {
|
||||
return new PacketWriter(64)
|
||||
.writeUtf(version)
|
||||
.writeLong(lastGenerationTimestamp)
|
||||
.writeInt(autoSyncIntervalMinutes)
|
||||
.writeByte(mode.ordinal())
|
||||
.writeInt(incrementalUpdateIntervalTicks)
|
||||
.writeUtf(serverName == null ? "" : serverName)
|
||||
.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ public final class SyncService implements PluginMessageListener, Listener {
|
||||
int minutes = Math.max(1, ticks / 20 / 60);
|
||||
byte[] payload = Protocol.encodeServerInstalled(
|
||||
"mapsyncer-paper/" + plugin.getPluginMeta().getVersion(),
|
||||
lastGen, minutes, Protocol.UpdateMode.TICK, ticks, settings.serverName);
|
||||
lastGen, minutes, Protocol.UpdateMode.TICK, ticks);
|
||||
player.sendPluginMessage(plugin, Protocol.SERVER_INSTALLED, payload);
|
||||
s.helloSent = true;
|
||||
helloCount.incrementAndGet();
|
||||
|
||||
@@ -58,10 +58,6 @@ sync:
|
||||
# cache, otherwise it forgets what it already has and re-syncs on every join.
|
||||
hello-delay-ticks: 100
|
||||
|
||||
# Optional stable name sent to clients. The client mod uses it to recognise this
|
||||
# server when it is reached under a different address. Leave empty to disable.
|
||||
server-name: ""
|
||||
|
||||
# Per-world settings. Keys are Bukkit world names. Anything not listed uses
|
||||
# "default". `layers` controls what is rendered:
|
||||
# auto surface for worlds with a sky, cave layers for worlds with a ceiling
|
||||
|
||||
@@ -138,6 +138,20 @@ class ProtocolTest {
|
||||
assertFalse(Protocol.split(0, 0, "null", new byte[100], 1, Protocol.SURFACE_LAYER).get(0).isSplit());
|
||||
}
|
||||
|
||||
@Test
|
||||
void helloHasExactlyFiveFields() {
|
||||
// The released 1.0.4 client reads utf, long, int, byte, int and nothing
|
||||
// else; a trailing byte disconnects the player.
|
||||
byte[] hello = Protocol.encodeServerInstalled("v", 123L, 5, Protocol.UpdateMode.TICK, 6000);
|
||||
PacketReader r = new PacketReader(hello);
|
||||
assertEquals("v", r.readUtf());
|
||||
assertEquals(123L, r.readLong());
|
||||
assertEquals(5, r.readInt());
|
||||
assertEquals(1, r.readByte());
|
||||
assertEquals(6000, r.readInt());
|
||||
assertEquals(0, r.readableBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
void hashValidity() {
|
||||
assertTrue(Protocol.isValidHash("a1b2c3d4"));
|
||||
|
||||
Reference in New Issue
Block a user