promotional bannermobile promotional banner

Radio Link

A radio mod that works with Simple Voice Chat.
Back to Files

radiolink-2.3.0.jar

File nameradiolink-2.3.0.jar
Uploader
Giak_88Giak_88
Uploaded
Sep 6, 2026
Downloads
14
Size
148.5 KB
Mod Loaders
Fabric
File ID
8821415
Type
R
Release
Supported game versions
  • 1.20.1

Curse Maven Snippet

Fabric

modImplementation "curse.maven:radio-link-1637885:8821415"

Learn more about Curse Maven

What's new

Changelog

2.3.0 — 2026-09-06

Repeaters finally bridge two distant players

  • A repeater no longer vanishes when nobody is nearby. Until now a relay existed, for the router, only while its block entity was being ticked — that is, only while its chunk was loaded. The result was the worst possible paradox: a station built halfway between two bases worked when you stood next to it (and did not need it) and disappeared as soon as you walked away, which is the only moment it is useful. Two players at the ends of a chain never load the chunks in the middle, so the bridge never formed. Repeaters are now stored in the world save (dimension, position, antenna height — three numbers each), exactly like missed calls. They survive chunk unload and server restart, and a chain of them relays between players who could never hear each other directly. This costs nothing at runtime: the router reads an in-memory list either way. It is a change of lifetime, not of workload — and it actually removes the old "re-register every second" write. Removal now happens only when the block is genuinely broken or replaced. A slow self-healing pass (every 10 seconds) drops any entry whose chunk is loaded but no longer holds a station, so a world edited without the mod repairs itself.
  • Fixed a real routing bug. The Dijkstra priority queue was ordered by a comparator that read an array mutated after insertion, so the heap invariant could break: poll() could return a node that was not the minimum, and it was then closed for good with a non-optimal value. Valid repeater chains could be scored worse than they were, or discarded. The metric now travels inside the queue entry (lazy-deletion Dijkstra).

Text messages are no longer confined to your channel

  • Anything sent on AM, FM or un-keyed DMR is read by everyone with a powered radio, on any channel and any modulation. The range is still the sender's, so an AM message travels far and a DMR one barely at all, and the prefix keeps showing which channel it came from ([AM2] Name: text).
  • Encrypted DMR stays a closed group. Only the same key reads it. Someone tuned to the same DMR channel with the wrong key (or none) still gets the fully scrambled text — they are on the frequency, they just cannot decode it — while anyone on another channel sees nothing at all. The group itself keeps reading everybody else's open messages.
  • New server option openTextChannels (default true) to go back to text being confined to its channel, like the voice. An encrypted group is never open, whatever it is set to.
  • The voice is unchanged: it stays per modulation and per channel.
  • This adds no per-tick cost: routes for a message are computed when someone presses enter, not five times a second.

Smaller things

  • "Mute nearby radios", a new switch in the radio settings (off by default). With it on, the speakers of radios other players are holding never reach you — neither voice nor ringtones — while your own radio keeps working normally. It is a listener's choice, so it is applied by filtering listeners on the speaker's channel, and it keeps working even with your own radio switched off. Different from the "Radio Speaker" slider in Simple Voice Chat: that one turns the volume down, this one turns the thing off.
  • A small number next to the PLR bars, in the HUD and in the radio GUI: how many people on your channel you are reaching right now — the answer to "if I press transmit, who hears me". Green when at least one, grey when nobody. It costs nothing: it comes out of the same routing pass that draws the bars.
  • The "i" screen documents the new text rules, the reached counter, and the fact that repeaters keep relaying when nobody is around.

Not included

The performance work from the audit (radiolink-audit-prestazioni.md) is deliberately not applied: link caching, reusing routes for the signal bars, dropping the per-sample BlockPos allocation and the per-tick raycast budget are all still on the table, waiting for a decision. The two changes above that touch the router were made as part of the repeater bridging request, not as optimisations — neither of them makes the mod faster or slower.

2.2.0 — 2026-08-17

  • Every leg of a link now uses the BEST range of its two ends. A radio link is reciprocal: a repeater with a tall antenna hears as far as it talks. Until now the router only applied the transmitting node's antenna bonus, so a handheld radio calling a repeater was computed at the plain handheld range (multiplier 1.0) and the antenna helped only on the way back — an asymmetry that does not exist in reality and that made repeaters much harder to reach than the RPT bars suggested. Now each leg is evaluated at base range × max(multiplier of the two ends):

    • player → repeater: the repeater's antenna counts;
    • repeater → repeater: the taller of the two sets the leg;
    • repeater → player: unchanged (already the repeater's antenna).

    Because voice, text messages and paging all go through the same router, they all inherit the new rule at once — and the router now agrees with the RPT signal bars, which already worked this way.

  • The "i" screen scrolls with the mouse wheel and can no longer grow past the bottom of the screen at high GUI scales (the "Done" button was getting cut off). It also explains the reciprocal-range rule.

2.1.0 — 2026-08-03

  • Encrypted DMR now scrambles the text too. Until now a text message sent on an encrypted DMR channel simply never reached anyone without the key. Now it arrives fully scrambled — the written counterpart of the buzzer you hear instead of the voice — using the same glitch alphabet as a failing link, with spaces preserved so it still reads as a message you are not allowed to read. "Mute undecodable" hides the garbage as well as the buzzer.
  • The pager has its own volume slider: paging tones ringing out of someone else's handheld radio now travel on their own audio channel, so Simple Voice Chat shows a third slider, "Other Radios' Pager", next to "Radio" and "Radio Speaker". They are the most intrusive sound in the mod and deserved a separate control.
  • The "i" screen in the radio GUI explains the DMR encryption behaviour.

Verified as already present (no change needed)

  • Slider for the voice coming out of other players' radios: the "Radio Speaker" category, in Simple Voice Chat's volume menu (since 1.4.0).
  • Paging a specific player: the field next to CALL — only that player is rung.
  • Missed call notices delivered only once you are back in range of a player or a repeater (missedCallGraceTicks: 0 by default).

2.0.4 — 2026-08-03

  • Build fix: removed the onChunkUnloaded() override in RepeaterStationBlockEntity. That hook is a Forge addition to BlockEntity and does not exist in vanilla, so it does not exist on Fabric either. Nothing is lost: vanilla already calls setRemoved() on every block entity of a chunk when the chunk unloads, and that is where the repeater unregisters itself.
  • tools/check-sources.py now also greps for Forge-only APIs (onChunkUnloaded, getCapability, DistExecutor, ForgeConfigSpec, ...). The offline javac check cannot see this class of error on its own: with the Minecraft classes absent, every @Override fails, so "does not override" has to be filtered out wholesale.

2.0.3 — 2026-08-03

  • Build fix (the real one): every @Nullable came from javax.annotation, which Forge provided transitively and Fabric does not — 26 compile errors across 10 files. Now org.jetbrains.annotations.Nullable, the Fabric standard, with an explicit compileOnly dependency so the build never relies on it arriving by chance.
  • Added tools/check-sources.py, the offline sanity check used while porting. It compiles the sources without the Minecraft/Fabric jars and reports only genuine problems — in particular any import from a package that is not supposed to be missing, which is exactly what slipped through in 2.0.2. Not a substitute for a real build, just a fast first filter.

2.0.2 — 2026-08-03

  • Build fix: dropped EditBox.setHint() on the call-target field. It was the one API in the port I could not confirm against the 1.20.1 javadocs, so the placeholder text is now drawn by hand instead. Same look, no risk.

2.0.1 — 2026-08-03

  • Build fix: the Gradle wrapper was still the one inherited from the Forge project (8.1.1), which Fabric Loom 1.6 refuses to run on. Now Gradle 8.8. No gameplay change.

2.0.0 — 2026-08-03 — Fabric port

The mod now runs on Fabric (Minecraft 1.20.1). This is a port of the Forge 1.4.1 codebase, not a rewrite: the radio physics, the DSP, the Simple Voice Chat integration and the whole GUI are the same code. Only the loader-specific layer changed.

Ported

  • Entrypoints: ModInitializer / ClientModInitializer, plus the voicechat entrypoint in fabric.mod.json (Fabric registers the Simple Voice Chat plugin that way instead of by annotation).
  • Registration through the vanilla registries + FabricItemGroup and FabricBlockEntityTypeBuilder.
  • Networking: one channel per packet via ServerPlayNetworking / ClientPlayNetworking, with the same payloads as before. The client half lives in its own class, because on Fabric a dedicated server has no client classes at all.
  • Events: ServerTickEvents, ServerLifecycleEvents, ServerPlayConnectionEvents.JOIN, and ServerMessageEvents.ALLOW_CHAT_MESSAGE for chat blocking (commands still never pass through it).
  • HUD: HudRenderCallback instead of Forge overlays.
  • Config moved to config/radiolink.json (plain JSON, created on first start, missing fields keep their defaults). Fabric has no per-world server config, so it is a single file for the whole installation.
  • Obstacle materials use RadioLink's own block tags (radiolink:rf_transparent, radiolink:rf_dense) instead of the Forge ones.
  • Built with loom.officialMojangMappings(), which is why the game code reads exactly like the Forge version.

New in 2.0.0

  • Private calls: type a player name in the field next to CALL and only that player is rung — everyone else on the channel hears nothing, like the individual call of a real DMR radio. Leave it empty for the usual group call.
  • Missed calls now behave properly: the notice is delivered only when you are genuinely back in coverage of another player or a repeater. The old "deliver anyway after a while" fallback is off by default (missedCallGraceTicks: 0) and can be re-enabled by setting a tick count.
  • The pager tone travels through the normal radio engine, so it leaks out of the recipients' speakers for bystanders to hear, exactly like voice.
  • The "Radio Speaker" volume slider in the Simple Voice Chat menu (added in 1.4.0, made reliable in 1.4.1) controls how loud other players' handheld radios are for you.
  • The "i" screen in the radio GUI now also explains group vs private calls.

Not included

The Forge line stays at 1.4.1. This is a separate project: the two do not share a build, so a change made here has to be ported by hand if you want it on Forge as well.

This mod has no additional files