
I downloaded XtoXray from Modrinth because I wanted a simple xray mod for a 1.21.5 Fabric instance. It worked. Then I opened the title screen and saw a rotating promo card in the corner.
One slide pushed the mod’s Modrinth page. The other asked me to subscribe to a YouTube channel. The bottom left corner had an X To Xray watermark with the mod version.
I could ignore that. Then I joined a world and chat printed this:
[System] [CHAT] Support X To Xray By Joining The Discord Server And Subscribing On Youtube! [Discord] [YouTube]
The chat message was the part that made me open the jar. A Discord link in the mod description is normal. A clickable ad in my chat box every time I load a world is not.
First look at the jar
The jar is a normal Fabric mod. fabric.mod.json lists the main entrypoint and the client entrypoint:
"entrypoints": { "main": ["com.xtoxray.XtoXray"], "client": ["com.xtoxray.client.XrayToggleHandler"]}The mixin configs also give away where the title screen code lives. There are three variants, one for each Minecraft range:
xtoxray.title_0_5.mixins.jsonxtoxray.title_6_8.mixins.jsonxtoxray.title_9_11.mixins.jsonI decompiled the client classes with CFR and checked the bytecode with javap. The promo path is small.
The title screen promo
Every MixinTitleScreen variant calls the same two methods at the tail of the title screen render:
NewsOverlay.render(this, graphics, mouseX, mouseY);ModBranding.render(this, graphics);NewsOverlay draws the rotating card. NewsManager holds the slides and reads config/xtoxray-news.json. If the file is missing, it writes the defaults.
The defaults are hardcoded:
list.add(new NewsEntry( "X To Xray Update", List.of("Version 2026.28 ist da!", "Druecke X im Spiel."), 0x55FF55, "https://modrinth.com/mod/x-to-xray", "xtoxray:textures/gui/news/1.png"));list.add(new NewsEntry( "YouTube", List.of("Subscribe!", "Neue Videos & Tutorials."), 0xFF5555, "https://www.youtube.com/@RandomPixelStudios", "xtoxray:textures/gui/news/2.png"));The strings are German even though the rest of the mod is in English. That is a small detail, but it made the defaults easy to find.
ModBranding is the bottom left text. It draws X To Xray and the mod version.
The join message
The chat message lives in XrayToggleHandler.onInitializeClient. The mod registers a ClientPlayConnectionEvents.JOIN callback. The decompiled shape, with the intermediary names cleaned up, is:
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { resetXray();
MutableText discord = Text.literal("[Discord]").styled(style -> TEXT.openUrlStyle(style, URI.create("https://discord.gg/CZ9Mr7epqj")) .withColor(5793266) );
MutableText youtube = Text.literal("[YouTube]").styled(style -> TEXT.openUrlStyle(style, URI.create("https://www.youtube.com/@RandomPixelStudios")) .withColor(0xFF0000) );
MutableText msg = Text.literal( "Support X To Xray By Joining The Discord Server And Subscribing On Youtube! " ).append(discord).append(Text.literal(" ")).append(youtube);
if (client.player != null) { client.player.sendMessage(msg, false); }});The callback also resets the xray state on join. I wanted to keep that part and drop the message.
Patching the class files
I did not have the mod’s source, so I patched the bytecode with ASM.
The first two changes are no-ops. NewsOverlay.render and ModBranding.render get a body with a single return:
method.instructions.clear();method.instructions.add(new InsnNode(Opcodes.RETURN));The join callback is a private static lambda method. I replaced its body with the original reset call and a return:
method.instructions.clear();method.instructions.add(new MethodInsnNode( Opcodes.INVOKESTATIC, "com/xtoxray/client/XrayToggleHandler", "resetXray", "()V", false));method.instructions.add(new InsnNode(Opcodes.RETURN));The rest of the class stays untouched. I rezipped the jar, kept the original as a backup, and dropped the patched jar back into the mods folder.
Verification
javap shows the new bodies:
public static void render(...); Code: 0: returnprivate static void lambda$onInitializeClient$1(...); Code: 0: invokestatic #362 // Method resetXray:()V 3: returnunzip -t passes. The mod still loads. The next world join produced no Discord or YouTube line in the log. The title screen render path returns before it draws the card or the watermark.
The xray code, the veinminer, and the hitbox renderer are not part of the patch. They stay exactly where they were.
The mod can have a Discord. I just do not want it in my chat box every time I load a world. Removing two render calls and one message call was enough.
If a future update brings the promo back, the same three methods are the place to look.