Guide
Building a Minecraft mod that learns from you
Dev notes on a Minecraft Fabric mod that learns from the player: counting habits, saving them with SavedData, and fixing Araz's pacing in beta.2.
In short Araz is a Fabric horror mod for Minecraft 26.3, 26.1.2, 1.21.10 and 1.20.1 whose creature unlocks abilities by counting what the player does: four door uses, five animal visits, three village walks, three sleeps. Those counters are saved with the world in one SavedData record, so it remembers across sessions. The current release is 1.0.0-beta.2.
Araz is a Fabric horror mod I write on my own. Its creature does not ship with a move list. It starts with one ability and unlocks the rest by counting what the player does in front of it, and those counts are written into the world save. As of September 2026 the current release is 1.0.0-beta.2, on Minecraft 26.3, 26.1.2, 1.21.10 and 1.20.1.
This is a build write-up, not a pitch. It covers why the learning system exists, how the state is stored, and how I rebuilt the pacing gate in beta.2 after players told me the creature turned up far too often. The mod page is at spicesfire.com/araz if you want to see what it looks like from the player side.
Everything below is checkable against the mod's own MODRINTH.md and CHANGELOG.md files, which ship in the repository next to the source.
Why do horror mods stop being scary?
A stalker mod is terrifying for about two hours. The creature has a fixed set of behaviours, the player sees all of them, and after that every appearance is a repeat. The fear was never about the model. It was about not knowing what the thing could do.
So the design problem is not "add more behaviours". It is "delay the moment the player has seen the whole set, and make the order personal". My answer was to gate abilities behind observation, not behind time or behind the player's progression. The creature cannot open a door until it has watched someone open a door.
How the creature learns from the player
There is one counter per observation type, per player. When the count crosses a threshold, the matching ability unlocks and the player gets a single line of chat telling them what just happened. The thresholds come from the mod's own design notes in HIKAYE-BRIEF.md and match the enum in the source.
| What it watched | Times needed | What that unlocked |
|---|---|---|
| You open and close your door | 4 | Doors and glass stop being an obstacle |
| You walk past your animals unharmed | 5 | It can take over your animals |
| You walk among villagers | 3 | It can stand among them wearing a villager |
| You sleep | 3 | It can enter your body |
Wall climbing is the one ability it has from the start, at threshold zero, so a fresh world is not completely toothless. The ogrenmeHiziCarpani setting scales every threshold: 200 halves the observations needed, 50 doubles them. The scaling is applied at read time, so changing the setting mid-world does not corrupt the stored counts.
It watched you open and close your door. Doors no longer stop it.
How the learning state is saved with the world
All of it lives in one SavedData record attached to the overworld's data storage, serialised through a RecordCodecBuilder codec. One blob, one file, one place to look when something is wrong. Here is what is in it.
- Which players have already seen the one-time first sighting.
- Per player: how many times each observation was counted, for doors, animals, villagers and sleep.
- Per player: how many encounters happened, how many nights they survived after the first sighting, and which Corrupted Records they read.
- Whether the abandoned camp and the portal ruin were built in this world, and the exact spot the camp was placed on.
- Which players killed it, and which players the ruin guard threw out.
Every field after the first is declared with optionalFieldOf and a default. That is the only reason worlds from 1.0.0-beta.1 still open on beta.2: a save that has never heard of the geceler or kalinti_ozu fields just reads the defaults instead of failing. It costs nothing to write and it is the difference between a patch and a broken save.
Why it appeared too often in beta.1
In beta.1 there were six separate ways the creature could end up visible: ambient encounters, door and window visits, the hanging ambush, the mining glimpse, abductions, and bed visits. Each one had its own timer, and each timer was tuned in isolation and felt fine in isolation.
They were independent, so they stacked. On a bad night four of them fired inside ten minutes and the creature stopped being an event. The beta.1 reports were not about any single feature being too frequent. They were about the sum, which nobody had tuned because nobody owned it.
The beta.1 to beta.2 pacing changes
| What | beta.1 | beta.2 |
|---|---|---|
| Shared appearance cooldown | none, six separate timers | one gate, 240 seconds by default |
| Encounter interval | about 1.5 to 5 minutes | about 4 to 11 minutes |
| Familiarity discount on the wait | 45% | 30% |
| Hard floor on the wait | 1 minute | 4 minutes |
| Waiting behind a door | 35% | 18% |
| Watching through a window | 50% | 22% |
| Hanging ambush | 25% | 12% |
| Villager disguise | 40% | 25% |
| Mining glimpse per cave opening | 30% | 18% |
| Glimpse follow-up cooldown | 4 to 10 minutes | 8 to 18 minutes |
| First abduction | about 5 to 10 minutes | about 15 to 30 minutes |
| Later abductions | every 7.5 to 15 minutes | every 20 to 40 minutes |
The structural fix is the first row. Every path that can put the creature on screen now calls one predicate before it is allowed to run, and every visible appearance pushes one shared timestamp forward. The per-path probabilities in the rest of the table are second-order tuning on top of that gate. Ambient mischief that does not spawn the creature, the phantom footsteps, the lights going out, the ransacked chest, was left alone, so the atmosphere did not get quieter with the creature.
What four Minecraft versions and 12 languages cost
Araz ships for Minecraft 26.3, 26.1.2, 1.21.10 and 1.20.1, Fabric only, with no Forge or NeoForge build. Fabric API and GeckoLib are required; Simple Voice Chat, Mod Menu and Cloth Config are optional. Here is what the matrix actually costs per release.
- Four source trees. Against 26.1.2, the 26.3 release note lists entity types, sign text, coloured blocks and the loot number system as things that changed and had to be rewritten at every call site.
- GeckoLib is pinned per version. The 26.3 build of Araz needs GeckoLib 5.5.6 or newer, which is a different requirement line on every store page.
- Twelve language files of roughly 160 keys each: EN, TR, DE, ES, FR, PT-BR, RU, ZH-CN, JA, KO, PL and IT. One new line of in-game text is twelve edits.
- Translation bugs are real bugs. The beta.2 changelog lists a wrong Altar of Araz advancement description in German and French, plus percent signs rendering incorrectly in the settings screen.
- One store listing per version per platform, on both Modrinth and CurseForge, each with its own dependency list.
The honest version: the 26.3 port was a day of mechanical API translation and no gameplay work at all, and the 1.20.1 backport was worse because the build chain itself is different. If I were starting again I would still do it, because the download split across versions is real, but I would write the API differences down the first time instead of the third.
Things that did not work
- Six independent appearance timers. Reasonable individually, unplayable together.
- Essence of Araz dropping only from the kill. The creature flees below half health, so a player who could not kill it could never forge The Last Line and the story stalled. In beta.2 the Essence sits in the portal ruin chest.
- Placing the abandoned camp on the highest block of each column. That built it on treetops and on the surface of water. It now comes from the terrain generator's own height data and has to be dry and flat.
- Checking arrival at the portal ruin by horizontal distance. Standing on the surface above it started the chase and spawned the guard 40 to 60 blocks below, inside solid rock.
- Building the camp and the ruin only in survival mode. In creative, the coordinates the mod had just whispered pointed at plain stone.
- Stopping the observation counters at the unlock threshold. The record signs and the Observation Log then showed capped numbers instead of real ones, which is exactly the wrong lie for a mod about being counted.
- Shipping the 26.3 build without checking the jar contents. The spawn egg texture was missing from the mod file.
The pattern in that list is that five of the seven are not logic errors. They are a correct rule applied to a case I had not imagined: creative mode, a lake, a player standing on the roof of my own structure. Horror mods are systems that run unattended for hours, and the failure mode is almost always an assumption, not a formula.
What is next: Part II
The story in 1.0.0-beta.2 ends at the portal ruin. The frame is broken and the portal stays dark, which is deliberate: Part I shows the door and does not open it. Part II is what lies on the other side, and it is not out. I am not going to give it a date while beta.2 is still collecting multiplayer reports, because single player is what I have tested properly and multiplayer is not.
Release notes for each version go up on the mod's own blog at spicesfire.com/araz/blog. If you want the engineering side, that is here on this site, and Part II will get the same treatment when there is something to write about.
Frequently asked questions
Which Minecraft versions does Araz support?
Araz 1.0.0-beta.2 runs on Minecraft 26.3, 26.1.2, 1.21.10 and 1.20.1. It is Fabric only; there is no Forge or NeoForge build.
Does Araz change world generation?
No. Nothing in Araz touches chunk generation. The abandoned camp and the portal ruin are built when a player gets close, so the mod is safe to add to an existing world.
What mods does Araz need to run?
Fabric API and GeckoLib are required, and the Minecraft 26.3 build needs GeckoLib 5.5.6 or newer. Simple Voice Chat, Mod Menu and Cloth Config are optional.
Does the creature still show up too often in beta.2?
It should not. Every visible appearance now passes through one shared cooldown, 240 seconds by default, instead of the six independent timers beta.1 used. If it is still too much, raise gorunmeBeklemesiSaniye in config/araz.json.
Does the creature remember me after I quit the world?
Yes. The observation counts, encounter counts, nights survived and story progress are written into the world save, so the abilities it learned from you are still unlocked when you come back.
Is Part II of the story out yet?
No. Part I ends at the portal ruin with the portal still dark, and Part II has no release date while 1.0.0-beta.2 is still collecting multiplayer reports.