Porting a 2016 Minecraft Mod to 26.2: What Ten Years of Changes Looked Like

pyrogenous

I ported Elemental Creepers from Minecraft 1.9 to 26.2 on Forge. What broke, what I rewrote, what I dropped, and how the first crash got caught.

Elemental Creepers was one of the first mods I ever loved. Lomeli12 made it for Minecraft 1.9: a creeper that floods everything with water, one that drops cookies, a pink one you can tame with gunpowder, and a Big Bad Creep six times the normal size that releases more creepers when it blows up. Twenty-seven of them, each with its own explosion.

Then Minecraft kept moving and the mod didn't. It needs a library, LomLib, which stopped at 1.12.2. So if you wanted Elemental Creepers you had to go back to 2016.

I wanted it on today's Minecraft, so I ported both to Minecraft 26.2 on Forge. Here's what that looked like.

Where I started

Two folders from almost a decade ago:

  • Elemental Creepers: about 5,400 lines of Java, built with ForgeGradle 1.2 against Forge for Minecraft 1.8/1.9.
  • LomLib: about 1,900 lines of Java plus a good amount of Kotlin, with an ASM core mod, a JEI plugin, custom fluid recipes and Patreon crowns.

None of it compiles on anything modern. The build scripts point to Maven repositories that no longer exist, and the Minecraft classes have different names.

So this wasn't an update. I kept the design, the textures and the Creepapedia text, and rewrote the code against today's Minecraft.

What changed in ten years

The numbers in Minecraft's version went from 1.9 to 26.2, but that doesn't say how much the modding side moved.

Entities are built differently. In 1.9 you registered a creeper class and gave it a spawn egg color in one call. Now entity types are built with builders and registered through deferred registers. Attributes like health and speed are declared separately, and so are the rules for where a mob can spawn.

Saving data is new. The old mod wrote NBT tags by hand. 26.2 gives entities a ValueOutput and ValueInput to save and load with, so every creeper that remembers something got a rewrite: whether it's charged, its fuse, whether the Spring Creeper already jumped.

Rendering is a different world. The old renderers called OpenGL directly: push the matrix, set the color, draw the model. Today a renderer copies what it needs from the entity into a render state, and the game draws from that later. The charged creeper's swirl, the see-through Ghost Creeper and the six-legged Spider Creeper all had to be rebuilt this way.

A charged six-legged Spider Creeper rendered in Minecraft 26.2

Spawn eggs aren't colored anymore. In 1.9 an egg was a base texture with two colors. Since 1.21.5 every mob has its own drawn egg. I didn't want 26 generic eggs, so I took the vanilla creeper egg and recolored it with each creeper's original two colors, keeping the shading.

The 26 Elemental Creepers spawn eggs, recolored from the vanilla creeper egg

Spawning is data now. Where a mob spawns used to be one Java call per biome type. Today it's a biome modifier in a data pack. I wrote a small custom one that reads the spawn weight from the config when a world loads, so you can still turn a creeper off without touching a data pack.

What I kept, what I dropped

Every creeper made it, with its behavior:

  • The Friendly Creeper still tames with gunpowder (one chance in three), follows you, sits, breeds with flowers. Its explosions now spare its owner and the owner's pets.
  • The Reverse Creeper still turns the ground upside down. It now leaves chests and furnaces where they are, because moving blocks with contents is how you lose or duplicate items.
  • The Creeperfish (the Silver Creeper in the original) still hides in stone like a silverfish, and its eggs spawn in windswept hills.
  • The Creepapedia still records every creeper you kill, and the Ghost Creeper's page is still gibberish until you take the book to an enchanting table.
  • Creepers still wear a pumpkin on Halloween, a sponge on November 12 and a snow block on Christmas. Vanilla creepers too.

A tamed pink Friendly Creeper sitting next to its owner

LomLib was harder to decide on. Half of it exists because 2016 Forge couldn't do things Forge does today. I kept the parts that are still useful and became LomLib Reloaded: the enderman-style teleport helpers and the admin commands (/lomlib clear-hostiles and friends). I dropped the ASM core mod, the Kotlin language adapter, the JEI plugin, the fluid recipes and the update checker. Forge and Minecraft do those themselves now, or they can't work anymore.

One thing I kept on purpose: the Hydrogen Creeper's explosion is still 64 blocks wide by default. That's the joke. It's in the config if your computer disagrees.

The first crash

The mod loaded, the creepers spawned, and then I opened the Creepapedia on a creeper's page and the game crashed.

The Creepapedia open on the Fire Creeper page, with the creeper drawn on the page

The book draws the creeper on its page. To do that it creates a creeper that never enters the world, and a creeper that never enters the world has no ID. Minecraft 26.2 reads that ID while drawing whatever the creeper wears on its head, so it crashed. The fix was one line: give the preview a negative ID that can't clash with real entities.

The interesting part is what happened next. The mod reports its errors with Nitea, free error tracking for Minecraft mods, and the crash showed up in my dashboard. But only when I started the game again.

The Creepapedia crash reported in the Nitea dashboard with its stack trace

Minecraft catches crashes itself: it writes a crash report and closes. Nothing else gets a chance to see the error. Nitea read those reports on the next launch, which is fine for you and me, but a player whose game crashes might never open it again.

So I changed that in Nitea itself. Since Nitea 0.4.1, the crash that closes the game is sent while the game is closing, with the steps that led up to it. If that fails (the game was killed, no internet), it's still sent on the next launch, and never twice.

Built to report its own bugs

A ten-year-old mod on a brand-new Minecraft will have bugs I haven't found, so I made them easy to catch:

  • Every explosion leaves a breadcrumb in Nitea: which creeper, whether it was charged, where it was. When something breaks I can see what happened just before.
  • Each explosion runs guarded: if one throws an error, it's reported and the world keeps going instead of crashing.
  • Players can report straight from the game: /elementalcreepers report bug <what happened>. The Creepapedia has a "Report a bug" button that fills that in.

Nothing is sent until the player agrees. Nitea asks once on the title screen, for every mod that uses it.

Why I did it

Old mods don't die because nobody likes them. They die because the game moves on and nobody updates them. Porting one is a good way to learn how much Minecraft modding has changed, and a good reason to build the mod so that the next bug gets found by a crash report, not by a player giving up.

Elemental Creepers Reloaded needs Forge for Minecraft 26.2 and LomLib Reloaded. If you want your own mod to report its crashes the same way, the Nitea docs take about five minutes.

  • Minecraft modding
  • Forge
  • Porting
  • Elemental Creepers
  • Error tracking

Did you find this article interesting?

Leave a reaction, it tells us what to write about next.

Share this article