Endlink v0.2.0
Custom content — items, entities, blocks and the resource packs behind them — now survives a backend
switch. Before this release it did not, and no amount of correct pack configuration fixed it.
Bedrock reads a client's resource pack stack, item registry, entity identifier list and custom block
definitions once, at level init. A seamless switch deliberately does not re-run level init, so a
client kept whatever the first backend it joined had told it: another backend's custom items drew
arbitrary vanilla textures, and its custom entities and blocks were invisible — solid and clickable,
but not drawn.
Cross-backend registries
Every client is now given the combined item and entity registries of all backends at login, and each
backend's own network ids are translated to and from that union as packets pass through. The
translation is free per packet: it rides on the codec's existing decode step rather than rewriting
item ids packet by packet.
Custom blocks need no id translation — a modern backend hashes a block's runtime id from its state,
so the number is the same everywhere — but they do need their definitions, which are merged in the
same way. A backend that numbers blocks by palette order instead of hashing them is reported, since
that case cannot be corrected by a proxy.
Each backend's registries are learned the first time anyone visits it and cached in
cache/backend-palettes.nbt, so later logins account for backends nobody has been to this run. After
a backend's addons change, the first player to go there sees the old registry until they rejoin; that
is logged, not silent.
Controlled by crossBackendPalette, on by default.
Resource packs
- Unpacked pack folders are loaded, not only
.mcpackfiles. A folder holdingmanifest.jsonis
zipped in memory at startup, reproducibly, so an unchanged folder keeps its hash across restarts
and clients do not redownload it. - Backend packs are cached and served by the proxy (
resourcePacks.cacheBackendPacks). The proxy
keeps a copy of the bytes it sees a client download, and downloads a switched-to backend's packs
itself — nobody else ever asks that backend for them. Later logins include them, which is what
makes a switched-to backend's content render. Newest version wins; a pack placed in
resourcePacks.dirby hand wins a tie. Encrypted packs cannot be cached and are named in the log.
Joining
security.rateLimit.packetLimit now defaults to 500 rather than RakNet's 120. A single Bedrock
login is a burst of MTU-sized fragments carrying the identity chain and skin; over loopback or a LAN
they land inside one 10ms tick and exceed 120. That blocked the address for ten seconds, stalled the
handshake into disconnect.timeout, and repeated on every retry — a player in that state could not
join at all. A blocked address now also names itself and the setting that blocked it in the log.
Resource pack chunks are 100KB rather than 1MB, so the acknowledgements a client sends back while
downloading stay inside that budget.
Upgrading
Drop in the new jar. No config changes are required — the new settings default to on, and an existing
config.properties keeps working. Two things worth doing:
- If your
config.propertiessetssecurity.rateLimit.packetLimit=120, raise it; the new default
only applies to newly generated configs. - The caches start empty, so the first visit to each backend is what teaches the proxy. Visit each
backend once and rejoin, and everything is in place from then on.