Modder-Facing Patch Notes (UPDATE 7)

Posted by Hytale Team October 12, 2026
Modder-Facing Patch Notes (UPDATE 7)

Update 7: Modder-Facing Changes

World Generation

  • Updated the public HytaleGenerator documentation, which can be found here.
  • World-Gen V2 now manages the Context Size dynamically, isolating the performance impact of adding new Biomes and POIs from the rest of the world. This feature can be configured in the Runtime node’s new ContextPrecision setting.
  • Dropped the GradientWarp Density node’s stale 2D and YFor2D options in both the asset and the node editor. A YOverride into Cache into GradientWarp chain should be used instead.
  • Fixed the SectionSize pin of the Cache Positions node.
  • Added missing tooltips on Density nodes.
  • Reduced severity for invalid Normalizer Density arguments (where FromMin equals FromMax) from Error to Warning to give more time for mods to update. Going forward the new logical Density nodes should be used to create boolean maps instead.
  • Fixed Rotator Density when the target axis is the inverted Y-axis.
  • Enabled an optimization for Plane Density when configured for an anchored horizontal plane.
  • Fixed the Switch and SwitchState Density nodes reading the Default state differently from each other.
  • Fixed gradient Density nodes producing grid-aligned artifacts in generated terrain.
  • Fixed SmoothClamp Density not reading its input.
  • Fixed the Offset Pattern node editor schema to use the proper node type for the Offset vector.
  • Fixed the Manhattan distance in the PositionsCellNoise Density.
  • Fixed the CellWallDistance Density.
  • Improved the quality of the random output from Jitter3d Positions, Jitter3d NodeAction and Random VectorProvider.
  • Props placed with an Anchor PropDistribution no longer come out with random parts missing in an 8x8 grid pattern.

Example Assets

  • Added an Example_Vector_Offset_Constant biome that provides an example of how to build a constant-value random vector offset.
  • Added two example biomes:
    • Example_Vector_Offset_Gradient - uses vector offset with a gradient density to form spikes that point away from a density center.
    • Example_Sin_XValue - uses sin to create a dune shape.

Orbis Tree Prefabs

  • Copied most trees from the legacy Prefabs/Trees folder into Prefabs/Orbis/Trees. You can now use and update these trees in V2 biome prototypes without affecting V1 world generation.
  • Renamed the growth stages for some of the copied trees. Stages that started at Stage_00 now start at Stage_0.
  • The Prefabs/Orbis folder holds work in progress for V2 world generation. It is less stable than the rest of the prefabs folder, so expect changes.
  • Fixed the support chains in the Orbis Ash, Ash_Swamp and Oak prefabs, so every leaf block links back to a trunk or a branch.

Drifting Plains

  • Added the Drifting Plains region with four biomes: Plains Hills, Plains Gorges, Plains Trork and Plains Oak. These are reachable only through the instances command and will make up part of Adventure 1.0.

NPCs & Entities

Encounters

  • An encounter can now force weather for everyone taking part. SetEncounterWeather takes a Weather asset and an optional TransitionSeconds (2 by default), and ClearEncounterWeather puts members back on the normal weather. Both are restricted to InstructionType.Encounter.
  • NPC weather sensors still read world weather only, so Sensor: Weather does not match an encounter's forced sky. Drive that behavior from encounter state or beacons instead.
  • The Example_Boss encounter now uses both actions as a worked example. It forces a Blood Moon on the transition into Phase 1 and clears it when the boss dies.
  • Rewards can be granted via the encounter manager. A new GrantReward action on encounter templates points at a reward asset, and RewardExistsValidator fails the load when that name does not resolve.
  • Encounters can now mark their boss as hard mode on the boss bar. SetEncounterBossBar takes an optional HardMode boolean that defaults to false, and because each action replaces the whole bar state, leaving it out turns hard mode back off.

Charging NPCs

  • ChargeAcceleration is gone from BodyMotionCharge. The new ChargeAccelerationDistance and ChargeDecelerationDistance size each ramp in blocks instead of setting a rate. A role that still sets the old key only warns at load and loses the behavior.
  • RemovedBlockSet is gone as well. IgnoredBlockSet now covers it, and the charge probe treats those blocks as non-colliding and breathable, so list only the blocks a charge really passes through.
  • A charge can now stop at a chosen distance from its target. ChargeDistanceMode picks how that distance is measured (MaxRange, TargetDist or one of the collider modes) and TargetDistanceRange offsets the stop point, with positive values stopping short of the target.
  • The charge ramps are fully shapeable. ChargeAccelerationCurveMode and ChargeDecelerationCurveMode choose whether the curve reads as speed or as distance covered, and the matching MinimumRelativeSpeed, HalfTimeValue, HalfTimeSteepness and EndSteepness keys tune the curve itself.
  • Movement behavior of a charging NPC can now be modified. ProbeRelaxedConstraints accepts Wade, Damage, Drop, Breathe and Fence, so a role can let a charge cross liquid or suffocating blocks it would otherwise refuse.
  • ChargeState gains InStopRange, which a role can match through SensorChargeState. An NPC enters it when its target sits closer than the stop point the configuration asks for.
  • Cleaned up the BodyMotionCharge config descriptions for template authors.

Motion & Pathfinding

  • All the meaningful config values on MotionControllerWalk and MotionControllerBase are holders now, so they can be computed and overridden from a template rather than fixed per role.
  • ThrottleIgnoreCount and ThrottleDelayRange on the find and seek motions now also cover a blocked path, not only a failed search. Setting ThrottleDelayRange to [0, 0] restores the old behavior on an obstacle.
  • Fixed BuilderMotionControllerWalk.getFenceBlockSet throwing when the configured block set was empty or missing.
  • Fixed a pathfinder crash on roles that turn DiagonalMoves off.
  • NPCs that place blocks now write through section storage, so a placement above or below the old height band lands instead of being dropped. An unknown block type key in role data is skipped quietly rather than throwing.
  • NPC block sensors and resource reservations now work at any height instead of being clamped to the 0 to 320 band, so a role can find and reserve blocks in a cubic world above or below that range. The Block sensor also caps Range and MaxHeight at 256, well above the 30 and 10 the shipped roles use.
  • The flying NPC template now exposes KnockbackScale as a parameter.

NPC Combat & Awareness

  • Combat Action Evaluator conditions can now tell apart direct hits and damage over time. RecentSustainedDamage and TotalSustainedDamage take an optional Sources list (Combat, DoT, Environment) and an optional DamageCauses list, and leaving either out still counts everything.
  • The role Damage sensor now takes IncludeDoT, which decides whether damage over time feeds the sensor. It defaults to true, so existing roles behave as before.
  • Creatures can now be made immune to frost. The new Immunity_Slow and Immunity_Freeze marker effects stop the frost slow, chill and freeze effects from applying.
  • A single NPC can now stay damageable in worlds that switch off NPC damage. The new IgnoreDisableNPCIncomingDamage flag on a role makes that NPC ignore CombatConfig.DisableNPCIncomingDamage. Test_Dummy_Stationary has this enabled by default.
  • NPCs can now also switch targets if line of sight to the previous one has been lost. The new TargetRequireLoS parameter on Component_Instruction_Combat_Target_Swap (true by default) keeps the current target prioritized only while line of sight holds, and the default TargetSwitchTimer range moved from [5, 5] to [4, 6] so switches no longer happen in lockstep.
  • Prowling NPCs can now glance around while they search. Component_Step_Generic_Detection has been given an Observe flag (true by default), as well as ObserveAngleRange, ObservePauseRange, and ObserveRelativeTurnSpeed to shape the head motion.
  • NPC roles can now react to being hit. Running Component_Instruction_Hit_Interrupt on a role now gives it a 0.5 second flinch, a 0.7 second attack delay and temporary protection after three reactions occurring within four seconds.
  • Models that use a different flinch move can override FlinchAnimation on that component, which otherwise plays Hurt in the Action slot.
  • Attack instructions and roots need to check for the absence of Hit_Interrupt_Stunned so a queued attack start gets blocked, and offensive roots have to keep their Attack tag for the cancel to find them.
  • A custom attack can tell the system where its counterattack ends. Hit_Interrupt_Begin_Protected_Attack goes after the start gate and Hit_Interrupt_Finish_Protected_Attack after the final swing and recovery, otherwise protection just times out after eight seconds.
  • An NPC role can now hide the healthbar or the damage numbers that draw above it. The new HiddenUIComponents key takes a list of EntityUIComponent ids such as ["Healthbar"], and leaving it out keeps everything visible as before.
  • NPC target swapping now uses the right sense ranges. Every template that references Component_Instruction_Combat_Target_Swap now sets NextTargetRangeView and NextTargetRangeHearing from its own ViewRange and HearingRange.
  • NPC roles can now react to universe-wide game flags. A new GameFlag sensor takes a Flag, a Level and a Comparator.
  • Target leading is now opt-in. Deflection defaults to false, so any NPC role that wants its ranged attacks to lead a moving target has to set it to true.
  • The Friendly flag on the Damage sensor changed meaning. It now enables friendly damage instead of disabling non-friendly damage, so a sensor that relied on the old reading needs flipping.
  • Creatures built on Template_Predator now fight back against ignored NPCs that damage them, which is how Void creatures started reacting to NPC hits.
  • Removed Component_Sensor_NPC_Detection_Player_LOD. Lower range spawn markers or an encounter manager do the same job without the expensive long range line of sight checks.

Spawning & Markers

  • Local spawn beacons can now be limited by weather. An optional WeatherIds list on BeaconNPCSpawn keeps the beacon spawning only while the current weather is one of those, and a placed beacon removes itself and despawns its NPCs when the weather stops matching.
  • The weather a beacon checks is the world's forced weather, otherwise the weather of the environment at the beacon, which a new WeatherResource.getEffectiveWeatherIndex(environmentId) resolves. Per-player weather such as a trigger volume override does not count.
  • Spawn markers can now hunt for a position that actually fits the NPC. SpawnPositionSearch takes Line to follow the marker orientation or Range for a bounded two-dimensional sweep, and MaxHorizontalSpawnOffset sets how far it looks, up to 16 blocks.
  • Markers now check their own placement. ValidatePosition rejects a marker buried too far inside solid blocks, and ValidateBelowPosition rejects one sitting over an empty column, looking up to 192 blocks down.
  • Range searches can now be pinned to the height you placed the marker at. RequireFitAtMarkerHeight restricts the search to vertical spans that contain the marker Y.
  • SpawnPositionSearchDebug reports on a failing search with either Summary or Map diagnostics, and range search failures now log why each candidate was turned down.
  • Spawn position limits are now bounded. MaxDropHeight tops out at 32 blocks, BlockOverlapHeightCompensation at 4, and non-finite or out-of-range asset values are rejected as the asset decodes.

Memories

  • Roles can now hand out their Memory on death rather than on approach. MemoriesUnlockedBy takes Proximity (the default) or Kill, and MemoriesKillRange sets how far a player can be and still be recorded. A Variant role needs its referenced template to declare both, the same as IsMemory.

Trigger Volumes

  • Fixed a trigger volume signaled by an NPC firing its effects twice, so a volume with a single message effect no longer sends the same chat message twice. DestroyTaggedVolumesInteraction picked up the same guard.

Entity Components

  • Fixed the UIComponentList entity component ignoring its Components key, which gave every entity every component. An entity that sets the key now receives only those components, and the list is resent when it changes.

Items & Interactions

Abilities & Keywords

  • Ability Runestones now carry AbilityKeyword assets instead of dotted tag strings. Keywords live in Abilities/Keywords/ and can declare RequiredAttributes and RequiredInteractions that any Runestone carrying them has to provide.

  • ItemAbility is now split on Slot into PrimaryItemAbility, which lists its Keywords, and SupportItemAbility, which gates on RequiresAnyKeyword, RequiresAllKeywords and ExcludesAnyKeyword. The editor only shows the fields that apply to the slot you picked.

  • Damage boosts can now carry through to effect ticks. ActiveEntityEffect gained a DamageMultiplier and ApplyAbilityEffects a DamageAttribute, which is how Damage Up now scales the poison imbue.

  • Signature attack mana returns now live in the shared signature damage assets and weapon variants inherit them. The empty on-hit overrides that were blocking the shared values have been removed from the variants, so variant damage and sounds are untouched.

  • Added Rend and Wither entity effects under Entity/Effects/Abilities/ for the two new Runestones to apply.

  • Poison is now a subtype of Elemental damage in Poison.json, so anything that treats Elemental damage specially picks poison up as well.

  • A raycast cast can now reach further the stronger it is. A new DistanceAttribute field on RaycastSelector names an ability attribute, and the resolved value multiplies Distance on the block raycast, the entity search sphere and the debug arrow, matching the SizeAttribute binding on the AOE and stab selectors. If the cast does not carry the attribute, the distance is unchanged.

  • Added Icicle and WindStrike_Projectile models for the reworked Charged Shot and Wind Strike visuals.

Food, Potions & Cooldowns

  • The Potion_Stamina_Cooldown entity effect has been removed. An asset pack that gated on it should read the Potion_Consume_Stamina cooldown id instead.

  • Any consumable can now start a cooldown when a drink finishes. Consume_Charge_Potion_Fast and Consume_Charge_Potion_Fastest read an optional ConsumeCooldown interaction var, which defaults to no cooldown.

  • Added Consume_Potion_Health_Cooldown, Consume_Potion_Stamina_Cooldown, Condition_Consume_Potion_Health and Root_Secondary_Consume_Potion_Health as reusable interaction assets for your own potions.

  • Every potion built on Potion_Template now inherits its stack size of 10 instead of overriding it, so editing the template changes all 19 of them at once. Antidotes, potion bottles and decorative potions do not use the template and keep their own stack sizes.

  • The Food_Instant_Heal_T2, _T3 and _Bread effects are gone. Every food now uses Food_Instant_Heal_T1.

Glider

  • Glider tuning was rebuilt for the new movement state machine. The old FallSpeedMultiplier, HorizontalSpeedMultiplier, TerminalVelocity and Speed values on the item are gone, replaced by a wider set of fields on Template_Glider that also cover the dive and the climb.

  • The Condition interaction now includes a parameter for the Gliding movement state.

Weapons & Ability Slots

  • Mace item animations gained a SwingUpLeft variant for abilities.

  • Items can now hang an interaction off a fourth ability slot instead of only the three, and the crossbow's Root_Common_StatAmmoReload_Entry reload moved onto it in Template_Weapon_Crossbow.

Dropped Items

  • Dropped items can now merge over a distance you pick. A new inherited MergeRadius key on ItemEntityConfig sets how far in blocks a dropped item looks for others to stack with. Leaving it at -1.0F falls back to the world default.

Portal Keys

  • Portal keys can now cap how many times each player enters. PortalKey carries the per-player limit, and the portal device pages show the limit and the entries left.

Movement Items

  • Removed the debug-only Debug_Movement_Boots armor.

  • Items can now play a separate sound to the wearer when they use an extra jump. A new ExtraJumpLocalSoundEvent on ItemMovementSettings takes a one-shot event and accepts stereo files, and the Rocket Boots use it alongside the world sound.

Beams & Projectiles

  • Fixed a piercing projectile that could stop ticking and sit in the world forever.

  • Textured beams can now be rendered between entities. A new AttachBeam interaction hangs a beam between the interaction context owner and the entity you name in the parameter, which is how the Hookshot draws its rope.

  • Projectiles can now be given a lifespan. A Lifetime value on the Projectile interaction despawns the projectile once that duration runs out.

Selectors

  • Cylinder area selectors now respect their size attribute. AOECylinderSelector multiplies its range and height by the sizeAttribute value, so an ability that scales its area finally grows the cylinder with it.

  • Selectors now honor their target filter and ignore owners when filtered.

Interaction Behavior

  • Cleared a batch of warnings out of the item interaction assets. Unused fields are gone from the teleporter config, the glowing mushroom eating interactions, the quartzite gravel half block, the guard bash and the staff interactions, and the geyser ambient sound key is spelled correctly again.

  • The blockymodel files for most food items were rebuilt to drive the new eating animations. Custom animations that reference the old node names may break.

  • Explosions can now define the damage cause. A new EntityDamageCause field on ExplosionConfig sets the damage cause applied to entities in range, and it falls back to Environment when you leave it out.

  • Fixed a crash when you added an entry to OnHitEffects on an ItemAbility. An empty entry used to throw a NullPointerException in the asset editor and on the server, and validation now rejects it instead.

  • Every bed now shares one Block_Bed root interaction carrying the Type=Bed tag, so a bed no longer defines its own use interaction inline.

  • The shared on-hit chain moved out of DamageEntityParent into a named DamageEntityParent_On_Hit. An asset that overrides Next can point back at that chain to keep normal damage and the usual hit effects.

  • A wielding interaction can now let stat regeneration carry on while it is held. Setting the IgnoreForFlaggedConditions parameter on a Charging or Wielding interaction to true will allow it to be ignored by Charging and Wielding conditions that have the UseIgnoreFlag parameter set to true.

  • Fixed the ChangeState interaction failing when the state it switched to had no interaction sound event id.

Crafting & Recipes

  • A recipe locked behind a bench augment tag can explain itself now. Give the tag an items.tooltips.crafting.augmentTagRequired.<tag> string and the crafting tooltip shows that line while the bench is missing the tag.

Item Quality

  • Item stacks now store a quality only when one is explicitly set. A stack without its own quality follows the quality on its item asset, so an item that gets updated picks the new value up.

  • The /give command gained an optional quality argument that overrides the quality the item asset would otherwise use.

  • ItemQuality assets now inherit from their parent. Every field except LocalizationKey falls back to the parent value when you leave it out, so a group of quality variants can share one set of slot and tooltip textures.

Blocks & Prefabs

Block Ticking

  • TickProcedure.onTick now takes a CommandBuffer<ChunkStore> and the chunk section Ref<ChunkStore> in place of the World and WorldChunk parameters, so any subclass override needs updating. The world is available from commandBuffer.getExternalData().getWorld().
  • Block tick procedures now run in chunk sections at any height. Scheduled ticking used to stop outside Y 0 to 319, so a procedure written for that range has to cope with negative and high coordinates.

Block Breaking Rules

  • Chosen blocks can stay breakable in a world that bans block breaking. WorldConfig.BlockBreakingBypassTag names a tag, and any block carrying it can still be broken while AllowBlockBreaking is off. Explosions follow the same rule.

Block Information

  • Blocks can now show their own name and item description in game without being broken first. Put "Page": { "Id": "BlockLore" } under the block's Use interaction and it reads both from the block item's TranslationProperties. A block with no description opens nothing.

  • The BlockLore page takes an optional TextAlignment key of Left, Center or Right. It defaults to Center.

Block Materials

  • Chapter 1 blocks that were copied from other assets now carry the right material data. Gather types, Fireproof tags, Fuel and Charcoal resources, stray Type: Soil and Type: Wood tags and missing PhysicalMaterialId entries were all corrected across the goblin, Enkindled, Cybercity and Hive Brick sets.
  • The 35 log half slabs now set ResourceTypes of Fuel and Charcoal directly, instead of inheriting Rock from Rock_Stone_Cobble_Half. Oak and Apple half slabs are tagged as wood.

Foliage

  • UseDefaultDropWhenPlaced is gone from 45 foliage assets, so player-placed bushes, berry crops, grass, leaves, moss, vines, reeds and seaweed fall back to their normal drop lists. Prefabs built with that flag no longer hand out the plant itself.

  • Plant_Leaves_Autumn_Floor, Plant_Leaves_Jungle_Floor and Plant_Leaves_Poisoned_Floor each gained a Shears entry in Gathering.Tools.

Farming & Crops

  • WaterGrowthModifierAsset now decides rain exposure from the heightmap, taking the highest opaque block at or below the crop, so a non-opaque block above a crop no longer keeps the rain off it.

Loot Containers

  • Generated loot containers, such as chests found in prefabs, can now be configured to stay open once emptied. The new StayOpenWhenEmpty flag on ItemContainerBlock keeps an empty container in its open block state when the last window closes.

Text Formatting

  • Trigger volume text now resolves a volume tag's value in plain written text, not just behind a translation key. SendMessage and ShowEventTitle both handle it.

  • Fixed formatted text losing a character whenever it met a placeholder it did not recognize, so an unknown {tag} is left exactly as you wrote it.

Asset Schemas & Formats

Event Titles

  • Event titles pick a named style in JSON now. ShowEventTitleInteraction, ShowEventTitleEffect and InstanceDiscoveryConfig all take a Style value.

  • The event title effect on a trigger volume can now pick who sees it. A new Recipient field on ShowEventTitleEffect takes the same options as SendMessageEffect and defaults to the triggering player.

  • The event title action, for WorldEvents, can now pick how the banner looks. ShowEventTitleAction takes an optional Style and an optional Icon, and falls back to the default style when you leave Style out.

  • Instance worlds no longer take DocumentDisplayOnRemoval. A new EventTitleOnRemoval shows an event title while the instance closes, and the close delay follows the title timing. Leave it out and the world closes right away.

  • Event titles can now play a sound alongside the text. An optional SoundEventId on EventTitleConfig fires once the title is sent, and assets that leave it out behave as before.

Trigger Volumes

  • Three new trigger effects handle respawning. SetRespawnPoint takes Origin, Position, Name and ClearExisting, SetWorldSpawn takes Origin, Position, Yaw and ClearPlayerRespawnPoints, and ClearRespawnPoints takes Name and AllPlayers.

  • Trigger volume tags can now be used like variables and compared to each other. TagCondition takes a CompareAgainst field that picks whether the tag is checked against a plain value (the default) or against a second tag named in CompareTagKey.

  • Respawn points can now set which way a player faces. PlayerRespawnPointData and SetRespawnPointEffect both take a Yaw in degrees.

  • Trigger volume PlaySound effects now take VolumeDb in decibels from -100 to 0 and PitchSemitones in semitones from -60 to 12, instead of the old linear Volume and Pitch. The old keys still load from existing JSON, but they no longer appear as rows in the trigger volume editor. Volume is capped at 0 dB, so a trigger can only quiet a sound and never boost it. To make something louder, raise the volume on the sound event itself.

Portals & Instances

  • Portal types now carry the default time limit and entry count. TimeLimitSeconds and AllowedEntryCount on PortalType apply to every key of that type, and a PortalKey only needs the fields when it wants to differ.

  • Portal worlds can now be authored with no time limit at all. PortalType and PortalKey accept a portal without a duration.

  • Portal instance configs now carry a DisplayName, and a world's display name reaches join and leave messages as a Message, so it localizes instead of printing the raw key.

Map Markers

  • Map marker overrides can change the display name of a marker. A new DisplayName key on MapMarkerOverride takes a localization key to use instead, and the marker override add command accepts it alongside --icon and --global.

  • World map markers can be drawn larger. A new IconSize on block and objective marker configs takes Default or Major, and Major renders at 64 pixels with a matching hitbox and text offset. Markers that leave it out keep the standard size.

  • Block map markers can now include a temporary alert for players when they get added to the compass. A new optional Alert block on BlockMapMarker takes Icon, Tint, Duration (5 seconds by default) and Timeout (10 seconds by default), and both times accept 0 to 30 seconds.

  • An alert fires every time the client adds the marker, so a join, a world change or walking back into marker range all show it again. A server update to an existing marker keeps the running alert rather than restarting it.

  • A block map marker can show a different icon on the compass than on the map. The goblin breach items and prefabs set CompassIcon to the new breach icon.

Encounter Assets

  • Encounter asset files must now declare the top-level Class key. Role files can still leave it out and fall back to Role.

  • Grouped the loose encounter manager assets into folders by purpose, covering examples, music, elite NPCs and world events. Encounters still bind by bare file name, so the move changes nothing at runtime.

Intro Pages

  • Added a shared intro modal template at Common/UI/Custom/Common/IntroModal.ui, holding the layout, styles and bullet rows that AbilityBenchIntro.ui and MemoriesUnlocked.ui now both build on.

Damage & Death Messages

  • Damage types now carry their own death message. A new DeathMessageKey on each damage asset replaces the old text that was glued together at runtime, and entity effects such as the poison stacks set theirs the same way.

UI, Beams & Visual Assets

  • UI sprites gained two fields. Color tints a sprite and lets you control its opacity, and KeepLastFrame holds an animation on its final frame instead of snapping back to the first.

  • Added a Beam asset type under Entity/Beams with a single TexturePath field. The texture has to sit under Beams/ or Trails/.

  • ModelVFX assets now inherit every field from their parent. ModelVFX.CODEC uses appendInherited throughout, so pointing an asset at a parent no longer leaves most of its values unset.

  • Custom UI pages can now reuse the runic console chrome. Common.ui gained a @RunicPanel group plus the @RunicTitleStyle, @RunicHeadlineStyle and @RunicBodyStyle text styles, and the title style shrinks to fit down to 12px.

  • Custom content that overflows a texture atlas now falls back to the missing texture and logs a warning instead of vanishing without a word. Atlases also pack across several pages, up to 16 for the block atlas and 4 for the others.

  • Embedding a Trail asset no longer disconnects the client. A trail that sets no texture now falls back to Trails/Basic.png instead of failing validation.

  • Content can now ask for confirmation before it acts, with a new Confirmation page for OpenCustomUI. It takes TitleKey and MessageKey for the text, optional ConfirmKey and CancelKey for the buttons, a required Success root that runs on confirm, and an optional Fail root for every other way the page closes.

Asset Editor & Schemas

  • Creating a folder in the asset editor now makes any missing parent folders along the way, so you can organize a brand new asset type without making a throwaway asset first.

  • Schema validation for Float2ObjectMap fields now matches what the codec really reads and writes. The generated key pattern accepts scientific notation such as 1.0E-4 and leading-dot values such as .5, and it no longer lets non-numeric keys like 1x2 slip through.

  • Fixed checkboxes in the asset editor showing as unchecked for fields whose schema default is true.

  • Fixed color fields losing their defaults. ColorCodec and ColorAlphaCodec now read the default value, and LightColor writes one byte per channel.

  • Fixed an error when an asset pack was refreshed. AssetModule was closing the pack’s ZIP file system before the unregister listeners had finished reading it, so the NPC listener hit a closed file system. The file system now closes after the event is dispatched, even if a listener throws.

  • The Projectile field on the LaunchAbilityProjectile interaction now opens the asset browser, so you can pick a ProjectileConfig from the list instead of typing the id, and the choice is validated.

  • Fixed the asset editor failing to load when a codec description held an unpaired * or _. Those characters now come through as written, and a backslash escape such as \* prints a literal delimiter.

Documentation

  • The particle asset documentation reads properly on the docs site now. Particle, ParticleSpawner, ParticleAttractor, ParticleCollision, ParticleSystem and ParticleAnimationFrame had their doc text reflowed for Fumadocs, and the spawner shape wording is clearer.

Other Asset Changes

  • Spawn points placed below Y 0 now stay where you put them, because FitToHeightMap only fits a point whose Y is Integer.MIN_VALUE rather than any negative Y.

Audio

Music Transitions & Stingers

  • Music can now hand off from one track to another by authored rule. Two new asset types, MusicTransition and Stinger, live in Audio/MusicTransitions and Audio/Stingers.

  • Handoffs can land on a musical boundary instead of a frame. MusicSync picks the moment on the outgoing track (immediate, next beat, next bar, an exit marker or a named marker) and DestinationAlign picks where the incoming track starts on its own timeline.

  • Overlap and crossfade are separate controls now. ExitAt sets the handoff, PlayPostExit lets the outgoing track run to the end of the file, and FadeOutDuration with FadeOutDelay ramps it out instead, following a FadeCurve that defaults to equal power.

  • Music containers picked up a batch of new fields. MusicContainer takes Tags, Align, AlignMarker, ExitAt and Stingers, SegmentMusicContainer takes named Markers, and HorizontalMusicContainer takes AudioState with Phases so it can switch phase from a state axis.

  • Stingers hang off a free-form music event on a container rather than being referenced directly. Anything can post the event, the deepest active container that binds it decides what plays, and stingers sort by priority inside an exclusion group.

  • StateTransition gained PostEvent, so an audio state edge can mark a musical moment without naming a stinger directly.

  • Audio timing now speaks one vocabulary, and the old spellings no longer decode. StateTransition.DurationMs: 2000 becomes Duration: { "Ms": 2000 }, AudioState.DefaultSyncTo: "NextBar" becomes DefaultSyncTo: { "Point": "NextBar" }, and MusicTransition.FadeOutDuration, FadeOutDelay and FadeInDuration each take an object instead of a number of seconds.

  • One music layer can now enter an audio state on its own schedule. A StateDelta takes an optional Fade block with Duration, Curve and Delay, and any field you leave out still falls back to the axis.

  • Fade.Duration and Fade.Delay are BarBeatDuration values, so a subscriber with no tempo keeps only the Ms component. The server now rejects bars or beats on an audio category, an ambient bed or a sound event, and it also rejects a negative fade value or a Fade with nothing set.

Volume Limits

  • Interface sound volume from SoundStyle and SoundEffect is now bounded to +10 dB, which matches every other authored gain field.

  • AudioState volume deltas are now bounded to +10 dB per axis on the per-voice path, the same bound the server already documents. A pack leaning on a bigger per-voice delta gets clamped.

Server & Permissions

Block Commands

  • Fixed /fluid setradius only making one block of the filled region flow instead of all of it, and /block setticking now resolves the chunk section itself and tells you when it is not loaded.

  • The /block point commands and /block row now work at any height in a cubic world, so get, set, getstate, setstate and setticking reach above Y 320 and below Y 0. A section that is not loaded answers with the new server.commands.block.noSection message.

  • /block bulk find-here and /block bulk replace now take their radius in chunk sections and sweep a sphere around you, including the sections above and below the old height range.

  • /block bulk find gained a --chunkY and a --radius option. It searches a sphere around that chunk position, up to the server's maximum view radius, instead of spiraling outward across the world until it times out.

  • Fixed /block bulk replace counting blocks it never changed, and /block setstate throwing on an unknown block id instead of reporting one. A block command that fails partway through now tells the sender rather than going quiet.

  • Fixed a block placed by a /block command into a freshly loaded section staying inert. The command now loads the section as ticking, so the block ticks and its block entity spawns.

  • The block spawner and prefab spawner commands no longer stall the world thread waiting on a chunk. They reply that the chunk is not loaded instead, they work at any height rather than only inside the old column range, and targeting a prefab spawner in an unloaded chunk no longer errors out.

Chunk & Lighting Commands

  • Added a /chunk height command that dumps a column's heightmap for debugging. /chunk fixheight also rebuilds the column into a fresh backend now, so a stored height that sat too high can finally be corrected instead of only ever being raised.

  • Command coordinates written with the _ height flag now answer with a chunk-not-loaded message when the column is not in memory, rather than force loading it on the world thread.

  • Fixed lighting invalidate --one and lighting info --detail always reading section 0, because both passed a section index where a block Y was expected. lighting get, chunk lighting, chunk forcetick, chunk fixheight and chunk resend --clearcache now work on loaded sections at any height, and an absent section answers with the new commands.errors.sectionNotLoaded message.

Instances & Portals

  • Instance edit worlds now load a new InstanceEdit gameplay config that switches on AllowBlockBreaking, AllowBlockGathering and AllowBlockPlacement, so an instance with restrictive rules stays editable.

  • Added a /fragment timer add <seconds> command that adds time to the fragment timer instead of replacing it, which is what triggers the gained time tag on the HUD.

  • Portal instances accessed via TeleportInstanceInteraction can now stay around between sessions when their asset asks for it. Worlds spawned from the portal device summon page still set setDeleteOnRemove and setDeleteOnUniverseStart themselves, so those stay temporary and get swept on the next start.

  • Portal worlds reached through TeleportInstanceInteraction are now removed from disk once the portal world’s timer reaches 0.

  • Fixed a portal world config overriding the settings of an instance you opened for editing. Instance edit worlds now carry an isEditMode flag on InstanceWorldConfig, and PortalWorldUtils leaves those worlds alone.

  • Portal worlds can now offer a Leave Portal button on the map. It is off by default and needs the new leave button flag set on the PortalType asset.

World Events & Gameplay Config

  • World events can now be switched on and off per world with /worldevent enable, which takes true or false and toggles when you leave the argument off.

  • The WorldEvents plugin stores an EnableWorldEvents flag in a new WorldEventsWorldConfig, and new Creative worlds get it set to false.

  • A world can now switch off specific interactions. The new BlockedRootInteractionTags list in GameplayConfig.WorldConfig takes root interaction tags, and anything matching is blocked on the server and hidden from the HUD.

Wilderness

  • Server operators can now check which chunks the wilderness system counts as wilderness and which count as home. The new /wilderness debug [enabled] [player] command tints those chunks green and red on one player's world map and draws matching cubes in the world. Wilderness tracking stays off by default in WildernessConfig, and the command warns when a world has it turned off.

Event Title & Beam Commands

  • The /eventtitle command takes --style in place of --major, and the secondary line now defaults to empty rather than to “Event”.

  • Added a /beam command for development work, with entity, position, spawn and clear.

Install Folder & Sign-in

  • The server now refuses to boot when the content it writes would land inside the launcher's install folder, which every update patches or wipes. The check covers the working directory plus --universe, --prefab-cache and --backup-dir, and it prints the steps to move them somewhere safe before exiting with code 11.

  • Added an --allow-install-dir flag, mirrored by the hytale.allow_install_dir system property, for anyone who wants to run there anyway and accept the data loss risk. Singleplayer runs, --help, --version and a --bare start without --bootstrap skip the check already.

  • Server operators can now run /auth login browser or /auth login device while already signed in, without signing out first. The existing session stays active until the new sign-in finishes, so a cancelled or failed login leaves the server signed in as it was.

View Radius

  • A MaxViewRadius outside 1 to 32 in config.json no longer stops the server booting. The value is clamped in memory with a warning, and the file keeps whatever you wrote.

  • The max view radius command rejects anything above 32 now, instead of 512.

Bans & Kicks

  • Bans and kicks now close every connection an account has open, including Asset Editor connections that previously remained connected.

Other Server Commands

  • The world add command now tells you whether creation succeeded or failed instead of quietly dropping the result.

  • The Asset Editor plugin ships a sample EditorPropertyGallery asset that shows every property control in one file. It stays unregistered until you create mods/Hytale_AssetEditor/config.json with EnablePropertyGallery set to true and restart the server, after which Gallery_AllControls.json opens in the editor.

  • /spawning markers debuginvalidmarkers now highlights invalid marker placements and revalidates markers that are moved or rotated, and /spawning markers autoremoveinvalidmarkers switches automatic removal of failing markers on or off.

  • BuilderTools gained two limits on how much world a single edit loads up front, PrefetchColumnLimit (default 1024) and PrefetchSectionLimit (default 10240). An edit over either limit reads what is already in memory and reports the rest as skipped.

Renames & Deprecations

Density Nodes

  • Three density asset types were renamed, so SmallerThan is now LessThan, SmallerOrEquals is now LessOrEqual, and Select is now Selector.

  • Two more density asset types lost their trailing s, so Equals is now Equal and GreaterOrEquals is now GreaterOrEqual. The node editor entries carry the new names too.

Void Spectre

  • The Void Spectre assets were merged under one name, so anything pointing at the old ids no longer resolves. Spectre_Void is now Void_Spectre across its model, drop list, icon and particles.

  • The Void Spectre's attack interactions were renamed to match what they do. Void_Spectre_Attack is now Void_Spectre_Charge, Void_Spectre_Attack_Damage is now Void_Spectre_Charge_Damage, and the root interaction is now Root_NPC_Void_Spectre_Charge.

Event Titles

  • IsMajor is gone from ShowEventTitleEffect. The Style field covers it, so pick the look you want there instead of flipping a boolean.

Treasure Map Objective

  • The treasure map objective is gone, along with everything it used. The TreasureMap objective task, the OpenTreasureContainer and DestroyTreasureCondition interactions, the LookBlocksBelow and TagBlockHeight world location conditions and the TreasureChest block entity component no longer decode, so any asset that names one fails to load. A world with a placed treasure chest still loads, since the server keeps the component as unknown data.

Portal Curse

  • Renamed the portal curse surface to ephemeral items. AdventureMetadata now carries the ephemeral flag, CursedItems became EphemeralItems, and the /cursethis command is now /ephemeral.

Carryable Block

  • Removed the Carryable_Block item animation asset. The throw now lives in Block.json, and Throw_Carryable_Block points at the new Heavy_Throw animations.

NPC & Spawn Marker Roles

  • The Goblin_Miner attitude role is now called Goblin_Brave, since it covers more than miners.

  • The Spider_Cave_Trigger spawn marker is now called Spider_Cave_Manual, matching how the other manual markers are named.

Audio Files

  • The heal sound Magic/Heal.ogg is now Magic/Magic_Heal_01.ogg, which matches the naming convention, and Magic_Heal_02.ogg sits beside it as the second variation.

Asset Files & Models

  • Asset file Spiwer_Web_Full.png has been renamed to Spider_Web_Full.png, Fig_Blue_.png is now Fig_Blue.png, and the duplicate file Totem_Heal_BeamStart (1).particlespawner has been removed.

  • The Goblin hookshot models are now named after scrap. Hookshot_Goblin.blockymodel and Hookshot_Goblin_Projectile.blockymodel became Scrap.blockymodel and Scrap_Projectile.blockymodel, and Tool_Hookshot.json and Hookshot_Hook.json point at the new paths.

  • The Void tentacle animations moved and were renamed. Bite2 and Bite3 are now Bite_Left and Bite_Right, and Idle and Idle2 sit in the Default folder next to the new spawn animations.

  • Renamed the Bear_Voidtaken_Tentacle_Model and Bear_Voidtaken_Tentacle_Marker_Model server models to Bear_Voidtaken_Tentacle and Bear_Voidtaken_Tentacle_Marker, with the roles that use them updated to match.

Protocol & Networking

Event Titles

  • The ShowEventTitle packet dropped IsMajor in favor of an EventTitleStyle Style field, which breaks any plugin that builds the packet by hand. Styles include Default and Major.

Gameplay Config

  • The world's gameplay config is replicated to the client by a new WorldGameplayConfig packet, carrying WorldConfig, CombatConfig and PlayerConfig structs that mirror the server assets. It goes out when a player joins a world and again whenever the GameplayConfig asset reloads.

Beams

  • The wire carries beams now. BeamConfig and UpdateBeamConfigs ship the beam assets, while BeamInstance and the Beams component update carry the placements, so this needs a matching client.

Limits & Language

  • A peer now rejects a structure that nests inside itself more than 32 levels deep, covering FormattedMessage trees, item categories, command trees, and interaction chains.

  • UpdateLanguage.Language is a required protocol field now instead of an optional one, and the protocol version was bumped for it. It and Connect.Language also widened from a 16-character cap to 100 characters, which fits any .NET CultureInfo.Name.

  • The server now rejects interaction chain sync packets that are missing their chain data, carry a fork without an id, or hold a negative or overflowing operation index. Before this a bad packet threw inside the interaction tick, logged at SEVERE and removed players. Rejections log at FINE now, and the vanilla client never sends packets these checks catch.

Portals & Movement Items

  • The portal state now carries BonusSeconds, the time just added to the fragment timer. The server clears it after the broadcast so later ticks do not replay the animation.

  • ItemMovementSettings gained a trailing ExtraJumpLocalSoundEventIndex, which changes its wire layout. The client and the server have to be built from the same protocol build.

Portal Pages

  • Added the packets OpenPortalSummonPage, PortalSummonPageResult, OpenPortalActivePage, PortalActivePageResult and OpenPortalErrorPage, along with the page values Page.PortalSummon, Page.PortalActive and Page.PortalError. The client rejects a SetPage carrying any of the three.

  • Each portal page answer carries the id of the page it came from, so the server ignores an answer to a page it already replaced, and it rechecks the world, the block and the held key before it acts.

Map Markers

  • Map markers now carry an optional CompassAlertComponent over the wire, with an Image, a Duration, a Timeout and a Tint, so anything that sends a marker can make it alert.

Chunk Environments

  • Environments now stream one chunk section at a time. SetChunkEnvironments is keyed to section coordinates and carries a single section payload, and SetColumn no longer carries environments at all. Clients and servers have to be on matching protocol versions.

Asset Editor Packets

  • Replaced the two-way AssetEditorUpdateAssetPack packet with AssetEditorAssetPackUpdated from the server and AssetEditorUpdateAssetPackManifest from the client. AssetEditorAssetPackSetup now maps pack ids to an AssetPack, which carries the manifest along with IsReadOnly and CanBeDeleted, rather than to an AssetPackManifest.

Asset Loading

  • A server must now declare the true asset size in AssetInitialize. The client disconnects a server that sends more bytes than it declared, and a single asset is capped at 256 MiB.

For Plugin Developers

Block Reads & Writes

  • ChunkAccessor.performBlockUpdate and WorldChunk.setTicking are gone. Use BlockOperations.updateBlockArea for a whole hitbox or BlockSection.setTicking with ChunkSection.markNeedsSaving for one cell, and note that updateBlockArea now takes the ChunkSection as well as the BlockSection.

  • Block writes are moving onto sections. Use BlockOperations.setBlock to make block changes to the world.

  • BlockDataProvider resolves its chunk and fluid sections once per block read instead of on every field access. The readBlockId, readRotation, readFiller, readFluidId and readFluidLevel methods are private now, so a plugin that calls them directly will not compile.

  • Removed the unused WorldChunk.setBlock overloads that took a String, a BlockType, or a BlockType and a rotation, along with BlockChunk.setEnvironment.

  • Removed WorldChunk.breakBlock, IChunkAccessorSync.breakBlock and BlockChunk.getEnvironment(Vector3i). Resolve the section ref with ChunkStore.getChunkSectionReferenceAtBlock, then use BlockOperations.setBlock or the EnvironmentSection component.

  • WorldChunk.getBlockComponentHolder is now allowlisted for BuilderTools and BlockSelection only, since block entity reads go through the section's BlockComponentSection.

  • Removed IChunkAccessorSync.setBlockInteractionState and both WorldChunk.setBlockInteractionState overloads. Interaction state now writes through the BlockSection component of the section ref from ChunkStore.getChunkSectionReferenceAtBlock, which skips the blocking chunk load and the old 0 to 320 height cap.

  • Removed the last WorldChunk.setBlock overloads that took a block id or a block key, along with IChunkAccessorSync.setBlock(String, SetBlockSettings). Block writes now go through BlockOperations on the section ref from ChunkStore.getChunkSectionReferenceAtBlock, which skips the blocking chunk load and the old 0 to 320 height cap.

  • Both getBlockType overloads are gone from IChunkAccessorSync because nothing called them. Read blocks through the chunk section reference from ChunkStore.getChunkSectionReferenceAtBlock instead.

  • Reading blocks without touching a column got simpler. The new BlockReader interface carries getBlock and getFluidId, SectionReader implements it over chunk sections, and SectionAccessor extends it.

  • WorldChunk.getBlockComponentEntity is gone, so block entities come from BlockModule.getBlockEntity, whose world overload now also rejects an invalid section ref. The BlockChunk block, count and ticking accessors went with it, and its (IntBytePalette, BlockSection[]) constructor is private.

Chunk Lookups & Column Accessors

  • Door and refill interactions no longer pull in a neighbor chunk just to update it. An unloaded neighbor is skipped, the same as every other block update.

  • The deprecated IChunkAccessorSync.getBaseBlock is gone. Filler blocks now resolve through BlockOperations.resolveBaseBlockPosition, which takes a ChunkStore and never triggers a chunk load.

  • Seventeen unused members are gone from the chunk access surface, so a plugin still calling them will not compile. That covers IChunkAccessorSync.getBlockComponentHolder, IWorldChunksAsync.getNonTickingChunkAsync(int, int), BlockChunk.getSectionRefAtIndex, BlockComponentSection.getBlockReferences, BlockSection.setChunkSection and getMaximumHitboxExtent, PaletteTypeEnum.getPaletteId, and ten accessors on LocalCachedChunkAccessor. Read and write through the section ref instead, using AbstractCachedAccessor or ChunkStore.getChunkReference.

  • ChunkPreLoadProcessEvent now carries the world and exposes getWorld(), matching ChunkSectionPreLoadProcessEvent.

  • BlockChunk.getSectionAtIndex is gone, since it indexed the legacy 0 to 9 section array and produced errors outside of it.

  • The old column accessor surface is gone. IWorldChunks, IWorldChunksAsync, IChunkAccessorSync, ChunkAccessor, OverridableChunkAccessor and LocalCachedChunkAccessor are deleted, along with the block accessors on World, WorldChunk and BlockChunk. Block reads now run through the section from ChunkStore.getChunkSectionReferenceAtBlock.

  • WorldChunk no longer holds a World, and the World parameters that only fed it are gone. The WorldChunk(Flags, BlockChunk) constructor, WorldChunk.loadFromHolder(x, z, holder) and GeneratedColumn.toHolder(sections) all dropped it, GeneratedChunk.toWorldChunk(World) folded into toHolder(), and the unused ChunkFlag.VALUES array was removed.

Section-Based Coordinates & Height

  • The lighting pass now runs per chunk section, so LightCalculation.init takes a ChunkStore and a section Ref rather than a WorldChunk, getSkyValue lost its unused WorldChunk parameter, and ChunkLightingManager exposes invalidateLightInChunkSections for section-level invalidation.

  • TargetUtil.getTargetBlock and getTargetLocation take a ChunkStore where they used to take a World, so plugin code calling them directly has to pass world.getChunkStore() instead.

  • Explosions, block explosion effects, block harvesting, raycast selectors and the spectator camera all work in cubic worlds now that TargetUtil no longer assumes a single vertical column.

  • Block tick callbacks can now get world coordinates without capturing them. A new BlockSection.forEachTicking overload takes the section coordinates and a TriObjectPositionBlockFunction, so the callback gets world positions and a third context value through its parameters.

  • SimpleBlockCommand.executeWithBlock no longer receives a WorldChunk. It now gets the CommandContext, the ChunkStore, a Ref<ChunkStore> section reference and the block coordinates, so a custom block command can reach any height.

  • Block health now lives on the chunk section rather than the column. BlockHealthChunk is decode only, so read and change health through BlockHealthSection on the section entity, keyed by ChunkUtil.indexBlock. WorldNotificationHandler.updateBlockDamage and getBlockDamagePacket are gone, because damage replicates on its own once it is written to the section.

  • The fluid and material helpers in WorldUtil now take the ChunkStore and resolve the block's section themselves, so they read correctly at any height. getWaterLevel, findFarthestEmptySpaceBelow and findFarthestEmptySpaceAbove take a caller bound rather than stopping at the column top, and PositionProbeBase.updateWaterLevel takes the ChunkStore too.

  • You can now ask a selection which world region it will write to before you place it. BlockSelection.computePlacementBounds(Vector3ic, Vector3i, Vector3i) reports those bounds and returns false for a selection with no cells.

  • All four TargetUtil.getTargetBlockAvoidLocations overloads now take Collection<Int3OpenHashSet> for blocksToIgnore rather than Collection<LongOpenHashSet>. The old packed-long form crashed the world thread on a stroke below Y 0.

Chunk Storage & Loading

  • Chunk storage providers now take a readOnly flag on initialize and have to answer hasStoredChunks, and a cubic IChunkLoader has to implement forEachSection. A provider that cannot open read only should reject the flag rather than open writable.

  • Instance validation no longer builds a whole world to read its stored chunks, so World.validate and WorldValidationUtil are gone in favor of ChunkStorageValidator. ValidateBlockEvent moved from PrefabBufferValidator to BlockValidator and now fires for chunk validation too, concurrently and off the world thread, so a handler must not keep state between events.

  • A chunk section can now be pinned in memory for the length of an async edit, with addKeepLoaded, removeKeepLoaded and shouldKeepLoaded on ChunkSection. A held section does not keep its column resident on its own.

Chunk Ticking & Section Loading

  • ChunkFlag.TICKING, ChunkFlag.INIT, ChunkFlag.START_INIT and WorldChunk.initFlags are gone. Chunk ticking is now the absence of the NonTicking component, so read it with !store.getArchetype(chunkRef).contains(ChunkStore.REGISTRY.getNonTickingComponentType()) and change it by adding or removing that component.

  • Fixed stored block entities and entities never spawning in a section whose first load request asked for ticking. ChunkGrid now adds every chunk and section as non-ticking and clears the marker afterwards.

  • BlockModule now creates block entities for newly generated blocks from ChunkSectionPreLoadProcessEvent rather than ChunkPreLoadProcessEvent, so sections outside the 0 to 320 height range are covered.

  • TeleportPlugin now spawns warp markers from ChunkSectionPreLoadProcessEvent, which also covers sections that cubic worlds load on their own.

Cubic Worlds

  • Cubic worlds now use a new tree heightmap, and BlockSection blobs moved to version 7. Older servers cannot read those blobs, so a world loaded on this version cannot be opened on an older one.

  • Cubic world generators must now implement generateColumn(seed, index, x, z, stillNeeded, priority) on IWorldGen.Cubic. It returns a GeneratedColumn holding only the column-level data such as the tint.

  • In a cubic world, column and section generation is now split, no longer requiring the 0-9 range to be generated with the column.

Block Carrying

  • Plugins can now react when a player starts to carry a block. The new BlockCarriedEvent fires on the block entity holder with the carrier ref, so an EntityHolderEventSystem<ChunkStore, BlockCarriedEvent> can adjust your own components at that moment.

ECS & Entities

  • Plugins can now build entity hierarchies in the ECS store, creating parent and child entities, reparenting them, and iterating a parent's children. Systems process root entities by default, and overriding getHierarchyScope() lets a system take in children or handle only parents.

  • Plugins can block players from opening Debug Screens. Adding PreventDebugScreens.INSTANCE to a player entity blocks the ToggleDebugScreens keybind (F7 by default) and closes any debug screen that is already open, and removing it gives the screens back. The component is runtime only and does not persist across a reload.

  • Entity hitboxes now follow EntityScaleComponent. BoundingBox keeps the entity scale across recomputes and applies it to the detail boxes as well, and a new EntityScaleBoundingBoxSystem keeps the box in step with the component.

Event Titles

  • EventTitleUtil has overloads that take an EventTitleStyle. The boolean overloads still work but are deprecated for removal.

Weather

  • WeatherTracker gained tryClaimOverride, releaseOverride and resolveUnoverriddenWeatherIndex. clearOverrideWeatherIndex now drops the owner as well. One owner holds a weather override at a time.

Beams

  • The new Hytale:Beam builtin ships a BeamComponent holding AttachedBeam entries, and each one runs from an attachment point on the owner to another entity, a node on that entity's model, or a fixed world position. Beams are runtime state, so they never save with the entity.

  • BeamComponent.spawn creates a replicated entity that carries beams and no model, for a beam that belongs to nothing else. It takes an optional lifetime and applies it with a DespawnComponent.

Map Markers

  • Any marker provider can attach an alert now. The new MapMarkerAlert config turns into a component through MapMarkerBuilder.withComponent(alert.toComponent()).

Ability System

  • Ability charges are now a collection. AbilityCharges holds AbilityCharges.Entry records and GrantAbilityChargesInteraction adds an entry to the existing component rather than replacing it, so several armed charges can run at once.

  • AbilityChargeHitSystem now checks the Damage.BLOCKED meta object and stops the charge hit when the target has blocked the attack.

  • Ability slot filtering has been split. AbilitySlotAddFilter is gone, replaced by AbilityCoreSlotFilter, which blocks a core Runestone already equipped on another line, while AbilitySupportSlotFilter now also rejects a support runestone already on the same line.

  • AbilityPullSystem no longer reels players in with knockback. It now works out the reel step itself, runs it through CollisionModule and applies it as a PendingTeleport, so player and NPC pulls are both server-authoritative. NPCs still take the pull as a one-tick knockback.

Damage & Knockback

  • Damage dealt from Entity Effects will now have the source type EntityEffectSource, making it easier to distinguish it from other types of damage.

  • PlayerDamageFilterSystem now cancels knockback alongside the damage it already cancelled for spawn protection and for PvP being off.

  • DamageMemory dropped getRecentDamage(), getTotalCombatDamage() and addDamage(float) in favor of per-source methods, and RecentSustainedDamageCondition and TotalSustainedDamageCondition no longer expose DAMAGE_MEMORY_COMPONENT_TYPE.

World Events

  • The world event failure counter was renamed. WorldEvent.failCount is now retryCount and WorldEvent.FAIL_COUNT_THRESHOLD is now WorldEvent.DEFAULT_RETRY_LIMIT.

  • Added EnterInstanceTeleporterEvent, fired when a player steps into an instance teleporter, so a plugin can react to the trip without hooking the interaction itself.

Audio

  • Volume modifiers passed to SoundUtil.playSoundEvent2d and playSoundEvent3d are linear multipliers, not decibels, and they were thrown away above 1.0. They now take effect, so a plugin passing 3.0 goes from roughly unity to about +9.5 dB. Nothing validates them, so check any modifier above 1.0.
  • Audio binding validation now needs to know whether a subscriber has a tempo, so AudioStateResolver.validateBindings takes a SubscriberTempo parameter. MAY_HAVE matches the old behavior.

Cameras, Input & Client Features

  • Cursor server cameras work on a gamepad now. The right stick drives the real cursor through a new GamepadCursor helper, and PrimaryItemAction with SecondaryItemAction send the click packets, so triggers break and use whatever the cursor is over.
  • ClientFeature no longer carries DisplayHealthBars, DisplayCombatText, CanHideHelmet, CanHideCuirass, CanHideGauntlets, CanHidePants, AllowBlockPlacement, AllowBlockBreaking or AllowBlockGathering, and a plugin naming one of them stops compiling. Those rules live in the GameplayConfig asset now, while ClientFeature keeps the movement capabilities plugins register themselves.
  • Cursor server cameras are playable again. A plugin that sets displayCursor on ServerCameraSettings gets cursor targeting back, and every movement direction uses the forward speed, so strafing is no longer slower than walking ahead.
  • PlayerMouseButtonEvent fires on clicks under a cursor camera again, carrying the target block or entity and the screen point for custom click logic from a top-down view.
  • Fixed a cursor camera reading mouse input while a menu, chat or page was open. Opening the pause menu used to spin the character, and MouseInteraction packets no longer go out behind a UI overlay.
  • A ClientTool now gets OnActiveStateChange(false) when the world is torn down while the tool is active, and that runs before the tool is disposed.

Kill Feed & Boss Bars

  • A boss bar name set through SetEncounterBossBar now renders text markup such as <s> and <color> instead of printing the tags. Markup applies to translated names only, so a raw display name from the tracked entity stays literal.
  • The UpdateBossBar packet gained a HardMode field, which changes the wire layout. EncounterBossBarState.setTracked and the UpdateBossBar constructor both take a trailing hardMode argument.
  • Kill feed entries now apply Message.strikethrough, .color, .bold, .italic and .underlined set on KillFeedEvent.KillerMessage and KillFeedEvent.DecedentMessage. Markup tags in killer and decedent names now render as formatting when MarkupEnabled is set, instead of showing as raw text.

UI & Noesis

  • An ItemGrid in a custom UI page no longer needs a DefaultItemIcon. An item whose icon will not resolve falls back to the unknown item icon, and DefaultItemIcon still overrides that placeholder.
  • The legacy UI Element base is now nullable-annotated, so HitTest and Find<T> return a nullable element and the constructor takes a nullable parent. Runtime behavior is the same, but an override that declares a non-nullable return needs a ? to match.
  • Noesis pages can now shrink text that would otherwise be cut off. The new hy:ShrinkTextToFit decorator scales its child down to MinFontSize, 10 by default. It never writes FontSize, so styles and triggers keep working. The wrapper needs a finite width, so it does not shrink inside a horizontal StackPanel, and wrapping children are not supported.
  • The tentative API for server-side Noesis UI has made its way into the server. It is not usable yet because we are still finalizing parts of the system before it is ready to be used. All new APIs are prefixed with dev_ and should not be used yet.
  • The cooldown overlay drawn on item slots can be reskinned. ItemGridStyle takes a new CooldownOverlay patch property that you can set in a .ui style block.
  • PortalDeviceSummonPage and PortalDeviceActivePage are no longer CustomUIPages, and the active page opens through PortalDeviceActivePage.open. PortalDeviceErrorPage builds the error page for both.
  • The legacy portal layouts are gone, covering Pages/PortalDeviceSummon.ui, Pages/PortalDeviceActive.ui, Pages/PortalDeviceError.ui and everything under Pages/Portals/, with the strings and textures only they used.
  • TextFormatting now parses the markup inside a resolved <msg> tag, nested up to 4 deep and capped at 16 tags per text.
  • The diamond bullet moved into the design system as Style.Bullet, and the chapter detail panel draws it from there. The three portal panels share one Style.Portal.Card for the frame and emblem.
  • Fixed the default button missing its controller cue the first time a page opened. The cursor warp now waits a frame when focus lands before the view is ready.

Worlds, Instances & Lifecycle

  • A universe resource whose codec comes from a plugin getCodecRegistry is now written at shutdown. The final flush moved to the new ShutdownEvent.FLUSH_UNIVERSE_RESOURCES stage, which runs after SHUTDOWN_WORLDS while every plugin is still enabled.
  • PortalWorld.overrideRemainingSeconds is now setRemainingSeconds(world, seconds, force), and it leaves the timer alone when the portal world is already scheduled for removal.
  • Other event listeners now keep running when one of them throws, and the failure is logged instead of stopping the dispatch.
  • A plugin can now load a target world while players are being drained out of a world that is shutting down. DrainPlayerFromWorldEvent is an IAsyncEvent, so the drain waits for listeners and you can call setWorld once the world is ready.
  • The message a drained player sees can now be replaced. DrainPlayerFromWorldEvent carries a message and the source world alongside the destination, and the setter is now setDestinationWorld. Portals uses it to explain that the fragment expired.

Localization

  • Fixed unbounded growth of the server translation cache. I18nModule now keys cached messages by the language returned from its new resolveLanguage() instead of the raw client string, and queueTranslations() replaces sendTranslations() so repeated language switches on one connection coalesce into a single send.

Performance & Memory

  • Moved the generated concurrent maps in ConcurrentFastUtil off sun.misc.Unsafe and onto VarHandle, keeping volatile ordering on every field and table access, which removes one of the three sources of the deprecation warning at server launch.
  • Fixed an out-of-bounds read in RawJsonReader, where a one-char-wide read near the end of the buffer could run up to three chars past it. The reader now goes through MemorySegment, and the protected readStringPartAsLongUnsafe is now called readStringPartAsLongWide.
  • Chunk saves now borrow their scratch buffers from a bounded direct buffer pool instead of allocating a fresh one per save, which is what stops busy servers from running past the direct memory limit. readSegments keeps its signature, but the buffer it returns is pooled, so a caller must not hold on to it after the read finishes.
  • Document writes no longer run on the common pool. BsonUtil.writeDocument now uses its own fixed pool of four Document Writer threads, which covers world config, world resources and player saves, so a world tick can no longer starve waiting on a save.

Rewards

  • Added a Rewards builtin module that plugins can extend with their own reward types. It ships one type for now, EntitlementReward, which grants an entitlement through RewardAsset.

Wilderness

  • Wilderness gains size(), test(int) and isValid(), so a plugin can walk a player's tracked region by index and test one chunk without world coordinates.

Dropped Items

  • The public ItemMergeSystem#RADIUS constant is gone. Merge distance now comes from the item's config through ItemComponent#getMergeRadius(ComponentAccessor), with ItemComponent#setMergeRadius(float) for changing it at runtime.

Other API Changes

  • com.hypixel.hytale.protocol.DurabilityOperator is now ComparisonOperator, because the same comparison list serves durability checks and the new game flag condition. Plugin code that names the old type has to switch, while asset JSON and the wire format stay exactly as they were.
  • The GroundedCondition interaction moved out of the Abilities builtin into the core server, so an interaction can use it without that plugin loaded.
  • LivingEntity, NPCEntity, PatrolPathMarkerEntity and SpawnBeacon now mark their World constructor parameter @Nullable, which matches the null world that Entity.clone already passes when it rebuilds an entity.

Previous post

Next post