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
2DandYFor2Doptions in both the asset and the node editor. AYOverrideintoCacheintoGradientWarpchain 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
FromMinequalsFromMax) 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
Defaultstate 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_Constantbiome 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/Treesfolder intoPrefabs/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_00now start atStage_0. - The
Prefabs/Orbisfolder holds work in progress for V2 world generation. It is less stable than the rest of the prefabs folder, so expect changes. - Fixed the
supportchains 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.
SetEncounterWeathertakes aWeatherasset and an optionalTransitionSeconds(2 by default), andClearEncounterWeatherputs members back on the normal weather. Both are restricted toInstructionType.Encounter. - NPC weather sensors still read world weather only, so
Sensor: Weatherdoes not match an encounter's forced sky. Drive that behavior from encounter state or beacons instead. - The
Example_Bossencounter 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
GrantRewardaction on encounter templates points at a reward asset, andRewardExistsValidatorfails the load when that name does not resolve. - Encounters can now mark their boss as hard mode on the boss bar.
SetEncounterBossBartakes an optionalHardModeboolean that defaults to false, and because each action replaces the whole bar state, leaving it out turns hard mode back off.
Charging NPCs
ChargeAccelerationis gone fromBodyMotionCharge. The newChargeAccelerationDistanceandChargeDecelerationDistancesize 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.RemovedBlockSetis gone as well.IgnoredBlockSetnow 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.
ChargeDistanceModepicks how that distance is measured (MaxRange,TargetDistor one of the collider modes) andTargetDistanceRangeoffsets the stop point, with positive values stopping short of the target. - The charge ramps are fully shapeable.
ChargeAccelerationCurveModeandChargeDecelerationCurveModechoose whether the curve reads as speed or as distance covered, and the matchingMinimumRelativeSpeed,HalfTimeValue,HalfTimeSteepnessandEndSteepnesskeys tune the curve itself. - Movement behavior of a charging NPC can now be modified.
ProbeRelaxedConstraintsacceptsWade,Damage,Drop,BreatheandFence, so a role can let a charge cross liquid or suffocating blocks it would otherwise refuse. ChargeStategainsInStopRange, which a role can match throughSensorChargeState. An NPC enters it when its target sits closer than the stop point the configuration asks for.- Cleaned up the
BodyMotionChargeconfig descriptions for template authors.
Motion & Pathfinding
- All the meaningful config values on
MotionControllerWalkandMotionControllerBaseare holders now, so they can be computed and overridden from a template rather than fixed per role. ThrottleIgnoreCountandThrottleDelayRangeon the find and seek motions now also cover a blocked path, not only a failed search. SettingThrottleDelayRangeto[0, 0]restores the old behavior on an obstacle.- Fixed
BuilderMotionControllerWalk.getFenceBlockSetthrowing when the configured block set was empty or missing. - Fixed a pathfinder crash on roles that turn
DiagonalMovesoff. - 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
RangeandMaxHeightat 256, well above the 30 and 10 the shipped roles use. - The flying NPC template now exposes
KnockbackScaleas a parameter.
NPC Combat & Awareness
- Combat Action Evaluator conditions can now tell apart direct hits and damage over time.
RecentSustainedDamageandTotalSustainedDamagetake an optionalSourceslist (Combat,DoT,Environment) and an optionalDamageCauseslist, and leaving either out still counts everything. - The role
Damagesensor now takesIncludeDoT, which decides whether damage over time feeds the sensor. It defaults totrue, so existing roles behave as before. - Creatures can now be made immune to frost. The new
Immunity_SlowandImmunity_Freezemarker 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
IgnoreDisableNPCIncomingDamageflag on a role makes that NPC ignoreCombatConfig.DisableNPCIncomingDamage.Test_Dummy_Stationaryhas this enabled by default. - NPCs can now also switch targets if line of sight to the previous one has been lost. The new
TargetRequireLoSparameter onComponent_Instruction_Combat_Target_Swap(true by default) keeps the current target prioritized only while line of sight holds, and the defaultTargetSwitchTimerrange 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_Detectionhas been given anObserveflag (true by default), as well asObserveAngleRange,ObservePauseRange, andObserveRelativeTurnSpeedto shape the head motion. - NPC roles can now react to being hit. Running
Component_Instruction_Hit_Interrupton 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
FlinchAnimationon that component, which otherwise playsHurtin the Action slot. - Attack instructions and roots need to check for the absence of
Hit_Interrupt_Stunnedso a queued attack start gets blocked, and offensive roots have to keep theirAttacktag for the cancel to find them. - A custom attack can tell the system where its counterattack ends.
Hit_Interrupt_Begin_Protected_Attackgoes after the start gate andHit_Interrupt_Finish_Protected_Attackafter 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
HiddenUIComponentskey takes a list ofEntityUIComponentids 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_Swapnow setsNextTargetRangeViewandNextTargetRangeHearingfrom its ownViewRangeandHearingRange. - NPC roles can now react to universe-wide game flags. A new
GameFlagsensor takes aFlag, aLeveland aComparator. - Target leading is now opt-in.
Deflectiondefaults to false, so any NPC role that wants its ranged attacks to lead a moving target has to set it to true. - The
Friendlyflag on theDamagesensor 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_Predatornow 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
WeatherIdslist onBeaconNPCSpawnkeeps 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.
SpawnPositionSearchtakesLineto follow the marker orientation orRangefor a bounded two-dimensional sweep, andMaxHorizontalSpawnOffsetsets how far it looks, up to 16 blocks. - Markers now check their own placement.
ValidatePositionrejects a marker buried too far inside solid blocks, andValidateBelowPositionrejects 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.
RequireFitAtMarkerHeightrestricts the search to vertical spans that contain the marker Y. SpawnPositionSearchDebugreports on a failing search with eitherSummaryorMapdiagnostics, and range search failures now log why each candidate was turned down.- Spawn position limits are now bounded.
MaxDropHeighttops out at 32 blocks,BlockOverlapHeightCompensationat 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.
MemoriesUnlockedBytakesProximity(the default) orKill, andMemoriesKillRangesets how far a player can be and still be recorded. A Variant role needs its referenced template to declare both, the same asIsMemory.
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.
DestroyTaggedVolumesInteractionpicked up the same guard.
Entity Components
- Fixed the
UIComponentListentity component ignoring itsComponentskey, 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
AbilityKeywordassets instead of dotted tag strings. Keywords live inAbilities/Keywords/and can declareRequiredAttributesandRequiredInteractionsthat any Runestone carrying them has to provide.ItemAbilityis now split onSlotintoPrimaryItemAbility, which lists itsKeywords, andSupportItemAbility, which gates onRequiresAnyKeyword,RequiresAllKeywordsandExcludesAnyKeyword. The editor only shows the fields that apply to the slot you picked.Damage boosts can now carry through to effect ticks.
ActiveEntityEffectgained aDamageMultiplierandApplyAbilityEffectsaDamageAttribute, 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
RendandWitherentity effects underEntity/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
DistanceAttributefield onRaycastSelectornames an ability attribute, and the resolved value multipliesDistanceon the block raycast, the entity search sphere and the debug arrow, matching theSizeAttributebinding on the AOE and stab selectors. If the cast does not carry the attribute, the distance is unchanged.Added
IcicleandWindStrike_Projectilemodels for the reworked Charged Shot and Wind Strike visuals.
Food, Potions & Cooldowns
The
Potion_Stamina_Cooldownentity effect has been removed. An asset pack that gated on it should read thePotion_Consume_Staminacooldown id instead.Any consumable can now start a cooldown when a drink finishes.
Consume_Charge_Potion_FastandConsume_Charge_Potion_Fastestread an optionalConsumeCooldowninteraction var, which defaults to no cooldown.Added
Consume_Potion_Health_Cooldown,Consume_Potion_Stamina_Cooldown,Condition_Consume_Potion_HealthandRoot_Secondary_Consume_Potion_Healthas reusable interaction assets for your own potions.Every potion built on
Potion_Templatenow 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,_T3and_Breadeffects are gone. Every food now usesFood_Instant_Heal_T1.
Glider
Glider tuning was rebuilt for the new movement state machine. The old
FallSpeedMultiplier,HorizontalSpeedMultiplier,TerminalVelocityandSpeedvalues on the item are gone, replaced by a wider set of fields onTemplate_Gliderthat also cover the dive and the climb.The
Conditioninteraction now includes a parameter for theGlidingmovement state.
Weapons & Ability Slots
Mace item animations gained a
SwingUpLeftvariant 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_Entryreload moved onto it inTemplate_Weapon_Crossbow.
Dropped Items
- Dropped items can now merge over a distance you pick. A new inherited
MergeRadiuskey onItemEntityConfigsets how far in blocks a dropped item looks for others to stack with. Leaving it at-1.0Ffalls back to the world default.
Portal Keys
- Portal keys can now cap how many times each player enters.
PortalKeycarries the per-player limit, and the portal device pages show the limit and the entries left.
Movement Items
Removed the debug-only
Debug_Movement_Bootsarmor.Items can now play a separate sound to the wearer when they use an extra jump. A new
ExtraJumpLocalSoundEventonItemMovementSettingstakes 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
AttachBeaminteraction 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
Lifetimevalue on theProjectileinteraction despawns the projectile once that duration runs out.
Selectors
Cylinder area selectors now respect their size attribute.
AOECylinderSelectormultiplies its range and height by thesizeAttributevalue, 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
EntityDamageCausefield onExplosionConfigsets the damage cause applied to entities in range, and it falls back toEnvironmentwhen you leave it out.Fixed a crash when you added an entry to
OnHitEffectson anItemAbility. An empty entry used to throw aNullPointerExceptionin the asset editor and on the server, and validation now rejects it instead.Every bed now shares one
Block_Bedroot interaction carrying theType=Bedtag, so a bed no longer defines its own use interaction inline.The shared on-hit chain moved out of
DamageEntityParentinto a namedDamageEntityParent_On_Hit. An asset that overridesNextcan 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
IgnoreForFlaggedConditionsparameter on a Charging or Wielding interaction to true will allow it to be ignored by Charging and Wielding conditions that have theUseIgnoreFlagparameter set to true.Fixed the
ChangeStateinteraction 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
/givecommand gained an optional quality argument that overrides the quality the item asset would otherwise use.ItemQualityassets now inherit from their parent. Every field exceptLocalizationKeyfalls 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.onTicknow takes aCommandBuffer<ChunkStore>and the chunk sectionRef<ChunkStore>in place of theWorldandWorldChunkparameters, so any subclass override needs updating. The world is available fromcommandBuffer.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.BlockBreakingBypassTagnames a tag, and any block carrying it can still be broken whileAllowBlockBreakingis 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'sUseinteraction and it reads both from the block item'sTranslationProperties. A block with no description opens nothing.The
BlockLorepage takes an optionalTextAlignmentkey ofLeft,CenterorRight. It defaults toCenter.
Block Materials
- Chapter 1 blocks that were copied from other assets now carry the right material data. Gather types,
Fireprooftags,FuelandCharcoalresources, strayType: SoilandType: Woodtags and missingPhysicalMaterialIdentries were all corrected across the goblin, Enkindled, Cybercity and Hive Brick sets. - The 35 log half slabs now set
ResourceTypesofFuelandCharcoaldirectly, instead of inheritingRockfromRock_Stone_Cobble_Half. Oak and Apple half slabs are tagged as wood.
Foliage
UseDefaultDropWhenPlacedis 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_FloorandPlant_Leaves_Poisoned_Flooreach gained aShearsentry inGathering.Tools.
Farming & Crops
WaterGrowthModifierAssetnow 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
StayOpenWhenEmptyflag onItemContainerBlockkeeps 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.
SendMessageandShowEventTitleboth 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,ShowEventTitleEffectandInstanceDiscoveryConfigall take aStylevalue.The event title effect on a trigger volume can now pick who sees it. A new
Recipientfield onShowEventTitleEffecttakes the same options asSendMessageEffectand defaults to the triggering player.The event title action, for
WorldEvents, can now pick how the banner looks.ShowEventTitleActiontakes an optionalStyleand an optionalIcon, and falls back to the default style when you leaveStyleout.Instance worlds no longer take
DocumentDisplayOnRemoval. A newEventTitleOnRemovalshows 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
SoundEventIdonEventTitleConfigfires once the title is sent, and assets that leave it out behave as before.
Trigger Volumes
Three new trigger effects handle respawning.
SetRespawnPointtakesOrigin,Position,NameandClearExisting,SetWorldSpawntakesOrigin,Position,YawandClearPlayerRespawnPoints, andClearRespawnPointstakesNameandAllPlayers.Trigger volume tags can now be used like variables and compared to each other.
TagConditiontakes aCompareAgainstfield that picks whether the tag is checked against a plain value (the default) or against a second tag named inCompareTagKey.Respawn points can now set which way a player faces.
PlayerRespawnPointDataandSetRespawnPointEffectboth take aYawin degrees.Trigger volume
PlaySoundeffects now takeVolumeDbin decibels from -100 to 0 andPitchSemitonesin semitones from -60 to 12, instead of the old linearVolumeandPitch. 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.
TimeLimitSecondsandAllowedEntryCountonPortalTypeapply to every key of that type, and aPortalKeyonly needs the fields when it wants to differ.Portal worlds can now be authored with no time limit at all.
PortalTypeandPortalKeyaccept a portal without a duration.Portal instance configs now carry a
DisplayName, and a world's display name reaches join and leave messages as aMessage, so it localizes instead of printing the raw key.
Map Markers
Map marker overrides can change the display name of a marker. A new
DisplayNamekey onMapMarkerOverridetakes a localization key to use instead, and the marker override add command accepts it alongside--iconand--global.World map markers can be drawn larger. A new
IconSizeon block and objective marker configs takesDefaultorMajor, andMajorrenders 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
Alertblock onBlockMapMarkertakesIcon,Tint,Duration(5 seconds by default) andTimeout(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
CompassIconto the new breach icon.
Encounter Assets
Encounter asset files must now declare the top-level
Classkey. Role files can still leave it out and fall back toRole.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 thatAbilityBenchIntro.uiandMemoriesUnlocked.uinow both build on.
Damage & Death Messages
- Damage types now carry their own death message. A new
DeathMessageKeyon 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.
Colortints a sprite and lets you control its opacity, andKeepLastFrameholds an animation on its final frame instead of snapping back to the first.Added a
Beamasset type underEntity/Beamswith a singleTexturePathfield. The texture has to sit underBeams/orTrails/.ModelVFX assets now inherit every field from their parent.
ModelVFX.CODECusesappendInheritedthroughout, 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.uigained a@RunicPanelgroup plus the@RunicTitleStyle,@RunicHeadlineStyleand@RunicBodyStyletext 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
Trailasset no longer disconnects the client. A trail that sets notexturenow falls back toTrails/Basic.pnginstead of failing validation.Content can now ask for confirmation before it acts, with a new Confirmation page for OpenCustomUI. It takes
TitleKeyandMessageKeyfor the text, optionalConfirmKeyandCancelKeyfor the buttons, a requiredSuccessroot that runs on confirm, and an optionalFailroot 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
Float2ObjectMapfields now matches what the codec really reads and writes. The generated key pattern accepts scientific notation such as1.0E-4and leading-dot values such as.5, and it no longer lets non-numeric keys like1x2slip 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
LightColorwrites 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
Projectilefield on theLaunchAbilityProjectileinteraction now opens the asset browser, so you can pick aProjectileConfigfrom 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,ParticleSystemandParticleAnimationFramehad 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
FitToHeightMaponly fits a point whose Y isInteger.MIN_VALUErather 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,
MusicTransitionandStinger, live inAudio/MusicTransitionsandAudio/Stingers.Handoffs can land on a musical boundary instead of a frame.
MusicSyncpicks the moment on the outgoing track (immediate, next beat, next bar, an exit marker or a named marker) andDestinationAlignpicks where the incoming track starts on its own timeline.Overlap and crossfade are separate controls now.
ExitAtsets the handoff,PlayPostExitlets the outgoing track run to the end of the file, andFadeOutDurationwithFadeOutDelayramps it out instead, following aFadeCurvethat defaults to equal power.Music containers picked up a batch of new fields.
MusicContainertakesTags,Align,AlignMarker,ExitAtandStingers,SegmentMusicContainertakes namedMarkers, andHorizontalMusicContainertakesAudioStatewithPhasesso 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.
StateTransitiongainedPostEvent, 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: 2000becomesDuration: { "Ms": 2000 },AudioState.DefaultSyncTo: "NextBar"becomesDefaultSyncTo: { "Point": "NextBar" }, andMusicTransition.FadeOutDuration,FadeOutDelayandFadeInDurationeach take an object instead of a number of seconds.One music layer can now enter an audio state on its own schedule. A
StateDeltatakes an optionalFadeblock withDuration,CurveandDelay, and any field you leave out still falls back to the axis.Fade.DurationandFade.DelayareBarBeatDurationvalues, so a subscriber with no tempo keeps only theMscomponent. 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 aFadewith nothing set.
Volume Limits
Interface sound volume from
SoundStyleandSoundEffectis now bounded to +10 dB, which matches every other authored gain field.AudioStatevolume 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 setradiusonly making one block of the filled region flow instead of all of it, and/block settickingnow resolves the chunk section itself and tells you when it is not loaded.The
/blockpoint commands and/block rownow work at any height in a cubic world, soget,set,getstate,setstateandsettickingreach above Y 320 and below Y 0. A section that is not loaded answers with the newserver.commands.block.noSectionmessage./block bulk find-hereand/block bulk replacenow take their radius in chunk sections and sweep a sphere around you, including the sections above and below the old height range./block bulk findgained a--chunkYand a--radiusoption. 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 replacecounting blocks it never changed, and/block setstatethrowing 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
/blockcommand 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 heightcommand that dumps a column's heightmap for debugging./chunk fixheightalso 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 --oneandlighting info --detailalways reading section 0, because both passed a section index where a block Y was expected.lighting get,chunk lighting,chunk forcetick,chunk fixheightandchunk resend --clearcachenow work on loaded sections at any height, and an absent section answers with the newcommands.errors.sectionNotLoadedmessage.
Instances & Portals
Instance edit worlds now load a new
InstanceEditgameplay config that switches onAllowBlockBreaking,AllowBlockGatheringandAllowBlockPlacement, 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
TeleportInstanceInteractioncan now stay around between sessions when their asset asks for it. Worlds spawned from the portal device summon page still setsetDeleteOnRemoveandsetDeleteOnUniverseStartthemselves, so those stay temporary and get swept on the next start.Portal worlds reached through
TeleportInstanceInteractionare 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
PortalTypeasset.
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
EnableWorldEventsflag in a newWorldEventsWorldConfig, and new Creative worlds get it set to false.A world can now switch off specific interactions. The new
BlockedRootInteractionTagslist inGameplayConfig.WorldConfigtakes 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 inWildernessConfig, and the command warns when a world has it turned off.
Event Title & Beam Commands
The
/eventtitlecommand takes--stylein place of--major, and the secondary line now defaults to empty rather than to “Event”.Added a
/beamcommand for development work, withentity,position,spawnandclear.
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-cacheand--backup-dir, and it prints the steps to move them somewhere safe before exiting with code 11.Added an
--allow-install-dirflag, mirrored by thehytale.allow_install_dirsystem property, for anyone who wants to run there anyway and accept the data loss risk. Singleplayer runs,--help,--versionand a--barestart without--bootstrapskip the check already.Server operators can now run
/auth login browseror/auth login devicewhile 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
MaxViewRadiusoutside 1 to 32 inconfig.jsonno 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 addcommand now tells you whether creation succeeded or failed instead of quietly dropping the result.The Asset Editor plugin ships a sample
EditorPropertyGalleryasset that shows every property control in one file. It stays unregistered until you createmods/Hytale_AssetEditor/config.jsonwithEnablePropertyGalleryset to true and restart the server, after whichGallery_AllControls.jsonopens in the editor./spawning markers debuginvalidmarkersnow highlights invalid marker placements and revalidates markers that are moved or rotated, and/spawning markers autoremoveinvalidmarkersswitches 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) andPrefetchSectionLimit(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
SmallerThanis nowLessThan,SmallerOrEqualsis nowLessOrEqual, andSelectis nowSelector.Two more density asset types lost their trailing s, so
Equalsis nowEqualandGreaterOrEqualsis nowGreaterOrEqual. 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_Voidis nowVoid_Spectreacross its model, drop list, icon and particles.The Void Spectre's attack interactions were renamed to match what they do.
Void_Spectre_Attackis nowVoid_Spectre_Charge,Void_Spectre_Attack_Damageis nowVoid_Spectre_Charge_Damage, and the root interaction is nowRoot_NPC_Void_Spectre_Charge.
Event Titles
IsMajoris gone fromShowEventTitleEffect. TheStylefield 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
TreasureMapobjective task, theOpenTreasureContainerandDestroyTreasureConditioninteractions, theLookBlocksBelowandTagBlockHeightworld location conditions and theTreasureChestblock 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.
AdventureMetadatanow carries the ephemeral flag,CursedItemsbecameEphemeralItems, and the/cursethiscommand is now/ephemeral.
Carryable Block
- Removed the
Carryable_Blockitem animation asset. The throw now lives inBlock.json, andThrow_Carryable_Blockpoints at the newHeavy_Throwanimations.
NPC & Spawn Marker Roles
The
Goblin_Minerattitude role is now calledGoblin_Brave, since it covers more than miners.The
Spider_Cave_Triggerspawn marker is now calledSpider_Cave_Manual, matching how the other manual markers are named.
Audio Files
- The heal sound
Magic/Heal.oggis nowMagic/Magic_Heal_01.ogg, which matches the naming convention, andMagic_Heal_02.oggsits beside it as the second variation.
Asset Files & Models
Asset file
Spiwer_Web_Full.pnghas been renamed toSpider_Web_Full.png,Fig_Blue_.pngis nowFig_Blue.png, and the duplicate fileTotem_Heal_BeamStart (1).particlespawnerhas been removed.The Goblin hookshot models are now named after scrap.
Hookshot_Goblin.blockymodelandHookshot_Goblin_Projectile.blockymodelbecameScrap.blockymodelandScrap_Projectile.blockymodel, andTool_Hookshot.jsonandHookshot_Hook.jsonpoint at the new paths.The Void tentacle animations moved and were renamed.
Bite2andBite3are nowBite_LeftandBite_Right, andIdleandIdle2sit in theDefaultfolder next to the new spawn animations.Renamed the
Bear_Voidtaken_Tentacle_ModelandBear_Voidtaken_Tentacle_Marker_Modelserver models toBear_Voidtaken_TentacleandBear_Voidtaken_Tentacle_Marker, with the roles that use them updated to match.
Protocol & Networking
Event Titles
- The
ShowEventTitlepacket droppedIsMajorin favor of anEventTitleStyle Stylefield, which breaks any plugin that builds the packet by hand. Styles includeDefaultandMajor.
Gameplay Config
- The world's gameplay config is replicated to the client by a new
WorldGameplayConfigpacket, carryingWorldConfig,CombatConfigandPlayerConfigstructs that mirror the server assets. It goes out when a player joins a world and again whenever theGameplayConfigasset reloads.
Beams
- The wire carries beams now.
BeamConfigandUpdateBeamConfigsship the beam assets, whileBeamInstanceand theBeamscomponent 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
FormattedMessagetrees, item categories, command trees, and interaction chains.UpdateLanguage.Languageis a required protocol field now instead of an optional one, and the protocol version was bumped for it. It andConnect.Languagealso 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
SEVEREand removed players. Rejections log atFINEnow, 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.ItemMovementSettingsgained a trailingExtraJumpLocalSoundEventIndex, 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,PortalActivePageResultandOpenPortalErrorPage, along with the page valuesPage.PortalSummon,Page.PortalActiveandPage.PortalError. The client rejects aSetPagecarrying 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
CompassAlertComponentover the wire, with anImage, aDuration, aTimeoutand aTint, so anything that sends a marker can make it alert.
Chunk Environments
- Environments now stream one chunk section at a time.
SetChunkEnvironmentsis keyed to section coordinates and carries a single section payload, andSetColumnno longer carries environments at all. Clients and servers have to be on matching protocol versions.
Asset Editor Packets
- Replaced the two-way
AssetEditorUpdateAssetPackpacket withAssetEditorAssetPackUpdatedfrom the server andAssetEditorUpdateAssetPackManifestfrom the client.AssetEditorAssetPackSetupnow maps pack ids to anAssetPack, which carries the manifest along withIsReadOnlyandCanBeDeleted, rather than to anAssetPackManifest.
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.performBlockUpdateandWorldChunk.setTickingare gone. UseBlockOperations.updateBlockAreafor a whole hitbox orBlockSection.setTickingwithChunkSection.markNeedsSavingfor one cell, and note thatupdateBlockAreanow takes theChunkSectionas well as theBlockSection.Block writes are moving onto sections. Use
BlockOperations.setBlockto make block changes to the world.BlockDataProviderresolves its chunk and fluid sections once per block read instead of on every field access. ThereadBlockId,readRotation,readFiller,readFluidIdandreadFluidLevelmethods are private now, so a plugin that calls them directly will not compile.Removed the unused
WorldChunk.setBlockoverloads that took aString, aBlockType, or aBlockTypeand a rotation, along withBlockChunk.setEnvironment.Removed
WorldChunk.breakBlock,IChunkAccessorSync.breakBlockandBlockChunk.getEnvironment(Vector3i). Resolve the section ref withChunkStore.getChunkSectionReferenceAtBlock, then useBlockOperations.setBlockor theEnvironmentSectioncomponent.WorldChunk.getBlockComponentHolderis now allowlisted for BuilderTools and BlockSelection only, since block entity reads go through the section'sBlockComponentSection.Removed
IChunkAccessorSync.setBlockInteractionStateand bothWorldChunk.setBlockInteractionStateoverloads. Interaction state now writes through theBlockSectioncomponent of the section ref fromChunkStore.getChunkSectionReferenceAtBlock, which skips the blocking chunk load and the old 0 to 320 height cap.Removed the last
WorldChunk.setBlockoverloads that took a block id or a block key, along withIChunkAccessorSync.setBlock(String, SetBlockSettings). Block writes now go throughBlockOperationson the section ref fromChunkStore.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.getBaseBlockis gone. Filler blocks now resolve throughBlockOperations.resolveBaseBlockPosition, which takes aChunkStoreand 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.setChunkSectionandgetMaximumHitboxExtent,PaletteTypeEnum.getPaletteId, and ten accessors onLocalCachedChunkAccessor. Read and write through the section ref instead, usingAbstractCachedAccessororChunkStore.getChunkReference.ChunkPreLoadProcessEventnow carries the world and exposesgetWorld(), matchingChunkSectionPreLoadProcessEvent.BlockChunk.getSectionAtIndexis 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.
WorldChunkno longer holds aWorld, and theWorldparameters that only fed it are gone. TheWorldChunk(Flags, BlockChunk)constructor,WorldChunk.loadFromHolder(x, z, holder)andGeneratedColumn.toHolder(sections)all dropped it,GeneratedChunk.toWorldChunk(World)folded intotoHolder(), and the unusedChunkFlag.VALUESarray was removed.
Section-Based Coordinates & Height
The lighting pass now runs per chunk section, so
LightCalculation.inittakes aChunkStoreand a sectionRefrather than aWorldChunk,getSkyValuelost its unusedWorldChunkparameter, andChunkLightingManagerexposesinvalidateLightInChunkSectionsfor section-level invalidation.TargetUtil.getTargetBlockandgetTargetLocationtake aChunkStorewhere they used to take aWorld, so plugin code calling them directly has to passworld.getChunkStore()instead.Explosions, block explosion effects, block harvesting, raycast selectors and the spectator camera all work in cubic worlds now that
TargetUtilno longer assumes a single vertical column.Block tick callbacks can now get world coordinates without capturing them. A new
BlockSection.forEachTickingoverload takes the section coordinates and aTriObjectPositionBlockFunction, so the callback gets world positions and a third context value through its parameters.SimpleBlockCommand.executeWithBlockno longer receives aWorldChunk. It now gets theCommandContext, theChunkStore, aRef<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.
BlockHealthChunkis decode only, so read and change health throughBlockHealthSectionon the section entity, keyed byChunkUtil.indexBlock.WorldNotificationHandler.updateBlockDamageandgetBlockDamagePacketare gone, because damage replicates on its own once it is written to the section.The fluid and material helpers in
WorldUtilnow take theChunkStoreand resolve the block's section themselves, so they read correctly at any height.getWaterLevel,findFarthestEmptySpaceBelowandfindFarthestEmptySpaceAbovetake a caller bound rather than stopping at the column top, andPositionProbeBase.updateWaterLeveltakes theChunkStoretoo.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
readOnlyflag oninitializeand have to answerhasStoredChunks, and a cubicIChunkLoaderhas to implementforEachSection. 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.validateandWorldValidationUtilare gone in favor ofChunkStorageValidator.ValidateBlockEventmoved fromPrefabBufferValidatortoBlockValidatorand 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_INITandWorldChunk.initFlagsare gone. Chunk ticking is now the absence of theNonTickingcomponent, 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.
ChunkGridnow adds every chunk and section as non-ticking and clears the marker afterwards.BlockModulenow creates block entities for newly generated blocks fromChunkSectionPreLoadProcessEventrather thanChunkPreLoadProcessEvent, so sections outside the 0 to 320 height range are covered.TeleportPluginnow spawns warp markers fromChunkSectionPreLoadProcessEvent, which also covers sections that cubic worlds load on their own.
Cubic Worlds
Cubic worlds now use a new tree heightmap, and
BlockSectionblobs 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)onIWorldGen.Cubic. It returns aGeneratedColumnholding 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.INSTANCEto a player entity blocks theToggleDebugScreenskeybind (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.BoundingBoxkeeps the entity scale across recomputes and applies it to the detail boxes as well, and a newEntityScaleBoundingBoxSystemkeeps the box in step with the component.
Event Titles
EventTitleUtilhas overloads that take anEventTitleStyle. The boolean overloads still work but are deprecated for removal.
Weather
WeatherTrackergainedtryClaimOverride,releaseOverrideandresolveUnoverriddenWeatherIndex.clearOverrideWeatherIndexnow drops the owner as well. One owner holds a weather override at a time.
Beams
The new
Hytale:Beambuiltin ships aBeamComponentholdingAttachedBeamentries, 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.spawncreates 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 aDespawnComponent.
Map Markers
- Any marker provider can attach an alert now. The new
MapMarkerAlertconfig turns into a component throughMapMarkerBuilder.withComponent(alert.toComponent()).
Ability System
Ability charges are now a collection.
AbilityChargesholdsAbilityCharges.Entryrecords andGrantAbilityChargesInteractionadds an entry to the existing component rather than replacing it, so several armed charges can run at once.AbilityChargeHitSystemnow checks theDamage.BLOCKEDmeta object and stops the charge hit when the target has blocked the attack.Ability slot filtering has been split.
AbilitySlotAddFilteris gone, replaced byAbilityCoreSlotFilter, which blocks a core Runestone already equipped on another line, whileAbilitySupportSlotFilternow also rejects a support runestone already on the same line.AbilityPullSystemno longer reels players in with knockback. It now works out the reel step itself, runs it throughCollisionModuleand applies it as aPendingTeleport, 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.PlayerDamageFilterSystemnow cancels knockback alongside the damage it already cancelled for spawn protection and for PvP being off.DamageMemorydroppedgetRecentDamage(),getTotalCombatDamage()andaddDamage(float)in favor of per-source methods, andRecentSustainedDamageConditionandTotalSustainedDamageConditionno longer exposeDAMAGE_MEMORY_COMPONENT_TYPE.
World Events
The world event failure counter was renamed.
WorldEvent.failCountis nowretryCountandWorldEvent.FAIL_COUNT_THRESHOLDis nowWorldEvent.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.playSoundEvent2dandplaySoundEvent3dare 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.validateBindingstakes aSubscriberTempoparameter.MAY_HAVEmatches 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
GamepadCursorhelper, andPrimaryItemActionwithSecondaryItemActionsend the click packets, so triggers break and use whatever the cursor is over. ClientFeatureno longer carriesDisplayHealthBars,DisplayCombatText,CanHideHelmet,CanHideCuirass,CanHideGauntlets,CanHidePants,AllowBlockPlacement,AllowBlockBreakingorAllowBlockGathering, and a plugin naming one of them stops compiling. Those rules live in theGameplayConfigasset now, whileClientFeaturekeeps the movement capabilities plugins register themselves.- Cursor server cameras are playable again. A plugin that sets
displayCursoronServerCameraSettingsgets cursor targeting back, and every movement direction uses the forward speed, so strafing is no longer slower than walking ahead. PlayerMouseButtonEventfires 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
MouseInteractionpackets no longer go out behind a UI overlay. - A
ClientToolnow getsOnActiveStateChange(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
SetEncounterBossBarnow 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
UpdateBossBarpacket gained aHardModefield, 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,.italicand.underlinedset onKillFeedEvent.KillerMessageandKillFeedEvent.DecedentMessage. Markup tags in killer and decedent names now render as formatting whenMarkupEnabledis set, instead of showing as raw text.
UI & Noesis
- An
ItemGridin a custom UI page no longer needs aDefaultItemIcon. An item whose icon will not resolve falls back to the unknown item icon, andDefaultItemIconstill overrides that placeholder. - The legacy UI
Elementbase is now nullable-annotated, soHitTestandFind<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:ShrinkTextToFitdecorator scales its child down toMinFontSize, 10 by default. It never writesFontSize, so styles and triggers keep working. The wrapper needs a finite width, so it does not shrink inside a horizontalStackPanel, 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.
PortalDeviceSummonPageandPortalDeviceActivePageare no longerCustomUIPages, and the active page opens throughPortalDeviceActivePage.open.PortalDeviceErrorPagebuilds the error page for both.- The legacy portal layouts are gone, covering
Pages/PortalDeviceSummon.ui,Pages/PortalDeviceActive.ui,Pages/PortalDeviceError.uiand everything underPages/Portals/, with the strings and textures only they used. TextFormattingnow 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 oneStyle.Portal.Cardfor 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
getCodecRegistryis now written at shutdown. The final flush moved to the newShutdownEvent.FLUSH_UNIVERSE_RESOURCESstage, which runs afterSHUTDOWN_WORLDSwhile every plugin is still enabled. PortalWorld.overrideRemainingSecondsis nowsetRemainingSeconds(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.
DrainPlayerFromWorldEventis anIAsyncEvent, so the drain waits for listeners and you can callsetWorldonce the world is ready. - The message a drained player sees can now be replaced.
DrainPlayerFromWorldEventcarries a message and the source world alongside the destination, and the setter is nowsetDestinationWorld. Portals uses it to explain that the fragment expired.
Localization
- Fixed unbounded growth of the server translation cache.
I18nModulenow keys cached messages by the language returned from its newresolveLanguage()instead of the raw client string, andqueueTranslations()replacessendTranslations()so repeated language switches on one connection coalesce into a single send.
Performance & Memory
- Moved the generated concurrent maps in
ConcurrentFastUtiloffsun.misc.Unsafeand ontoVarHandle, 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 throughMemorySegment, and theprotectedreadStringPartAsLongUnsafeis now calledreadStringPartAsLongWide. - 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.
readSegmentskeeps 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
Rewardsbuiltin module that plugins can extend with their own reward types. It ships one type for now,EntitlementReward, which grants an entitlement throughRewardAsset.
Wilderness
Wildernessgainssize(),test(int)andisValid(), so a plugin can walk a player's tracked region by index and test one chunk without world coordinates.
Dropped Items
- The public
ItemMergeSystem#RADIUSconstant is gone. Merge distance now comes from the item's config throughItemComponent#getMergeRadius(ComponentAccessor), withItemComponent#setMergeRadius(float)for changing it at runtime.
Other API Changes
com.hypixel.hytale.protocol.DurabilityOperatoris nowComparisonOperator, 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
GroundedConditioninteraction moved out of the Abilities builtin into the core server, so an interaction can use it without that plugin loaded. LivingEntity,NPCEntity,PatrolPathMarkerEntityandSpawnBeaconnow mark theirWorldconstructor parameter@Nullable, which matches the null world thatEntity.clonealready passes when it rebuilds an entity.