Skip to content

Guide Link Compatibility

bryanthaboi edited this page Jul 19, 2026 · 1 revision

Link compatibility

How two connected games decide whether they can battle and trade, and how to keep a mod link-safe. Implementation: src/link/Fingerprint.lua, src/link/Handshake.lua.

The fingerprint

On entering link play, each side digests its link surface: the merged pokemon, moves, type chart, statuses, and move_effects records (over stable allowlisted fields), the link-relevant constants, any registered link_fields, and the { id, version } of every mod whose affects_link is true. Identical surfaces produce identical digests — regardless of how mods produced them.

The verdict

Verdict When Battle Trade
full fingerprints match yes yes
vanilla_peer old (v1) build on the far side, this side unmodified yes yes
subset both v2, fingerprints differ no strict-vanilla subset, negotiated
refused v1 peer that our mods would corrupt, or an engine mismatch no no

The subset trade path admits only mons both sides rebuild identically — per-record digests agree species by species — so a modded game and a lightly-modded friend can still trade the vanilla 151 without risk. A mid-battle divergence (the last line of defense) raises link.desync with the failing component and ends the battle as a draw instead of letting the two screens drift apart. Never desync silently is the rule.

The manifest switch

affects_link defaults by profile: false for content, true for overhaul and total_conversion. Set it explicitly when the default is wrong:

  • A "content" mod that rebalances moves or adds species does move battle outcomes — declare "affects_link": true.
  • An overhaul that only touches UI, music, and text can declare "affects_link": false to keep vanilla-compatible link play.

Declare false while writing into a link-relevant registry (pokemon, moves, type_chart, statuses, move_effectssrc/mods/Manifest.lua LINK_REGISTRIES) and the loader logs an attributed warning: your claim and your writes disagree.

Keeping a content mod link-safe

  • Prefer additions over changes: a new species you never trade does not block the vanilla subset.
  • Keep battle-relevant records untouched if you want vanilla_peer compat with unmodified builds.
  • Extra per-mon data that must survive a trade belongs in the link_fields registry — { rev, pack?, unpack? } per field, where only rev enters the digest; bump it when the codec's meaning changes.
  • Two peers must run the same ordering rules: battle.turn_order wraps inside link battles too, so a mod that changes it must be installed on both sides (the fingerprint enforces this when affects_link is true).

Observing link play

Events: link.connected ({ role, remote = { name, mode, mods, fingerprint } }), link.ended, link.desync, trade.completed, pokemon.received. The link.fingerprint hook wraps digest computation itself — for tooling, not for lying to your peer.

Player-facing link setup: Link Play.

Clone this wiki locally