ZiggfreedCommon-2.1.0.jar
What's new
The library's fourteenth module: a boss framework over the game's own encounter scripts. The fight is authored natively and the game runs it; the library adds what the game cannot say on its own, from one binding row per fight and with no Java in a pack: who gets credit, what a fight pays, what it announces, a leaderboard, a map marker, and quest and achievement progress. Beside it, everything since 2.0.0: a shared progress-bar HUD any mod can put a value on, with a settings page to say where it sits; a corner feed that stops burying itself; a fix for a server that could freeze for good; an NPC placement pass; a way to share a key with a weapon; enhanced gear on a bare server; a picture on every quest step; quests that reset on a window of any length, say why they are locked and list what they paid; a folder of the library's for a server owner's own quests; and the placed-block record moving onto the world's own chunks. There was no 2.0.1 release; what was written under that number ships here. Four changes break a mod built on 2.0.0, each named below, and the mods built on this library update with it: MMO Skill Tree 1.6.1, Kweebec Nightmare 1.2.0 and MMO Mob Scaling 1.2.0.
Boss fights
- New: boss fights on the game's own encounter scripts. The fight itself, its states, phases, health thresholds, in-place changes of form, invulnerability, adds, the boss bar and the music, is a native encounter script under
Server/EncounterManager/, and the game runs it. A script speaks to the library with the game's ownSignalWorldEventaction and a reserved vocabulary (zc:engaged,zc:phase:<State>,zc:wave,zc:defeated,zc:reset; any otherzc:id is your own beat), and each beat becomes an event any mod on the server can hear. The exact moment of a defeat is read off the boss's own death, so a quest step and a payout land on the killing blow. The library re-implements nothing of the fight, and a fight written for the base game runs unchanged. - New: a binding row says what the server owes a fight.
Server/ZiggfreedCommon/Encounters/<Id>.json, named for its script: who the boss is (Subject), how credit is shared (Participation), how its health scales with the party and the region's power (Scale), a wipe grace and a run limit (Timing), what it pays on defeat and per phase (Loot), where its scores go (Leaderboard), how quest steps read the run (Progression), which notices it shows (Feedback), and whether a map marker follows it (Discovery). A row restates nothing the script says."Enabled": false, in the file or under the id inmods/ziggfreedcommon/encounters.jsonfollowed by/zigencounter reload, switches a fight off without touching its script. - New: credit for the whole party, not the last hit. Everyone in a fight is credited on three channels, damage dealt, damage taken and time present, with weights a server sets in
Server/ZiggfreedCommon/EncounterParticipation/. The shipped default counts damage dealt in full, damage taken at a quarter and presence at a tenth, and credits the dead and the disconnected; a rule can match one mob family or one world, and a fight's own row overrides it leaf by leaf. Your share is measured against the top contributor's, and a share under the rule's minimum earns attempt credit only. - New: loot, notices and a map marker, scaled by your share. On a defeat the fight's loot is rolled once per credited participant, and every roll you won is kept with a chance equal to your share (the top contributor keeps everything); a participant who is offline when the boss falls is paid on their next connect. Four notices fire at the engage, each phase, the defeat (with your own share and the fight's length beneath it) and a wipe, from four plain files any pack replaces by name. A notice can reach beyond the fight: the same world only, within so many blocks, its participants wherever they stand, and not again for so long, so a world boss rising is news to the world it stands in once a minute at most. A map marker can follow the boss while it stands.
- New: a pack-only boss pays, notifies, scales and rests with no Java. Six instructions join the game's own encounter vocabulary for use inside a script:
ZigGrant(pay the credited party),ZigFeedback(show a notice),ZigScaleTarget(scale a creature's health to the party),ZigMembers(how many are still standing),ZigFactor(read any condition the server knows, including the fight's own member count, elapsed seconds, phase, waves and deaths) andZigRested(whether the site has rested since its last kill). - New: a boss rests between fights, and the library keeps the time.
Timing.Reston the binding row says how long a site rests after a kill, on the world's own clock ("P1D"is one game day,"PT8H"a third of one). The library stamps the moment that rest ends on the fight's own entity when the boss falls and saves it with the world, so it survives a chunk unload and a restart, and a script that gates its summon onZigRestedwaits quietly until then instead of trying its spawn marker; the shipped base script does. Two copies of one fight placed in two spots rest on their own, and/zigencounter inspectshows the rest and how much of it is left. Neither the game's own respawn timer nor the script itself can hold this: a spawn marker a script fires by hand fires whenever it is asked and its last spawn is dead, and a script forgets every timer when its chunk unloads. - New: a base script, three macros and a working example, each overridable by id.
Zc_Encounter_Basecarries the shape a boss usually wants (a member collector, a summon from a spawn marker, the release on the Target sensor, a defeat beat and a re-arm after a delay);Zc_Phase_At_Health,Zc_Adds_WaveandZc_Defeat_Beatare the three moves a fight repeats;Zc_Encounter_Exampleruns with no player and no boss so you can watch every beat go by (/zigencounter spawn Zc_Encounter_Example). - New:
/zigencounter.list,inspect,spawn(which loads the chunk first, so a fight is not unloaded on the spot),end,state,validateandreload, answering in all nine languages. - New: the encounter audit. A named finding, from
/zigencounter validateand once per boot, for each of: a misspeltzc:beat, a phase beat naming no state, a defeat beat that never clears the boss bar, a row naming a script the server does not have, two rows for one script, a boss slot the script never fills, a loot table nothing defines, a blocking action list under a sensor markedOnce(the game spends such a sensor after one tick), a script sharing an id with an NPC role (the game keeps one name for both, so one silently replaces the other; name a fight<Boss>_Encounter), and a pack prefab whose spawner block carries no per-block marker state, which pastes as a plain block with no marker under it and leaves the fight standing silent. - New: a boss fight is quest and achievement progress. Three step kinds:
ENCOUNTER_DEFEATED(once per credited participant when the boss falls),ENCOUNTER_ATTEMPT(once per participant when a fight settles, won or wiped) andENCOUNTER_PHASE(once per member on each phase). The target is the fight's script id, never the creature's, so a step holds through a change of form; leave the target out to count any boss. A server first over a boss kill is won by the whole party that killed it, not raced between its members. - New: boss fights write a leaderboard. A row naming a
Leaderboard.Bucketrecords every participant's share and the fight's length, split by party size and by difficulty when asked; the fastest clear keeps the lower time. - New: a lifetime tally is a condition.
{"Factor": "ziggfreedcommon:counter", "Param": "Encounters_Defeated/<Script>", "Min": 1}gates a shop row, a dialogue branch, a placement or a harder contract on having done a thing this often; the mod that keeps the tallies supplies them, and a total or one line of a breakdown can be asked for. An unknown key reads zero, so every condition wants aMin. - New: a generated family fans out over every boss on the server through the
ziggfreedcommon:encountersaxis, with{"Difficulty": "hard"}as its one filter, so a slay-every-boss chain or a boss shelf stays right as packs add fights. - Gone: the old boss and wave engine. The three-phase boss files under
Server/ZiggfreedCommon/Bosses/and the wave rule files underServer/ZiggfreedCommon/EncounterRules/are no longer read, and nothing warns about a file still there. A fight is a native encounter script plus a binding row; Kweebec Nightmare 1.2.0 shows the shape.
The bar panels, and the corner feed
- New: a progress bar any mod can put a value on, with nothing authored. A mod reports that a value moved and a bar appears for it: a name, a picture, a colour, the gain since it came up, the fill to wherever the value is heading and a word at each end of the bar, all supplied by whoever reported the movement, and gone a few seconds after the last move unless the reporter asks for it to be held. A bar wears the same frame as the quest tracker and the zone card, with a sunk well behind the fill, a gloss across its top and a bright band riding its leading edge for a moment after it moves. MMO Skill Tree puts every skill's XP on one, and RPG Stations puts a run's whole ledger on them.
- New: two panels, and the spots they sit at. The Activity ledger is a tall column in the top-left, for the rows of something a player is in the middle of; the World bars are a wide block in the top-right, above the quest tracker, for values that move while they are simply out in the world. Which panel a row lands on is decided by the mod reporting it. Where a panel sits is a spot, one file under
Server/ZiggfreedCommon/HudSpots/naming a corner, offsets, how many columns and how deep each runs;Top_Left,Top_RightandBottom_Leftship, a pack adds one by dropping a file, and every picker offers it at once. A panel names where it is listed in the HUD settings too (Order): the World bars come first and the Activity ledger second. A panel names its spot inServer/ZiggfreedCommon/HudPanels/, and an owner re-tunes either inmods/ziggfreedcommon/hud-panels.jsonorhud-spots.json, one leaf at a time. A single row is re-tuned by id underServer/ZiggfreedCommon/HudRows/, which is optional: the library ships no row file. - New: a spot can leave a band clear for what is already on screen, and hold a short panel to a least height. At the bottom-left spot the World bars would climb into your own health and mana bars, so that spot leaves a band clear after its third row and the rest of the bars carry on above them; the row and the band's height are both in the spot's file (
Gap), counted from the edge the spot pins, and the pair shipped is a starting point for a server to tune against its own screen. A spot can also name the least height a panel draws at (MinHeight), so the ledger sitting over the zone card covers it even with one row showing. Both fold like every other leaf: a player's pick brings its own spot's, a panel restates either over its spot, and the owner file changes one leaf at a time. - New: a spot can leave the bottom cells of one column empty, and the World bars hold nine rows a column. At the bottom-left spot the utility slot and the left end of the hotbar sit under the far-right column, so that spot cuts the three cells nearest the edge out of that column alone (
Cutout, a column counted from the panel's own first and a number of cells); that column's bars start above the cut and stop where the other columns stop, so it never stands taller than them: the bars it has no room for go into a row of their own above the whole block, filled from the panel's first column outward, and the frame is only as tall as that. Every column stands on the edge it is pinned to whatever its height, so a short last column sits on the edge beside the full ones rather than hanging from the panel's top. The World panel's document holds nine rows a column, and the bottom-left spot's band is tall enough for the rows above it to clear the mana bar; both numbers in the spot's file are a starting point for a server's own screen. - New: every HUD card takes its colour and its transparency from one hex. The Activity ledger, the World bars, the quest tracker and RPG Stations' session summary all wear the frame
Server/ZiggfreedCommon/HudCards/Default.jsondescribes: a singleColormultiplied over the shipped frame, so#ffffffis exactly the look you have, a darker hex darkens every card at once and a hue tints them, and eight digits carry a transparency in the last two,#ffffffb8being the same cards at about 72 percent. A bar spot or a bar panel may state aColorof its own, and a mod may give its own panel one, each falling back to the shared file; an owner changes the shared look inmods/ziggfreedcommon/hud-cards.jsonand never touches a.ui. On the bar panels the well behind each fill, the gloss across it and the shade under it follow the card's transparency on their own, keeping their colours, so a dimmed panel still reads as a set of bars. Left out everywhere, nothing changes and nothing is sent; a value that is not a hex is ignored with one line in the log. - New: a player picks where their bars sit, or hides them, and the page is the library's. Every player may pick another offered spot for a panel, hide one panel, or hide them all, and the pick is kept on a record beside the panels that a mod persisting player data elsewhere can carry between servers. The HUD settings page has a Mine tab every player may open and a Server tab for whoever the hosting mod admits, which moves a panel for everyone, nudges it by an offset or switches it off and writes the owner file in the shape an owner would type. A mod's own settings menu opens it;
/zighud open|place|hide|show|defaultdrives the same switches from the console, in nine languages. - New: the Server tab tunes the whole shape and look of a panel. Beside the offsets and the spread, it takes the band a panel leaves clear (after which row, and how tall), the cells cut out of one column, the least height it draws at and the colour of its frame, one field each per panel, and Save writes them into
mods/ziggfreedcommon/hud-panels.jsonfor everyone. A blank field hands that leaf back to the spot; a letter where a number should be, or a colour that is not a hex like#ffffffor#ffffffb8, is named and nothing is written until it is fixed; and the file stays one you can still edit by hand. - A gain of ten thousand or more reads compact. The number beside a bar's name is written
+12.3kfrom ten thousand up, on both panels, so a big gain no longer clips in the World bars' narrow gain column; below that it is grouped by your own client as before. - Fixed: a notice that repeats itself rewrites its own line of the feed. The corner feed shows seven lines and the game gives a server no way to retire one early, so every notice this library sent took a fresh line and a quest step that kept moving pushed the pickups and finds out of sight. A moment file may say its notice merges, and a repeat about the same thing then rewrites one line while two sources keep two; the shipped step-progress notice does, so a moving step stays on one line and its finish lands on the counter it finishes. A value that moves every few seconds belongs on a bar, and the feed is for things that happen once.
- Fixed: a step the quest tracker is already drawing says nothing in the corner feed. With the tracker up and the quest pinned to it, a notice per tick was a second copy of a count the player was looking at. The tracker claims those ticks and the feed stays clear; the sound, the banner and any command still run, and the tick that finishes a step still announces. A hidden tracker, a quest past the tracker's block count, or a player with no tracker at all keeps every notice.
- The quest tracker's count takes the room it needs. A long count no longer runs back over its own text, and a goal in the thousands is written compressed on both sides (
1.4k/10.0k), so an objective counting into the thousands stays a few characters wide.
Notices, and what a quest says
- Fixed: a payout lists what it actually handed over. A quest, achievement, shop or boss payout that rolled a loot table painted one generic "Loot Bundle" line on every notice that followed it. A notice raised after a payout lists the items the table rolled, a line and a picture each, nothing for an empty roll, and only what was really handed over: a quest that parks its reward (a full bag, or it collects somewhere else) carries the finished headline and no rows. A hand-in that parks the quest reads a plain "Handed in." rather than the gold finished line.
- Fixed: earning an achievement says what it earned. The notice read its points and nothing else while the achievement's own page listed the XP or the token waiting to be collected. It lists what waits under the headline, the way a finished quest waiting to be collected does.
- Fixed: a notice drawn into an open screen kept only its second line, and no picture. Finish a quest or earn an achievement with a conversation or a menu open and the notice is drawn into that screen rather than the corner, and the sentence naming what happened was dropped on the way; earning First Quest read as "+5 achievement points". Both lines are there, and the picture beside them. A quest's own notices carry the quest's picture too, where before only an achievement could have one.
- Fixed: a quest with no name of its own is called by its first step, on every screen. A bounty contract, or a pack's quest shipped without a title, read "Untitled" on the board and as a raw key in the quest book and on a character's offer list, while the notices called the same quest "Mine 10 Iron Ore". Every surface names it the same way.
- A locked quest says why, and one that comes back says when. A daily already done today, a quest already carried, one finished for good and a server with quests switched off each read the same "Not available yet". Each has its own line, a repeat waiting out its clock quotes the wait ("Comes back in 5h 12m") under its own "Comes back" heading, and the quest book uses the same clock, so a daily held until tomorrow no longer reads "Cooldown: 0m".
- New: every quest list says how often a quest comes round. Daily, Weekly, or Repeatable for one that comes round sooner than a day, badged beside the quest wherever it is listed, read off the quest's own timing so nothing is hand-labelled.
- A payout lists up to twenty things. A notice that follows a payout lists twenty lines before it sums the rest up as "and N more", where it used to run out of room after a handful. A one-line notice is the size it always was.
Quests, steps and progression
- A quest's step list shows what you can do now. A quest may keep a step you cannot work on yet off its list until the steps before it are done, so a return trip is not sitting under the work it waits on as though both were open. The author turns it on with one line (
Flow.HideLockedSteps); a quest that does not lists every step as it always has, the locked ones dimmed. - A quest that names a hand-in character gets its report-back step. A quest that says who it is collected from, and writes no hand-in step of its own, gets one added at the end of its list: "return to" for the giver, "go to" for anyone else. It shows on the list like any other step, can be hidden until the work before it is done, and plays the closing conversation. A quest that wrote its own is left exactly as written.
- New: your own quests live in
mods/ziggfreedcommon/quests/. One file per quest, named after the quest, in the same shape a content pack ships, read as the top layer with nothing to register: a file named after a shipped quest changes only the lines you write ({"Enabled": false}alone switches one off), a file naming aParentinherits from that quest wherever it lives, and a new name is a quest of your own. The folder is re-read on every reload, and a quest gated on a feature locks or unlocks the moment that feature is switched, with no restart. A mod that kept a quest fold of its own can hand the library one whole layer of quests instead, which is what MMO Skill Tree 1.6.1 does. - Fixed: a finished quest waiting to be collected is on the list of whoever you collect it from. A quest one character gave you and another one credits could vanish from "Quests here" at the very character you collect it from.
- Fixed: finishing a quest through a conversation takes you to it. Pick the line that finishes a quest and you land on that quest with its Collect button in front of you, instead of back in a menu with nothing to show it happened. A quest that pays out on the spot does not jump anywhere.
- Fixed: Collect plays the quest's closing conversation. Pressing Collect at the character who has one lets them say their piece; collecting from the book or out in a field stays quiet.
- The steps and rewards on every quest screen are drawn larger. The lines that say what a quest asks and what it pays, at the character handing it out, in the quest book, on a bounty board and in a shop, are one size up with a bigger picture beside each, and the small OBJECTIVES and REWARDS labels above them are lighter, so they read as headings instead of fading into the panel.
- New: a listed step is drawn with a picture, not just a sentence. Every surface that lists quest or achievement steps shows one: the item a step names drawn as itself, a creature as the still the client already renders of it, a wallet or a board as its own icon, another quest as the picture it is listed under everywhere else. It is decided in one place, so a step cannot be pictured one way on a giver's screen and another in the objective book, and a step nothing can picture reads as its text alone rather than borrowing an unrelated thing's art. An item is only ever drawn when the server really ships one under that id.
- New: an objective KIND is a file.
Server/ZiggfreedCommon/ObjectiveKinds/<Id>.jsonis the one place a kind is described:ValueBased,AtMostandProducible(what it counts, whether its amount is a ceiling, and whether content may use it),TargetNames(whether its target is a place, an item, a creature, a wallet, a board, an encounter or another piece of content), andPresentation(TextKey,Icon, andTargetIconsfor the individual targets that need a picture of their own). The filename is the id content writes as itsKind. - A kind file MERGES over the code that registered it, leaf by leaf. A file usually means to state one fact, so a leaf it does not mention is not an instruction: writing a picture keeps the arithmetic the mod that invented the kind registered, and turning a kind off keeps its picture. A file naming an id nothing registered adds that kind outright, which is how a server describes a step kind its own producer already fires. The library ships a file for every built-in kind.
- A step of a kind another mod owns reads that mod's own wording. A kind file's
TextKeyis what a step of that kind reads when the step has no line of its own, so a work-station step reads the station mod's sentence rather than a generic one. - New: a quest can reset on a window of any length.
Reset.Everynames how long one window lasts,{"Hours": 8},{"Days": 1},{"Weeks": 2}, shifted byAtMinutesand, for a whole number of weeks, byWeekday;PeriodDaily or Weekly stays as shorthand. How often a quest comes round is measured one way for every screen and every achievement that counts dailies: the longer of its rolling wait and its calendar window, so a quest that resets once a day with no rolling cooldown is a daily. Breaks a mod that read the old runtime reset value; authored quest JSON is unchanged. - New:
ziggfreedcommon:quest_known. Reads 1 when the server's quest catalogue holds a quest and 0 when it does not, with no player needed, so a conversation can tell whether a quest another pack ships is on this server at all. - Fixed:
hytale:mod_installedsees a pack that is only assets. A content pack with a manifest and no code read as absent while it was installed. - Fixed: "Server First lost" is announced once, when it is lost. A player who qualified for a server first somebody else already holds was told again on every login, every instance entry and every visit to an achievements screen. The chance to win it back if an admin clears the claim is unchanged. Breaks a mod that implements the achievement earn gate, which is told whether the criteria were just met or are being re-checked.
- Fixed: a quest that came to be met while a player was away pays out in full. The maintenance pass on login settled such a quest and paid its rewards, but the mod hosting the quest never heard about it, so its own follow-on (an achievement credit, a reset, a further grant) was skipped in silence. The pass runs under the same context every other completion does.
- New: the
Flairreward kind and/zigflair. A quest, achievement or contract can pay a flair ({"Kind": "Flair", "Params": {"Flair": "<id>"}}); a flair already held is a quiet no-op, an offline grant waits on the same retry queue as every other reward, and a new one draws aFlair_Unlockednotice a pack can replace by name./zigflair grant|revoke|list --player=<name> [--flair=<id>]administers it, in nine languages. - New: a shared line group can say which screens it belongs on. A conversation's
Fragmentsentry gains an object form beside the array it always took:Onpicks screens by id or by aTagsleaf a screen declares, andIncludefolds other groups in, so a line that belongs on every temple screen is written once against the tag rather than a list of names, and a screen added later that carries the tag gets it too. ADoatom can carry one native action in full ({"Action": {...}}) beside the shorthand atoms, so a step with no shorthand keeps its place in the order without forcing the whole option back to the long form; an atom mixing the two, or an option writing bothActionsandDo, is named by the audit.
NPC placement
- Fixed: an NPC nothing placed still answers press F. The stamp binding an NPC to its placement is attached only by the placement sweep, so one spawned by a command, an egg, a prefab or another mod carried none: the press-F action rendered its prompt and then did nothing, with the only trace a fine-level log line. A base role can author its own
DialogueorOpenon that action, used when there is no placement to read. It is a FALLBACK, never an override, so a placement standing the NPC still decides and one shared role can be re-pointed per standing.Dialogueis computable, so a nativeVariantbinds it per character;Openis read as the authored value and decoded at first press-F rather than at role load. - Where governs placement, and only placement. An NPC standing in a world the placement does not target, by whatever route it got there, answers normally. This is what the interact path always did; the schema documentation and the shipped comments say so.
- New:
mods/ziggfreedcommon/npc-placements.jsoncarries whole placements. An entry may hold the same fields a pack authors beside theenabledswitch, decoded against whatever the packs already say about that id, so writing one leaf changes that leaf and keeps the rest. The file stays schema 1 and every existing file reads unchanged: the switch is the lower-caseenabledleaf and an asset's own fields all start upper-case, so the two can never be confused. Only an entry naming one id may carry a body; settings under a wildcard key are skipped and named. - New:
/zignpc place. Writes a placement where the caller is standing, in their world, facing their way, then re-reads and sweeps so the NPC appears immediately. It refuses a role the server cannot spawn, an unknown one or an abstract template other roles are built on, rather than writing a placement that could never appear, and refuses an id already in use rather than replacing somebody. A consumer aliasing the verb calls the same path, so the two cannot drift. - New: an NPC placement admin page. Every placement targeting the world the admin is in, with the state the sweep would act on and a switch each; a denied placement is painted as blocked rather than as off, since its gate and not the switch is what stops it. A filter and a Place button stand a new one where the admin is, offering only roles the server can spawn. It is opened through the library's own opener rather than as a registered destination, and its audience seam defaults to DENY: the page writes, and the library cannot know what an admin is on a given server.
- Fixed: an NPC standing somewhere nobody walks actually gets placed. A placement's spot has to be loaded before the NPC can be put there, and some spots never are: a world spawn point every returning player skips, an anchor off any route through the world. The NPC simply never appeared, and the server log filled with the engine trying again. The world loads the spot it needs, stands the NPC there, and lets the chunk go back to sleep afterwards, exactly as if a player had walked past.
- Fixed: the placement log is quiet again. Walking through a world kicked a fresh round of retries for every structure marker it sighted, so one placement that could not be resolved turned into dozens of overlapping retry rounds, each re-scanning the world and each ending in the same warning. One field log carried 127 of them in a minute. There is one round per world, it is shorter, and the line saying a world has given up is printed once. A later sighting, an arriving chunk or a manual reconcile still gets a fresh look, without the burst.
- Fixed: two startup lines that were not problems. A
Whereaimed at an instance world reported a warning on every boot for being aimed at something that is not running, which is what content aimed at an instance always looks like; it is a note, while a world named by a pattern that matches nothing keeps its warning, since that is usually a typo. And registering a generated language pack warned on the very first boot for tidying up a registration that did not exist yet.
Sharing a key with a weapon
- New: a way to ask whether a native interaction can actually do anything right now. A mod that puts its own interaction on a key a weapon already uses has to decide which of the two a press belongs to, and the honest answer depends on the weapon: a signature move with an empty energy bar has no claim on the key, and a reload has none with a full magazine.
NativeInputGatereads that off the weapon's own opening conditions without running it, so a mod can route the press instead of swallowing it. It reports two things separately, whether the conditions pass and whether the chain spends a resource at all, since a chain that costs nothing is as ready on the thousandth press as the first and so never means a move is waiting. Anything it cannot read reports as not ready, which is safe for the intended pairing: run the weapon's own chain anyway when your alternative declines, and it re-checks the same conditions itself.
Stats on an item
- New: rolling stats onto an item a player already owns works with no other mod installed. The library rolled and budgeted the stats but left the writing to whoever registered a writer, so a server running it alone stamped items nothing could read or apply. It owns the whole path: the write, the tooltip, and turning a stamped stat into a real one when the item is worn or held. A consumer supplies vocabulary and nothing else.
- A mod that adds a stat does not have to register a name for it. The client already names every stat it can show, and that is the first place a stamped line looks. A stat the game defines reads correctly with nothing authored, and so does a mod's own stat as soon as it ships the label it needs anyway for the ordinary tooltip.
- New:
Server/ZiggfreedCommon/StatDisplays/<StatId>.jsonrenames or recolours one stat.Keyis the translation key naming it, handed the points as a{value}argument;Coloris a hex colour. Both optional and independent. An authored file outranks whatever a mod decided in code, so a server owner or a pack can correct any stat's wording without waiting on whoever invented it. - New:
Durabilityis a stat id a pool can roll. It raises the item's maximum durability instead of storing a stat entry, because durability belongs to the item rather than being a stat channel. The roll engine treats it as an ordinary entry throughout: it takes a pick, it costs budget, and a per-stat ceiling holds it. - New: a pool or a stamp can say what the item becomes.
StampNameis a translation key handed the item's own name, so one key reads correctly on anything it lands on.Qualitynames an item quality asset, the game's own per-instance rarity channel, so the client colours the name, the tooltip frame and the slot for it natively. Both are authored or absent: nothing is renamed or re-tinted unless a file asks, and there is no built-in tier vocabulary. - Fixed: an enhanced item keeps its own description. An item whose base-game entry already carried stats lost its description under the enhancement lines; every item shows its own description first, wherever the catalogue has one.
Placed blocks and mob identity
- Blocks you placed are remembered by the chunk, not by a file. The record of what a player put down, the reason nobody earns from breaking what they placed themselves, was one
mods/ziggfreedcommon/placed-blocks.jsonthat grew forever and was rewritten whole twice a minute. It rides on the chunk the block sits in, saved and loaded with it, with nothing left to grow or scan. On first boot the old file is renamed aside with one notice and its rows are not carried across, so blocks placed before the update stop being remembered; everything placed from then on is guarded as before. Breaks a mod that set the ledger's policy: nobody earns from a placement whoever breaks it, a placement is remembered until broken, and the one case the lenient setting was really for, somebody standing ore up for others to work, is answered by naming a builder whose placements are never recorded, typically by permission. - A mob is its role, not the costume it wears. Everything keyed on a mob across this family, a kill step's target, a consumer's XP and drop config, a deny list, matched the model a mob wears rather than the mob. For most creatures the two are the same word; where they differ (the training dummies, a pack mob dressed as a vanilla one) the rule governed mobs nobody aimed it at. A mob goes by its role name, the one a server owner can see and type.
Fixes
- Fixed: the server could freeze for good, and then it would not even stop. Any mod that wrote a game asset after boot from the thread that runs the world (an ability reload, a resistance effect generated on a gear change, a stat registered from an admin page) waited on a lock that same thread was already holding, and nobody could move until the process was killed. The library owns the one way to write an asset store after boot: inline when it is safe, and on a thread of its own when the caller is on a world thread, handing the result back when it lands.
- Fixed: placing a block where building is off earned XP anyway. The game announces a placement before it decides whether the world allows one, and refuses without cancelling, so in a world with building off (the Forgotten Temple, a protected dungeon) the block never went down, the item came back, and every mod listening still paid out. The library asks the world's own two building permissions before it counts a placement, so no XP, no objective, no statistic and no placed-block mark for a placement that never happened.
- Fixed: a step's item picture draws. A craft or gather step naming an item laid out the width of its picture and drew nothing in it, on the giver's screen, in both tabs of the objective book and on a board's contract; a creature's portrait drew as intended.
- Fixed: a character a mod authored is drawn as what it wears. A "speak with" step, and the placement admin page's role picker, addressed a portrait by the role's own id, and a role a mod authored under a name of its own has no still under that name. The picture is looked up by the model the role wears, so every quest giver, trainer and broker is pictured.
- Fixed: a step calls an item by its name, not a tidied-up version of its id. A step asking for something guessed the name from where a name is usually written: right for anything the base game ships, wrong for an item a mod named its own way. A step asks the item what it is called.
- The search field is one shared row. A screen with a search box uses the library's own field, Search and Clear, worded in nine languages, and whatever was typed but not yet searched survives a filter or sort click.
- A tally key, and a saved quest's id, read under any spelling. A lifetime tally is matched without regard to case and re-spells itself the way its writer spells it, so a mod may change a key's casing (
mob_killstoMob_Kills) with no migration and no save left behind; a quest's saved progress is found under any casing of its id the same way.
For modders
- New:
HudPanels, the one call that puts a value on a bar.HudPanels.moved(player, rowId, delta, reading, display)names a row by the measured thing's own id, the delta, where the value now stands and how the row looks (label, icon, colour, order, linger, held, a total rather than a gain, the key its number is worded on, the two words at the bar's ends);movedInWorldputs it on the World bars,itemMoved(player, itemId, quantity)names an item and a count and nothing else, andfadeAllsends a held ledger away together. No provider is registered and nothing is authored: the reporter already knows where the value stands. - New:
asset/AssetStoreWriter, the one way to write an asset store after boot. Inline and synchronous when the caller holds no world read lock, queued on a daemon thread with the result handed back when it does;offThreadruns a whole pass there. Every engine store mutator called anywhere else is a build failure in the consumers that adopt the rule. - New:
world/BuildPermission, the world's own two building permissions asked as one question, read by the placement producer before it counts a placement. - New:
Notifytakes aTag, so a repeat rewrites its own line, andFeedbackMomentAsset.ToastgainsMerge;feedback.moment.FeedbackSurfaceslets a surface that already spells a moment out claim it off the feed. Nothing takes a notice off the feed once sent, soflushFeedis gone: a value that moves often belongs on a bar. - New:
NativeNames.itemNameMsgandtargetNameMsgask the item asset for its own name before any convention key is guessed. RewardGrants.GrantOutcomeanswers a receipt, and a fourthRewardHandler.grantform reports what a grant handed over;QuestEngine.AcceptCheckcarrieswaitMsandLockReasonstakes the wait;ContentText.title()ends at the first step's line. Breaks a mod that calledRewardChips.itemChip, which is removed: the item form reads a/giveline itself now.- New primitives.
ItemMatch, the one item-identity match (exact id, native tag, resource family, and any-of);BlockPatternandPatternIndex, structure-pattern matching over a caller's own cells with every rotation and mirror precomputed;Vec3i, a whole-block offset leaf that refuses a decimal;BlockOps, single-block read and write plus the block identity reads (a lit and an unlit block compare equal);BlockRecordSection, a per-block record of your own type saved with the chunk;BlockStash, what a block position is holding for players, saved with the chunk;OwnerLayerReader, the one reader of an id-keyed owner file;AbstractTargetPlayerCommand, the per-player admin verb walk once;NativeEventSeam, the guarded engine-bus dispatch once;FactorRegistry.registerOverride, for a registry answering a few of its own seeded ids differently without a warning;icon.IconSpecandui.icon.IconRenderer, the one picture reference and the one seam that paints it;icon.Portraits, where the client keeps its still of each creature;inventory.ItemIds.exists, the honest question about an item id. The deferred-codec forwarder andContentTextAssetmove into zc-core, and twelve of the wiring root's phase bodies move into the modules that own them; nothing a consumer calls changes. - Fixed: a block-shaped prop is the size its caller asked for. Every block-shaped display item rendered at twice its authored size; the sawmill's placed logs drew as a whole block sitting on the bench.
- Fixed: one shared row template existed twice.
ZigDetailLine.uishipped from two modules at one path, so an edit to the wrong copy did nothing; it lives once.
This mod has no additional files

