Hytale Stable-5 Migration
All Glymera plugins updated for Hytale Server 0.5.x (Stable 5)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All Glymera plugins have been updated for compatibility with Hytale Server 0.5.x (Stable 5). The previous versions targeted Hytale Server 0.4.x (Stable 4).
This document covers what changed in the Hytale Server API between Stable 4 and Stable 5, and which adjustments were required across plugins so that things keep working.
◆ Why a new major version
Stable 5 introduced a number of source-incompatible API changes. A plugin compiled against Stable 4 will either fail to load, fail silently on first use, or — in a few cases — crash the world thread. Because the surface of change is large, every plugin received a new major version number, even when the only functional behaviour change was a manifest flag.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ What changed in Hytale Stable 5
▸ Vector math
- Internal Hytale vector types were replaced by JOML.
- com.hypixel.hytale.math.vector.Vector3d/3i/3f → org.joml.Vector3d/3i/3f
- Rotation helpers now use the Rotation3fc interface where the older API took a concrete Rotation3f.
▸ Particle / Sound API
- SpawnParticleSystem constructors gained additional arguments.
- PlaySoundEvent3D / ambient sound registration semantics tightened — long-running or looped sounds attached to a block must now use the block-state AmbientSoundEventId path; firing them with PlaySoundEvent3D from a tick handler no longer behaves correctly.
▸ Asset pack registration
- AssetModule.registerPack(...) now requires a PackSource parameter (use PackSource.MODS for plugin-installed packs).
- The IncludesAssetPack manifest flag is now strictly enforced. If a plugin both declares IncludesAssetPack: true and registers a runtime pack from its setup code, Hytale detects this as a duplicate registration and aborts boot with "Duplicate asset pack ... Remove the duplicate." For affected plugins IncludesAssetPack is now set to false; the actual asset pack is installed by the plugin at startup as before.
▸ HUD / UI system
- The HudManager API has moved to a keyed model — HUD entries now require a stable key and explicit lifecycle hooks.
- InteractiveCustomUIPage event bindings are wiped if the page is rebuilt while the client is processing a click. Plugins refreshing a HUD per tick had to throttle the rebuild rate (commonly to 1 Hz) so button presses are not lost.
▸ Player handles
- The Player component and the PlayerRef reference have been split. Plugins previously juggling one or the other now need to consider both.
- ServerPlayerListPlayer requires a worldUuid field — entries without it are silently dropped from the tab list.
▸ Entity utilities
- EntityUtils.toHolder(...) was removed. Lookups need to go through the entity store directly or via Ref<EntityStore>.
▸ Damage system
- Resistance fields on EntityEffect (damageResistanceValuesRaw, damageResistanceValues) now expect ResistanceModifier[], not StaticModifier[]. Plugins that previously injected resistances via reflection now use the ResistanceModifier(ResistanceCalculationType, float) constructor.
- The corresponding JSON CalculationType value "Multiplicative" is no longer accepted for damage resistance — it must be "Percent". Migrating large packs needed a bulk rewrite of Potion/Effect JSONs.
- Lethal-damage detection: EntityStatValue#getMin() is no longer a usable death-threshold. Lethal checks now compare the post-damage health against 0.0f directly. Plugins relying on the old behaviour would silently fail to fire and the player just died.
▸ ECS / system tick safety
- It is no longer legal to call mutating store methods (addComponent, removeEntity, …) directly from inside a system's tick handler. Doing so now throws IllegalStateException: Store is currently processing! Such calls must be deferred: either via the system's CommandBuffer, or by scheduling onto the next world tick with world.execute(...).
▸ Items, weapons and recipes
- Custom swords must declare Tags.Type: "Weapon" (not "Tool"), and they need their own complete InteractionVars block — these are no longer inherited from the parent template under Stable 5. A custom weapon without its own InteractionVars will spawn but cannot deal damage.
- Recipe bench IDs and recipe categories are now validated against the asset registry. Mistyped values cause Hytale to silently drop the recipe with no error message.
▸ Cosmetics
- CosmeticsToHide now only accepts a restricted, enumerated set of values. Custom values are rejected at asset-load time.
▸ Server authentication
After every Stable update the server's OAuth credentials must be refreshed:
If the server is still on cached OAUTH_STORE credentials after a Stable update, every incoming player connection is rejected with serverAuthUnavailable and the client only sees "QUIC handshake failed".
- auth logout
- auth login device
- Open the printed verification URL, complete the device authorisation
- auth select <profile>
▸ Manifest / ServerVersion
- Stable 5 enforces a recognisable ServerVersion declaration in each plugin's manifest.json. A malformed value prevents the server from booting. Glymera plugins declare "ServerVersion": "*" to remain agnostic across patch versions.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
◆ Plugin-data path
The plugin-data directory used by all Glymera plugins is now:
mods/de.glymera_<PluginName>/
(Previously it wasplugins/<PluginName>/.) Existing configuration files are not migrated automatically — if you want to keep custom configuration from an older install, move the relevant files from the old plugins/ location into the new one before first launch.
GlymeraMegaChest - Changelog
v5.0.0 (2026-05-23)
Single-issue release fixing a Windows-specific Network Chest persistence bug reported by BottenRastrd on 2026-05-23.
Network Chests are now persisted on Windows hosts
BottenRastrd reported that under v4 on his Windows installation: "I place a network chest (or multiple chests) and they work as intended. If I save the game, return to the main menu, and reload the game the chest cannot be opened. Additionally, if you break the chest (which shouldn't be possible if it has items inside), it disappears and doesn't go into your inventory. There are no JSON files being written at all in the 'network' folder."
Three symptoms, one root cause.
Root cause. Network pools were keyed by id "net:" + ownerUuid and that id was used directly as the on-disk filename (plugins/GlymeraMegaChest/network/net:<owner-uuid>.json). The colon is legal on Linux/ext4 — so every internal test passed against the Linux dev server — but on NTFS the colon is reserved for alternate data streams. FileOutputStream of net:<uuid>.json.tmp raises IOException on Windows, which saveChest catches and silently returns from. Nothing ever made it to disk. Because the in-memory chests map still held the pool until restart, the chest looked fine until the player quit; on the next load, no JSON to read, no entry in posToChest, the UI wouldn't open, and vanilla break handling with "DropList": "Empty" kicked in — block and contents vanished without a trace. Standard Mega Chests were unaffected because their id is a plain UUID with no colon.
Fix. Pool id prefix changed from "net:" to "net_" (single character, single source-of-truth constant NETWORK_ID_PREFIX). The underscore is legal on every filesystem the plugin can plausibly run on. saveChest, deleteChestFile, and loadChests all derive the filename from c.id so no other code-paths needed changes.
Migration. Linux servers that ran v3 or v4 already have net:<uuid>.json files on disk. loadChests now detects the legacy prefix at startup, rewrites c.id in memory, and atomically renames the file to net_<uuid>.json (via Files.move). The rename is one-shot and idempotent; once renamed, subsequent loads see only the new prefix. If the rename fails (e.g. permission denied), the in-memory id is still corrected and the next saveChest writes a fresh file under the new name. Customers on Windows had no v4 network files at all (the bug we are fixing), so there is nothing to migrate there.
Compatibility
- v4 data on Linux migrates automatically on first start. No manual file rename required.
- v4 data on Windows is empty by definition — nothing to migrate.
- No save-format change beyond the id-prefix swap. The chest contents (items, positions, etc.) are byte-identical.
- All in-world placed chests and the per-owner network pool are entirely preserved.
v4.0.0 (2026-05-16)
This release rolls up everything addressed from the v3.0.0 CurseForge bug-report thread: a crash-safe persistence rewrite, a header-bar UI fix, an impossible-to-craft recipe corrected, and a deliberate "no" to workbench-pulls-from-chest integration.
1. Persistence: chests no longer lose contents after a hard kill
- saveChest rewritten as an atomic four-step: serialize under synchronized(c), write to .tmp, fsync, atomic rename. A crash at any point leaves the previous good copy intact.
- loadChests now self-recovers from .tmp siblings if the target JSON is missing or unparsable.
2. UI: trailing >-button stays inside the container
- #HeaderBar padding extended with Right: 16 to stop the pagination button from being pushed past the container edge.
3. Network Chest recipe is finally satisfiable
- Recipe ingredient changed from Furniture_Temple_Light_Chest_Large x 1 (does not exist as inventory item) to Furniture_Temple_Light_Chest_Small x 2.
4. Workbenches reading from MegaChest is intentionally not added
- By design. Native crafting benches query per-block native containers; the MegaChest's 1080-slot JSON-backed storage cannot be surfaced through that mechanism without a fragile sync layer.
v3.0.0 (2026-05-02)
- Second chest variant: Network Chest with shared per-owner item pool
- Smart break rule for Network Chests
- New OP command /megachest givenet [player]
v2.0.0 (2026-05-01)
- Deposit Manager sub-page with per-slot, per-section and bulk deposit options
v1.0.0 (2026-04-25)
- Initial release
- Paginated mass-storage chest: 108 slots x 10 pages = 1080 slots, default 999,999 items per slot
- Custom UI page with search, page navigation, Deposit Inventory button, per-slot click-to-take
- Auto-sort on UI close, owner-only 3-layer protection, drop-safe block
- Crafting at the Alchemybench, compact quantity display, per-slot durability percentage
- /megachest give and /megachest reload commands
GlymeraMegaChest - Changelog
v4.0.0 (2026-05-16)
This release rolls up everything addressed from the v3.0.0 CurseForge bug-report thread (BottenRastrd 2026-05-12, Walomart 2026-05-06): a crash-safe persistence rewrite, a header-bar UI fix, an impossible-to-craft recipe corrected, and a deliberate "no" to workbench-pulls-from-chest integration. All four were verified in-game against the live Dev server before release.
1. Persistence: chests no longer lose contents after a hard kill
BottenRastrd reported that previously-placed Network Chests became unopenable after quitting to the main menu and returning, with the net files in the network/ folder showing 0 bytes. Standard Mega Chests showed the same symptom under restart pressure.
Root cause: v3 saved each chest with FileWriter, which truncates the target file to zero bytes the moment it is opened, before gson writes anything. If anything went wrong between that truncate and the final stream close — JVM kill (SIGKILL), ConcurrentModificationException on c.items while gson was streaming, an I/O error, OOM during serialization — the target JSON file was left empty on disk.
Fix: saveChest was rewritten as an atomic four-step:
1. Serialise the chest to a String under synchronized (c). A ConcurrentModificationException mid-serialisation now aborts the save and leaves the previous good copy on disk untouched.
2. Write the bytes to a sibling <id>.json.tmp.
3. FileOutputStream.getFD().sync() to flush OS buffers to the disk.
4. Files.move(tmp, target, ATOMIC_MOVE, REPLACE_EXISTING) — POSIX-atomic rename. The target points either at the previous good copy or at the new complete copy at every instant, never at a half-written file.
loadChests now self-recovers: if a target <id>.json is missing or unparsable, the loader looks for a sibling <id>.json.tmp and, if it parses cleanly, promotes it to the target (atomic rename again).
Verified with a deliberate SIGKILL test against a populated v4 server: chests/network folders had no 0-byte files, no leftover .tmp siblings, and every item placed before the kill was still in-game after restart.
2. UI: trailing >-button stays inside the container
Walomart reported the UI buttons being "out of GUI". The pagination >-button on MegaChestPage extended roughly halfway past the right edge of the visible container.
Root cause: MegaChestPage.ui #HeaderBar uses LayoutMode: Left with a FlexWeight: 1 search container in the middle. Hytale's flex algorithm sizes the FlexWeight element from the remaining space without reserving a right-edge buffer for the trailing fixed widths.
Fix: #HeaderBar padding extended from (Bottom: 4) to (Bottom: 4, Right: 16). The 16-pixel right pad stops the Left-layout flow early enough that the trailing > stays inside the container.
3. Network Chest recipe is finally satisfiable
BottenRastrd: "How am I supposed to get this? I make two small ones, place them next to each other to make a Large one, break the large one, and have two small chests again."
He was right. The v3 recipe required Furniture_Temple_Light_Chest_Large as an input, but that item does not exist as an inventory item. No player could ever satisfy the v3 recipe.
Fix: Recipe ingredient changed from Furniture_Temple_Light_Chest_Large x 1 to Furniture_Temple_Light_Chest_Small x 2. Bench requirement (Alchemybench / Alchemy_Potions) and the 3x Ingredient_Life_Essence_Concentrated co-input are unchanged.
4. Workbenches reading from MegaChest is intentionally not added
BottenRastrd asked: "The workbenches don't 'see' what is in the network chest. Is this intentional?"
Yes, by design. Native Hytale crafting benches pick up nearby item containers via CraftingManager.getContainersAroundBench, which queries a spatial index of blocks that declare BlockEntity.Components.ItemContainerBlock in their JSON. Adding that component to the MegaChest blocks would create a parallel 36-slot native container sitting next to the plugin's own 1080-slot JSON-backed storage. The two storages would not be synchronisable without a fragile sync layer.
For the Network Chest the model breaks down completely: a single per-owner pool sits behind N block instances, and there is no sensible way to surface "what is in the owner's pool" through a per-block native container.
The MegaChest stays as a personal pool-storage tool that lives next to the vanilla crafting flow rather than inside it. Players who want a workbench-feeding chest should keep using the vanilla Temple Light or Royal Magic Chest for that role.
Compatibility
- No data migration needed. v3 chest JSON files are read by v4 unchanged.
- Any 0-byte JSON files left behind by a previous v3 crash are still unrecoverable — but a .json.tmp sibling, if present, will be picked up automatically on the next start.
- All in-world placed chests, the per-owner network pool, and the save format are entirely untouched.
v3.0.0 (2026-05-02)
New Features
- Second chest variant: Network Chest — a Temple Light double-chest with a soft lavender tint. Every Network Chest a player places shares a single per-owner item pool.
- Smart break rule for Network Chests: allows breaking freely as long as at least one other Network Chest is placed. Blocks breaking only when it's the last chest AND the pool is non-empty.
- New OP command /megachest givenet [player].
- Standard Mega Chest unchanged.
v2.0.0 (2026-05-01)
New Features
- Deposit Manager sub-page with per-slot, per-section and bulk deposit options. Hotbar is still never deposited.
v1.0.0 (2026-04-25)
- Initial release
- Paginated mass-storage chest: 108 slots x 10 pages = 1080 slots, default 999,999 items per slot
- Custom UI page with search, page navigation, Deposit Inventory button, and per-slot click-to-take
- Auto-sort on UI close, owner-only 3-layer protection, drop-safe block
- Crafting at the Alchemybench, compact quantity display, per-slot durability percentage
- /megachest give and /megachest reload commands
GlymeraMegaChest - Changelog
v3.0.0 (2026-05-02)
New Features
- Allows breaking any chest freely as long as the owner still has at least one other Network Chest placed — the pool stays accessible.
- Second chest variant: Network Chest — a Temple Light double-chest block with a soft lavender tint (item id GlymeraMegaChestNetwork_Block). Every Network Chest a player places shares a single per-owner item pool. Drop something into one Network Chest and it's instantly available in every other Network Chest the same player owns, anywhere in the world.
- Smart break rule for Network Chests. Unlike the standard Mega Chest, which refuses to break while non-empty, the Network Chest variant:
- Blocks breaking only when it's the last Network Chest in the network AND the pool is non-empty, with the message "This is your last network chest. Empty the storage first or place another network chest."
- The pool itself is never destroyed by a break; items remain in the player's pool until they are taken out through any Network Chest, or until both the pool and the chest count reach zero.
- New OP command /megachest givenet [player] for handing out Network Chest items.
- Standard Mega Chest is unchanged. Same crafting, same model, same per-chest standalone behavior.
Why
Customer feedback (CurseForge): players building castles and village settlements wanted crafting benches in different themed buildings to draw from a single shared stockpile. The Network Chest variant solves the storage half of that problem out of the box, while leaving the standalone Mega Chest variant intact for players who want a per-location chest.
Crafting
Network Chest is crafted at the Alchemybench (category Alchemy_Potions):
- 1x Furniture_Temple_Light_Chest_Large
- 3x Ingredient_Life_Essence_Concentrated
The single craftingEnabled config toggle now governs both variants. OPs can hand chests out via /megachest give (standard) and /megachest givenet (network) regardless.
Technical Details
- New block id GlymeraMegaChestNetwork_Block. Model: Decorative_Sets/Temple_Light/Chest.blockymodel (the native 2-block double-chest), HitboxType: Chest_Large, custom texture with a gentle lavender tint applied per pixel from the original Temple Light chest texture.
- ChestData gained a kind enum (CHEST / NETWORK) and a positions: List<ChestPosition> field. Standard chests keep their single worldName/x/y/z triple; network pools use positions instead and the id is "net:" + ownerUuid.
- Storage layout: Standard chests serialize to plugins/GlymeraMegaChest/chests/<uuid>.json (one file per placed chest). Network pools serialize to plugins/GlymeraMegaChest/network/net:<owner-uuid>.json (one file per owner).
- posToChest continues to map every block position to a single ChestData id, so the existing MegaChestUseBlockSystem works for both variants without modification.
- New event system MegaChestNetworkPlaceBlockSystem mirrors the standard place-handler with the same PendingPlace + tryConfirmNetworkPlace after-tick check.
- MegaChestBreakBlockSystem was extended with a kind == NETWORK branch implementing the smart break rule.
- MegaChestDamageBlockSystem and MegaChestCraftRecipeSystem accept both BLOCK_ID and BLOCK_NETWORK_ID so the 3-layer protection and the craftingEnabled toggle cover both variants.
- Deposit deny-list was extended to refuse BLOCK_NETWORK_ID as well.
v2.0.0 (2026-05-01)
New Features
- Deposit Manager sub-page: Clicking the "Deposit Inventory" button now opens a dedicated picker page where you can click any individual slot to deposit just that one stack, use bulk buttons Deposit Storage / Deposit Backpack / Deposit All, or hit Back to return to the chest's main view.
- Hotbar is still never deposited, even on "Deposit All".
v1.0.0 (2026-04-25)
- Initial release
- Paginated mass-storage chest: 108 slots x 10 pages = 1080 slots, default 999,999 items per slot
- Custom UI page with search, page navigation, Deposit Inventory button, and per-slot click-to-take
- Auto-sort on UI close, owner-only 3-layer protection, drop-safe block
- Crafting at the Alchemybench, compact quantity display, per-slot durability percentage
- /megachest give and /megachest reload commands
GlymeraMegaChest - Changelog
v2.0.0 (2026-05-01)
New Features
- Deposit Manager sub-page: Clicking the "Deposit Inventory" button no longer dumps your whole inventory into the chest at once. It now opens a dedicated picker page where you can:
- Click any individual slot in your Storage (or Backpack, if you have unlocked capacity) to deposit just that one stack.
- Use the bulk buttons Deposit Storage / Deposit Backpack / Deposit All to mass-deposit a single section or everything at once.
- Hit Back to return to the chest's main view.
- Hotbar is still never deposited, even on "Deposit All". Equipped tools, weapons, and quick-access items stay where they are.
Why
Customer feedback (CurseForge): with the old all-or-nothing button, players had to either empty out items they wanted to keep before opening the chest, or fish them back out of the chest afterwards. The new picker makes selective deposits a one-click operation while keeping the existing one-button bulk-deposit available for the common case.
Technical Details
- New page class MegaChestDepositPage extending InteractiveCustomUIPage<DepositEventData>. Opened by the existing "Deposit Inventory" button on MegaChestPage instead of running the deposit immediately.
- New UI asset MegaChestDepositPage.ui with two slot grids (StorageGrid, BackpackGrid) plus three bulk buttons and a back button. Slots reuse the existing MegaChestSlot.ui template, including durability percentage display.
- Backpack section is rendered only if Inventory.getBackpack().getCapacity() > 0; otherwise a "none unlocked" hint is shown.
- depositPlayerBackpack(...) was split into: depositContainers (bulk path, walks one or both containers), depositSlot (single-slot path used by per-slot clicks), and depositOneSlotInternal (the only place that actually moves items and rolls back the chest add if the inventory removal fails — anti-dupe).
- New codec DepositEventData (Action / Container / Slot) for the sub-page event traffic. Container is a string id ("storage" or "backpack"); the live ItemContainer is resolved server-side at handle time, never sent through the codec.
v1.0.0 (2026-04-25)
- Initial release
- Paginated mass-storage chest: 108 slots x 10 pages = 1080 slots, default 999,999 items per slot (approx 1 billion items total per chest)
- Custom UI page with search, page navigation, Deposit Inventory button, and per-slot click-to-take (left-click = 100, right-click = 4500)
- Auto-sort on UI close (alphabetical by item id, with stack merging)
- Owner-only 3-layer protection (DamageBlock + BreakBlock + UseBlock cancellations)
- Drop-safe block (Material: Solid, no Support, DropList: Empty, markDeco) — never dropped by physics changes
- Block lock when non-empty: a non-empty chest refuses to be broken; only an empty chest returns the chest item to the owner
- Crafting at the Alchemybench from 1x Furniture_Royal_Magic_Chest_Small + 2x Ingredient_Life_Essence_Concentrated. Toggle via craftingEnabled in the config
- Compact quantity display for big stacks (12K, 3.5M, 1.2B) and per-slot durability percentage with green/yellow/red color tiers
- Persistence: one JSON file per chest under plugins/GlymeraMegaChest/chests/
- /megachest give — give yourself a Mega Chest item (OP only)
- /megachest reload — reload config.json (OP only)
