Skip to content

Dev869/awdl-lan

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AWDL LAN

Minecraft multiplayer between two Macs with no router, no network, and no configuration, carried over AWDL — the peer-to-peer Wi-Fi radio behind AirDrop and Sidecar.

Minecraft speaks plain TCP, so the whole problem reduces to a proxy:

[MC host] ──127.0.0.1:25565──> [helper] ≈≈AWDL≈≈> [helper] ──127.0.0.1:PORT──> [MC client]

A small Swift binary owns the radio via Network.framework. The Java mod never sees anything but a loopback port, which is why it needs no JNI, no native bindings, and no Bluetooth stack.

Minecraft 26.1–26.2, Fabric, client-side, macOS only.

Build and package

./package.sh          # tests both halves, builds, verifies, writes dist/

That is the only command needed for a release. It runs both test suites, then checks the packaged jar rather than trusting the build: required resources present, embedded binary byte-identical to the one just compiled, signature still valid, and the binary still executable after the jar round trip.

Upload dist/awdl-lan-<version>.jar. Project page copy is in MODRINTH.md.

Layout

Path What
helper/ Swift binary. Owns AWDL, speaks JSON lines on stdio.
mod/ Fabric mod. Process management and UI.
docs/DESIGN.md Design, including revisions and what was measured.

Testing

helper/test.sh        # full relay path on one machine, no second Mac
mod/test.sh           # transport classes under plain javac, no Minecraft
cd mod && gradle runClient

helper/twomac.sh runs the two-Mac transport test. mod/test.sh enforces that HelperProcess and HelperBinary never import Minecraft or Fabric. That boundary is what keeps them testable in seconds, and it broke silently once already.

Design notes

Peers are surfaced as ordinary LanServer entries pointing at a loopback tunnel, so vanilla renders, pings, and joins them unaided. One @ModifyVariable is the entire list integration.

They are dialled eagerly on discovery, because an entry's address must be real before it can be clicked. This also hides AWDL's slow first association.

Discovery is hold-counted, not started and stopped. Screen handoff fires the old screen's removed() before the new screen's init(), so a plain stop/start blanks the list on every navigation.

Minecraft went unobfuscated at 26.1, which is why there is no mappings line in build.gradle and why the mixins reference real names. It is also why 1.21.x is out of reach without a separate mappings build.

Limits

macOS only, by construction. Roughly 2–4 players before Apple's peer-to-peer protocol degrades. Traffic is unencrypted, matching vanilla Open to LAN.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages