Tags
Creators
Details
0.4.3-beta
Compatibility
Changes
SerialCraft v0.4.3-beta โ Release notes
Minecraft 1.21.11 ยท Fabric
This is the release with the most internal work in the project so far. A good part of it is invisible while playing: networking, performance and architecture fixes that had to land before the mod could be recommended on a server.
โ ๏ธ Before you update
0.3.x sketches will not work unchanged. The protocol changed in two places: the value scale and the direction of the Wi-Fi connection. See How to migrate for what to touch.
๐ด Breaking changes
1. Unified 0-255 scale
Output used to send 0-255 while input was clamped to 0-15. The protocol was asymmetric: a 200 sent by the board came back as 15.
The wire now speaks 0-255 in both directions. Conversion to redstone's 0-15 scale is done by the mod.
2. Digital mode sends 255, not 1
In digital mode a powered block used to send 1. That forced your firmware to know how the block was configured inside the game: analogWrite(pin, 1) is a 0.4% duty cycle, i.e. an LED that looks dead.
It now sends 255, so a single analogWrite(pin, value) covers both digital and analog signals. In the other direction, any incoming value of 1 or greater is treated as fully on.
3. Wi-Fi changed direction and port
The board used to run a server on port 8080 and Minecraft connected to it. It is now the other way around: the mod is the server on port 25585, and the board connects as a client, sending a pairing token as its first line.
4. An empty Target Data no longer accepts everything
A block with a blank identifier used to accept any message containing :. An empty identifier now means the block ignores everything. There is no wildcard.
๐ Notable fixes
Boards no longer vanish after a server restart
This was the worst bug in 0.3.x. The active-board registry was only populated when a block was placed by hand. After a server restart the registry started empty and nothing refilled it: every board loaded from disk was invisible โ empty list, input mode dead โ until each block was placed again, one by one.
Boards are now indexed as they load from the world, per dimension and per owner.
That same registry also never released destroyed boards: one blown up by TNT, pushed by a piston or removed with /fill stayed in it forever, and with it a live reference to its dimension. Fixed.
Other functional bugs
| Bug | What it did |
|---|---|
| The block model wasn't updated on serial input | An incoming signal worked, but the block never showed it |
Missing getDirectSignal |
A block in output mode against a solid block powered nothing |
| The top face was unreachable | Configurable through internal logic, but impossible to click |
A message like "cmd:" threw an exception |
Swallowed by an empty catch that also hid every other error |
| Thread self-join on disconnect | The reader thread waited on itself when closing after an error |
| Thread leak in the UI | A home-screen timer was only cancelled on one of the exit paths |
| Phantom connections | Connection state had three separate owners that could disagree |
| Focus lost while typing | The interface rebuilt itself on every server reply |
๐ Security
Seven things that were open and no longer are:
| Issue | Real-world risk |
|---|---|
| Wi-Fi server with no authentication | Anyone on the same network (classroom, cafรฉ, coworking space) could telnet in and drive your redstone |
| Forced chunk loading | Network handlers used client-supplied coordinates unvalidated; random positions made the server generate terrain without limit |
| Packets with no ownership check | Any player could disable or reconfigure another player's boards |
| No rate limiting | A Serial.println() inside loop() at 115200 baud produces thousands of packets per second. No modified client needed โ a badly written sketch was enough |
| Unbounded strings in NBT | Identifiers of up to 32,767 characters, persisted and replicated to every client |
| Unbounded reads | A peer that never sent a newline exhausted client memory |
| Ownerless board = public | Boards placed by command or dispenser were open to everyone |
Now: mandatory token, private addresses only, one board per session, lines capped at 256 characters, position and distance validation on every packet, a 40 messages/s per-player limit (burst of 80), identifiers capped at 32 characters, and ownerless boards are claimed by the first player to operate them.
The Wi-Fi channel is still plaintext. The token prevents casual access inside your own network, but it is not encryption. It is fine for a home or classroom network; do not forward port 25585 on your router.
โก Performance
- Block states cut from 17,496 to 2,916 (six times fewer) by removing two properties that were used neither in code nor in the models.
- Per-tick cost fixed. The output check was always true, so every board ran six redstone queries twenty times per second. With a hundred boards that is 12,000 queries per second to discover nothing had changed. It now runs every 2 ticks, and only when there is something to send.
- Output deduplication. A lever held on sends one message, not twenty per second.
- Message queue swapped for a structure that doesn't copy the whole array on every message.
๐จ Interface
- Reorganised into independent pages. Previously, adding a tab meant touching four separate
switchblocks, and forgetting one caused several leaks. - Correct text clipping: buttons no longer overflow with long translations.
- Badges measure the text inside them; the console clips to the available width.
- Text-field focus is no longer lost while typing.
- Fixed a race in the power button that could leave it in an inconsistent state.
- Removed the latency meter: it used a function that requires administrator privileges on Linux and macOS, and its fallback timed opening a fresh connection rather than actual latency.
Limits that remain
Worth stating plainly:
- The board list has no scrolling. Past roughly eight boards, the rest fall off screen. That is the mod's practical ceiling today.
- The UI doesn't adapt to very small resolutions at maximum GUI scale.
- There is no confirmation when disconnecting.
- The token can't be copied to the clipboard.
๐ Localisation
The Spain, Mexico and Argentina Spanish files were byte-for-byte identical except for one word. That is not localisation.
On top of that, around forty Spanish strings were hardcoded in the Java source โ so the interface stayed in Spanish even with the game set to English โ plus roughly twenty-five dead keys from screens that no longer exist, missing keybinding entries (the controls menu showed the raw identifier), and several messages passing whole sentences as if they were translation keys.
Now: 121 keys with verified parity across five locales โ English, Spanish for Spain, for Mexico (American lexicon), for Peru (new) and for Argentina (with real voseo).
Emoji that Minecraft's default font cannot render were also removed.
๐ Documentation
The guide and protocol reference were labelled 0.4.3 but described 0.3.x behaviour. Both rewritten from scratch in Spanish and English, with new sections on common failures, known limits and multiplayer scope.
New: examples and test routine โ three builds of the same circuit (a potentiometer and an LED) for Arduino Uno R3 over USB, ESP32 over Wi-Fi, and Arduino Uno Q with Bridge and Python. Each includes pin-by-pin wiring, in-game setup, and a five-step routine where every step isolates a different layer.
There are also ready-made prompts for generating the wiring diagrams with an image AI.
๐๏ธ Internal
For anyone reading the source:
- Magic ints (
ioMode == 1,signalType == 0) replaced with enums whose network codec degrades invalid values instead of corrupting the block. - Duplication removed: the local-IP calculation existed twice and had already diverged; border drawing three times; card drawing three times with shadows at different offsets โ hence the misaligned edge; badges five times in a single screen.
- Colours repeated across five files centralised into one theme.
- Connection state now has a single source of truth.
- Removed the example mixins, a config file that was loaded and saved but whose fields were never read, and a variable that decided read speed but was never written to.
- Enums are persisted by name rather than position, so reordering them can't break saved worlds.
๐ง How to migrate from 0.3.x
In your sketch
- Drop the comparisons against
1. If you hadif (value == 1) digitalWrite(pin, HIGH);, replace it with an unconditionalanalogWrite(pin, value);. It works the same in digital and analog. - Check your send scale. If you were sending 0-15, send 0-255 now. The mapping depends on your ADC:
map(raw, 0, 1023, 0, 255)for 10-bit,map(raw, 0, 4095, 0, 255)for 12-bit. - Send changes only. Add hysteresis. Above 40 messages per second the mod drops the excess silently.
If you were using Wi-Fi
Your board is no longer the server. Now:
- In game: Laptop โ Home โ Start Wi-Fi server. Note the IP, the port and the token.
- In your sketch, connect as a client to that IP on port 25585.
- Send the token as your first line, newline-terminated.
- Wait for
OK. If you getERR TOKEN, the token is wrong or another board is already connected.
There is a complete ESP32 example with the handshake already implemented.
In your saved worlds
Boards placed under 0.3.x load normally. It is worth opening the Laptop to check they all appear in the list: if one had stopped responding after a restart under 0.3.x, it should come back now.
โ ๏ธ A note on scope
There is no mode where the server owns the hardware. The serial port lives in each player's client, so the model is "every player drives their own boards from their own PC". That is an architectural decision, not an oversight: changing it would mean moving the whole serial layer to the server side, with a port allowlist and admin controls.
With this release's fixes, a dedicated server is viable. Reasonable figures: 10-50 boards per player, several hundred per server, and roughly 2 KB/s of traffic per active board.
๐ Reporting problems
Open an issue stating the mod version, the board you use, and whether the connection is USB or Wi-Fi.
Optional dependencies
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:hLV9sPrg:xckfGXh4"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:hLV9sPrg:xckfGXh4"
}

