Основа — Horizon (MIT). История апстрима не переносится: этот репозиторий ведёт свою.
9.4 KiB
Block behaviours and ticking: parity status
Area: random and scheduled block ticks, growth, bone meal, TNT and
explosions, hoppers, dispensers and droppers, comparators reading
containers, weather-driven blocks. The library code lives in
crates/horizon-world/src/level/. The client glue lives in
crates/horizon-client/src/game/ (growth.rs, tnt.rs, explosion.rs,
machines.rs, blockctl.rs).
Implemented (ported from the 26.3 sources)
-
Growth through live feature placement.
worldgen/live.rsdecodes configured and placed features by name from the worldgen bundle. It shares the generator'sGeneratorData.level/feature_world.rsruns features on the live level as aFeatureWorldandPlacementContext, and writes blocks throughBehaviours::set_blockwith the feature's flags. Tree placement also callsupdateShapeAtEdge. -
TreeGrower.growTree(level/growth.rs) covers every vanilla grower: oak and its bee variants (with the flower check), spruce, birch, jungle, acacia, cherry, mangrove, azalea and poplar. It also covers the 2×2 forms: dark oak, pale oak, mega spruce and pine, and mega jungle. It keeps the random draw order: mega feature, then flowers, then feature. Saplings are removed with flags 818 and restored with flags 260 when the tree does not fit. Saplings, propagules and azaleas grow both on random ticks and with bone meal. -
Bone meal (
level/bonemeal.rs) portsBoneMealItem.useOn,growCropandgrowWaterPlant, including coral from bone meal in warm ocean biomes. It also ports every vanillaBonemealableBlock:- saplings, propagules, mushrooms, fungi and azaleas
- grass (with the biome's
getBoneMealFeatures), nylium, netherrack and moss - rooted dirt, mangrove leaves, crops (including beetroot and torchflower increments) and stems
- pitcher, bamboo and bamboo sapling, cocoa and sweet berries
- tall grass and fern, tall flowers, bush and firefly bush, flower beds
- kelp, twisting and weeping vines, cave vines (head and body), seagrass and sea pickles
- big and small dripleaf, glow lichen (
MultifaceSpreader), hanging moss and pale moss carpet - short and tall dry grass, and shelf mushroom
Level event 1505 plays the bone meal sound.
-
Fixes to existing ticks. Torchflower crops now mature into torchflowers. Kelp grows into any water block, as in vanilla.
-
Primed TNT (
game/tnt.rs):- It has an 80-tick fuse, gravity 0.04, 0.98 drag and the 0.7/−0.5 ground bounce.
- It explodes with power 4 at
y + 0.06125. - It renders with the
TntRendererswell and a white flash every 5 ticks (entity overlay 4 inentity.wgsl). - TNT is primed by redstone, fire, flint and steel or fire charges
(
TntBlock.useItemOn), and by players breaking unstable TNT. - Explosions prime TNT with a random short fuse (chain reactions).
- Dispensers prime TNT too.
-
ServerExplosion(game/explosion.rs):- It marches 1352 rays through a Java
HashSet<BlockPos>(java_hash_map), so iteration and theUtil.shuffledraws match vanilla. - Each block costs
max(block, fluid)resistance. - Damage and knockback scale with exposure for the player, mobs, items and TNT. Creative players take no damage.
- TNT explosions drop every block. Mob explosions use drop decay.
- Drops merge in stacks of up to 16. Container contents spill.
- It marches 1352 rays through a Java
-
Hoppers (
game/machines.rs):- They push and pull through
HopperBlockEntity.tryMoveItems. - The 8-tick cooldown applies, with the transfer cooldown hand-off between hoppers.
- They insert into furnace faces (
WorldlyContainerslots, fuel and bucket rules) and into double chests (right half first). - They respect
does_not_block_hoppersand pick up item entities from the suck box. - The
enabledproperty stops them.
- They push and pull through
-
Dispensers and droppers. They use
getRandomSlotand the drop position and velocity fromDefaultDispenseItemBehavior.spawnItem. The dispense behaviours are:- bone meal
- TNT
- flint and steel (fire, TNT, campfires and candles)
- water and lava buckets (including waterlogging)
- empty buckets (fluids, waterlogged blocks and powder snow)
- arrows (power 1.1, uncertainty 6)
Droppers insert into containers. Clicks and failure sounds play.
-
Comparators reading containers.
GameLevelanswersblock_entity_analog_signalwithAbstractContainerMenu.getRedstoneSignalFromContainer. Chests blocked by a conductor read 0. Double chests are combined. Container changes from hoppers, dispensers and the player callcontainer_changed, which runsupdateNeighbourForOutputSignal. -
Weather (
level/weather.rs) uses biome temperatures from the worldgen bundle, with the height adjustment and frozen noise. They feedServerLevel.tickPrecipitation: ice formation, snow accumulation, and cauldrons filling with water or powder snow. They also feedLevel.isRainingAt, which drives farmland moisture and fire going out in rain. -
Day-timeline blocks (
level/timeline.rs):- Eyeblossoms open and close, and potted eyeblossoms follow. Neighbours are
scheduled in the
BlockScanUtilsscan order. - Turtle eggs crack and hatch on sand, using the dawn hatch chance.
- Dried ghasts hydrate while waterlogged.
- Eyeblossoms open and close, and potted eyeblossoms follow. Neighbours are
scheduled in the
-
Landing writes. Farmland trampling and turtle eggs crushed by landing now run neighbour and shape updates, so crops on trampled farmland pop.
-
Smaller fixes.
- Hopper, dispenser and dropper block entities save with their own ids. Barrels and trapped chests do too.
- Their screens use the vanilla hopper and dispenser layouts.
GameLevel::max_yis exclusive, asLevelAccessdocuments.
-
Block entity removal (
level/removal.rs,game/spill.rs):LevelChunk.setBlockStaterunsBlockEntity.preRemoveSideEffectswhen a block's block entity goes with it. Containers spill throughContainers.dropItemStack, jukeboxes and lecterns pop their item, shulker boxes keep theirs, copper chests and statues keep theirs across weathering.Block.dropResourcesdraws when the behaviour calls it and awards ore, sculk and spawner experience; the item entities join the world before the behaviour returns. -
Copper golems (
mobs/copper_golem.rs,game/copper_golems.rs): built from a pumpkin on a copper block (CopperChestBlock.getFromCopperBlock), sheared and equipped by dispensers, weathering, waxing, statues.
Verification
-
tools/test_block_removal_parity.py: 4,000 replacements, destructions and removals of block entity holders with contents match vanilla. The dispenser harness builds, shears and equips copper golems (6,000 cases match). -
Unit tests in
crates/horizon-world/src/level/growth_tests.rscover:- every sapling kind, including the 2×2 trees
- azalea and mangrove growth
- random-tick stage advance followed by growth
- grass bone meal with flowers
- huge mushrooms and crimson fungi
- crop ages, torchflowers, ferns and tall flowers
- snow, ice and rain answers
- eyeblossoms and turtle eggs
They need the feature block exports in
worldgen/blocks(block-properties.nbt). The shared.localbundle lacks those files, so run the tests withHORIZON_RESOURCESpointing at a complete prepared bundle. Without one, the tests skip. -
Client tests cover the Java
Vec3ihash and compare order and the explosion stack merging. -
In the game on the virtual screen, driven by
horizon-ctl:- Bone meal on oak, birch, cherry, 2×2 dark oak, spruce and jungle saplings grew all of them.
- Flint and steel on a TNT cluster: the TNT flashed white and chain exploded, leaving a crater with drops.
- A redstone block primed TNT.
- A chest drained through a hopper chain into a chest at 2.5 items/s. The comparator lit a lamp.
- A dispenser bone-mealed a sapling into a tree. A dropper ejected an item.
- Landing on farmland turned it to dirt and popped the wheat.
- The hopper screen shows the vanilla layout.
New
horizon-ctlcommands drive these checks:setblock,fill,getblockandcontainer.
Known gaps
- Random draws.
- Features placed from block behaviour draw from a copy of the level
random. Their
next_world_*draws and any draws in neighbour updates during placement do not reach the real stream. - The client picks randomly ticking sections from their palettes, so a section whose palette still lists a ticking state no block uses any more gets random ticks that vanilla's exact counts would skip.
- Features placed from block behaviour draw from a copy of the level
random. Their
- Explosion details. Exposure uses full-collision blocks only.
getEntitiesorder is approximate. Experience orbs, falling blocks and arrows are not pushed. - Missing entities.
- Dispensers have no behaviour for fire charges, other projectiles, armour, shulker boxes, boats, minecarts or spawn eggs. Fire charges and most other items drop instead; projectiles, boats, minecarts and spawn eggs are not entities in Horizon.
- Turtle hatchlings and happy ghastlings are reported as
BlockEvents and not spawned. - Hoppers do not see minecart containers. Item entities do not trigger the
hopper's
entityInside; suction covers the same box on the hopper tick.
- Not implemented. The sculk vibration system (sensors, shriekers,
catalyst spread) and creaking hearts. Lightning (
tickThunder). Particles for bone meal, explosions and TNT smoke. - Not saved. Primed TNT and hopper cooldowns (
TransferCooldown).