-
Notifications
You must be signed in to change notification settings - Fork 2
Guide 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.
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.
| 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.
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
movesor adds species does move battle outcomes — declare"affects_link": true. - An overhaul that only touches UI, music, and text can declare
"affects_link": falseto keep vanilla-compatible link play.
Declare false while writing into a link-relevant registry (pokemon,
moves, type_chart, statuses, move_effects —
src/mods/Manifest.lua LINK_REGISTRIES) and the loader logs an
attributed warning: your claim and your writes disagree.
- 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_peercompat with unmodified builds. - Extra per-mon data that must survive a trade belongs in the
link_fieldsregistry —{ rev, pack?, unpack? }per field, where onlyreventers the digest; bump it when the codec's meaning changes. - Two peers must run the same ordering rules:
battle.turn_orderwraps inside link battles too, so a mod that changes it must be installed on both sides (the fingerprint enforces this whenaffects_linkis true).
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.
Engine 1.0.0 · mod API 2 · repository · Discord
This project ships no ROM data. All game content is decoded on the player's machine from their own verified Pokemon Red ROM; mods ship recipes and original assets, never extracted content.
Start here
Concepts
Tutorials
- The ladder
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Reference
Guides
Playing