Skip to content

Soul Armory

A minecraft mod that features snowballing

By Ice_Kube | 2026-03-19

The idea of the mod — It’s been in my mind a few years ago.

Now’s might the time to start actually making it.

Just finished creating the repository.

It’s time.

Finished the soul accumulation, decay, and damage boost mechanics for the Soul Sword.

Unlike my previous implementation, I used a “lazy update” approach this time—mostly because InventoryTicks only runs when the item is in the player’s inventory. I want the soul value to decay regardless of whether it’s in the backpack, the hotbar, or even dropped on the ground.

I don’t want players filling up on souls at a mob grinder and then stuffing the sword into an Ender Chest or a modded backpack to cheese their way into a boss fight.

Tried using Google Gemini as a coding agent via Cline—total disappointment.

The thing has no concept of “minimalist changes,” and its “Plan Mode” is basically fluff.

Back to Claude I go.

Though, perhaps my implementation logic is a bit unconventional because even Claude keeps misunderstanding me.

Still, it’s faster than writing everything by hand.


The sword kept triggering the “re-equip animation” (the one where it slides up from the bottom of the screen) every single tick while held. It looked incredibly glitchy.

Reason: I was modifying NBT tags every tick, and every NBT change triggers a re-equip animation by default.

Fixed.


Why does soul accumulation never hit exactly 100 when killing an Iron Golem?

I need to install the Neat health bar mod to see what’s actually going on.


What the hell? Why isn’t Neat working?

Mixin injection failed? Is my Forge version too new?

Just downgraded from 47.4.17 to 47.4.10. Still nothing.


Downgraded to 47.3.0.

It broke my own code.

Crap!

Revised plan: Use Jade.


What do you mean Jade doesn’t work either??

Good god, am I really going to have to check HP using the F3 menu?

Kill me now.


It’s a Mixin issue.

But this doesn’t happen when the mod is exported and run in a production environment.

I wonder… if I manually add the Sponge Mixin library to the dev environment, maybe that’ll fix it?

It’s standard procedure for coremods; shouldn’t break the project.


It worked.

I think it’s because the dev version of Forge Gradle doesn’t include Mixin by default, which is why other mods fail when trying to run Mixins.

It’s not a “built-in version is outdated” issue, since the latest Sponge Mixin is already five years old.

This also explains why the exported builds work fine—either the Forge Mod Loader (FML) provides Mixin at runtime, or another mod requiring Mixin brings it along.

Forge… how many more “surprises” do you have for me?


With Neat and Jade working, I fixed the “100 HP Iron Golem gives 120 souls” bug. Turns out, if the target’s HP was lower than the attack damage, the code was adding the full damage value instead of the target’s actual remaining HP.

Also fixed a float-to-int conversion issue: if you attacked without a full charge, the soul gain could be lower than the total damage because the decimals were being truncated.

The fix wasn’t too complex—just changed the soul storage from int to float.

Implemented the Soul Bow. Some features from the design doc are still missing, and like the Soul Sword, it’s using vanilla icons as placeholders.

Still can’t fully trust the AI. Spent a lot of time fine-tuning the code, but it’s still more efficient than doing it alone.

Ran a test—why is the right hand twitching so much?

Re-equip animation again!!

I played myself!


I’m not sure what I missed, but:

  1. Drawing the bow doesn’t trigger the FOV zoom like vanilla.
  2. While drawing, the item icon in the hotbar flickers between the “pulling” and “idle” states every other frame. Weird.

New bizarre bug:

My arrows have homing capabilities, but they fly in a normal parabola mid-air and then suddenly “teleport” to their intended impact point.

Strange. Very strange.


Final verdict: When running the arrow’s tick(), do NOT use !level.isClientSide. That causes data desync.

My theory: The client-side arrow and server-side arrow were flying different paths. The server-side arrow synced its data at launch and at impact, but calculated its own path in between. Since the server knew it was turning but the client thought “I’m flying straight,” you get that weird teleportation effect when the data finally syncs at the end.


The previous homing algorithm searched for the nearest entity to the arrow, but the “game feel” was terrible. It often resulted in “aiming at A but hitting B.”

If it’s just “nearest target” instead of “the target I’m actually aiming at,” it might as well be a melee weapon. I’d be better off just using the Soul Sword.

So, I added a feature: upon firing, it detects the entity closest to the player’s crosshair within a certain range and tells the arrow to track that specific target.

And then—the teleportation issue returned. In theory, the server knows “I am tracking this guy,” but on the client, the target entity is still null, so it flies straight until it hits, syncs, and teleports.

This is tricky. When it was “nearest target,” the logic was self-contained within the arrow, so I could just remove !level.isClientSide to let both sides calculate it.

But now I need to figure out how to sync a LivingEntity as data from the Server Side to the Client Side.


Fixed the sync, but the feel is still off. The miss rate is high.

More importantly: the player must have a clear line of sight to the center of the enemy’s body. This means if you are shooting from a lower elevation, the homing fails completely.

Also, since it tracks the center of the body, if an enemy is behind a one-block-high wall, the arrow just slams into the cover.

Current thoughts:

  1. The LOS issue: I can adjust the targeting algorithm to check three points on the entity: the eyes, the center, and the feet. If any of them are visible, it’s a hit. Alternatively, use a hybrid plan: if no target is found via crosshair at launch, fall back to “Plan B” (nearest target) which I just deleted.
  2. The cover issue: Perform a ray cast to the three points of the target every tick and track the first visible one? Seems feasible, but the player’s PC will not “thank” me for the CPU load.
  3. The “feel” issue: Parameter tuning. Maybe implement “the closer the arrow is to the enemy, the stronger the homing steer”?
  4. The “Lazy” fix: Just lower the homing radius. If players don’t rely on it, the first two problems are masked. After all, the homing is mainly for the “Fan Shot” special skill.
  5. Gravity: I might just disable gravity for the Soul Arrow.

LMAO, disabling gravity completely fixed the “feel” issue.

The probability of arrows hitting cover also dropped significantly.

Simplicity is the ultimate sophistication, indeed.

Now I just need to tweak the targeting so the player only needs to see one of the three points (eyes, center, feet).