Compare commits

...
Author SHA1 Message Date
Ludovic MarieandClaude Opus 5.5 cf550b69fd WIP (session wrap-up 2026-10-15): unfinished, not reviewed
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 12:36:19 +02:00
Ludovic MarieandClaude Opus 5.5 ed3d1e1168 Trial spawners run in game
Trial spawner block entities are kept (generated chunks and saves), tick on
the server with the level random and random sequences, spawn persistent
mobs, eject their rewards as items and set their block state, with their
level events and shutter sounds.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 12:20:30 +02:00
Ludovic MarieandClaude Opus 5.5 ca76075cc9 Trial spawner state machine, checked against vanilla
mobs::trial_spawner: TrialSpawner and its state data, the registry
configs (data/*/trial_spawner), the six states, player detection with the
visual line of sight, mob spawns and reward ejection, read and saved as
vanilla does (a field that fails to decode takes its default alone).

tools/test_trial_spawner_parity.py ticks 2,500 random trial spawners in
VanillaNaturalSpawnOracle and natural_spawn_fixture and compares states,
spawns, events and ejected items line by line.

Also: copper grates have no visual shape; a slime's or magma cube's
obstruction box scales with the Size its spawn data sets; LootData::roll_split
for an empty-context getRandomItems.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 12:20:29 +02:00
Ludovic Marie 050b203846 Merge pull request #306 from ludovic111/feat/debug-lightmap
F3+4 shows the lightmap texture in the bottom right corner
2026-10-15 11:39:03 +02:00
Ludovic Marie b6ced87869 Merge pull request #305 from ludovic111/feat/debug-charts
Debug charts: F3+2 frame and tick times, F3+3 ping and bandwidth
2026-10-15 11:38:57 +02:00
Ludovic Marie 89465a8c6d Merge pull request #304 from ludovic111/feat/create-world-tabs
Create New World: vanilla's Game, World and More tabs
2026-10-15 11:37:55 +02:00
Ludovic Marie fd8223061c Merge pull request #303 from ludovic111/feat/list-scrollbars
World list and pack lists: vanilla scroller, dragged with the pointer
2026-10-15 11:37:49 +02:00
Ludovic Marie 889fff562d Merge pull request #301 from ludovic111/feat/multiplayer-lan-scanning
Multiplayer: vanilla's server list, with the LAN scanning text and its animated dots
2026-10-15 11:37:43 +02:00
Ludovic Marie fbb458252f Merge pull request #299 from ludovic111/feat/menu-blur
Blur the panorama behind world selection, multiplayer and world creation, as vanilla does
2026-10-15 11:37:36 +02:00
Ludovic Marie b92cc7c9e8 Merge pull request #295 from ludovic111/feat/recipe-toast-icons
Recipe toasts show the workstation icon and cycle through the unlocked recipes
2026-10-15 11:37:23 +02:00
Ludovic Marie 4abf648a85 Merge pull request #280 from ludovic111/fix/streaming-reload-loop
Stop reloading saved columns every frame after the player moves
2026-10-15 11:27:01 +02:00
Ludovic Marie 5d17c56d77 Merge pull request #269 from ludovic111/perf/worker-face-visibility
Load worlds ~4.7x faster: stop copying the face visibility table per mesh job
2026-10-15 11:26:54 +02:00
Ludovic Marie 9044c69429 Merge pull request #307 from ludovic111/feat/bee-hives
Bees live in hives and nests: they go home, come out in the morning and make honey (#208)
2026-10-15 11:18:21 +02:00
Ludovic Marie 68ec2236e2 Merge pull request #293 from ludovic111/fix/drowned-parity
mob_ai oracle: wait for the light engine before ticking (drowned flake, #290)
2026-10-15 11:13:48 +02:00
Ludovic MarieandClaude Opus 5.5 5876014b57 Droppers and hoppers don't take a beehive for a container
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 10:36:37 +02:00
Ludovic MarieandClaude Opus 5.5 1f4154c0df F3+4 shows the lightmap texture in the bottom right corner
DebugScreenOverlay.toggleLightmapTexture and showLightmapTexture: the 16x16
lightmap at 64x64 on a black border, 2 pixels from the corner, sky light up
and block light right, as vanilla's flipped blit. It shares the bottom of the
screen with the F3+2 and F3+3 charts, so each switch turns the others off.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 10:31:14 +02:00
Ludovic MarieandClaude Opus 5.5 dc863a66a4 Create New World: vanilla's Game, World and More tabs
CreateWorldScreen as in 26.3: a MenuTabBar (tab sprites, header
separators, underline) over the transparent tab header, each tab's
GridLayout aligned at (0.5, 1/6) between it and a 33-pixel footer with
Create New World and Cancel.

Game: the world name box with its save-folder tooltip, Game Mode
(Survival, Hardcore, Creative), Difficulty and Allow Commands, locked
in Hardcore. World: World Type (Default, Superflat), Customize, the seed
box with its hint, and the Generate Structures / Bonus Chest switches.
More: Game Rules, Experiments and Data Packs. Tooltips follow vanilla's.

The choices reach the new world: hardcore, difficulty and allowCommands
in level.dat, and world_gen_settings with the flat preset, structures and
bonus chest written before streaming starts. Re-Create reads them back.

Fixes #281

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 10:24:52 +02:00
Ludovic MarieandClaude Opus 5.5 6ae018055d Debug charts: F3+2 frame and tick times, F3+3 ping and bandwidth
DebugScreenOverlay's FpsDebugChart, TpsDebugChart, PingDebugChart and
BandwidthDebugChart with vanilla's scales, colours and places: 240 samples
(LocalSampleLogger), F3+2 and F3+3 toggles that show the overlay and exclude
each other, the overlay's "Debug charts" lines, and the play-state ping
request and pong response packets the ping chart uses on servers.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 10:16:02 +02:00
Ludovic Marie df0acb2810 Merge pull request #302 from ludovic111/ci/parity-timeout
CI parity: allow 120 minutes so core changes finish instead of timing out
2026-10-15 10:05:43 +02:00
Ludovic MarieandClaude Opus 5.5 a8bd497132 World list and pack lists: vanilla scroller, dragged with the pointer
SelectWorldScreen's list now sits at vanilla's 49..h-60 with the list
background, header and footer separators, white selection outline and
the widget/scroller sprites at the row's right + 8. The scroller follows
the pointer while held (AbstractScrollArea.mouseDragged), the wheel moves
half a row, and the pack screen's lists can be dragged the same way.

Part of #282

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 10:04:37 +02:00
Ludovic MarieandClaude Opus 5.5 f2e87721f4 CI parity: allow 120 minutes, so changes to core crates finish instead of timing out
Changes to horizon-core or horizon-world make ~280-300 harnesses rerun, which takes
60-90 min on the Mac mini runners; at 45 min those runs were cancelled and proved nothing
(#269, #280, #292 today).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:59:10 +02:00
Ludovic Marie 3ed8abd25e Merge pull request #300 from ludovic111/fix/autosave-spike
Autosave stops waiting for entity writes: no more 2 s freeze (#224)
2026-10-15 09:58:50 +02:00
Ludovic Marie c0e1095ea9 Merge pull request #294 from ludovic111/fix/arrow-interpolation
Arrows stop jumping along their path after they land (#278)
2026-10-15 09:58:46 +02:00
Ludovic Marie 9593d9e329 Merge pull request #292 from ludovic111/fix/golem-persistence
Copper golems keep the persistence vanilla saved (#289)
2026-10-15 09:58:42 +02:00
Ludovic MarieandClaude Opus 5.5 587695e108 Multiplayer: vanilla's server list, with the LAN scanning header and its dots (#282)
JoinMultiplayerScreen's layout: the title centred in the 33-pixel header, the
ServerSelectionList between the separators (list background, 305-wide rows,
white selection outline, scissored rows, the scroller sprites), the footer
buttons centred in 60 pixels. The list always ends with the LAN header,
"Scanning for games on your local network" over LoadingDotsText's dots,
then the LAN games. Saved servers show two MOTD lines, the player count and
the ping, pinging or unreachable icon; Edit and Delete need a saved server.
The list scrolls with the wheel and a draggable scrollbar (ui::Scroll, after
AbstractScrollArea).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:48:14 +02:00
Ludovic MarieandClaude Opus 5.5 b18261cc79 Autosave doesn't wait for the entity writes
The autosave queued its chunks without waiting (#284), then saved the
entities with the waiting call. The region writer is one FIFO thread,
so the main thread still waited for every chunk queued before the
entities: a 1.9 s frame at the 5-minute autosave on a world with ~900
columns. Like PersistentEntitySectionManager.autoSave (saveAll's flush
only on save-all and quit), the autosave now queues the entities too.

Part of #224

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:39:04 +02:00
Ludovic MarieandClaude Opus 5.5 6953710c74 Blur the panorama behind the title menus' screens, as vanilla does (#282)
Screen.extractBlurredBackground: every classic screen reached from the title
(world selection and creation, multiplayer, options) blurs the panorama with
vanilla's minecraft:blur post chain, three horizontal and vertical box blur
passes of menuBackgroundBlurriness pixels, then draws menu_background over it
instead of a flat dark fill. The title screen itself stays sharp.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:32:16 +02:00
Ludovic Marie 02cfbf6f28 Merge pull request #298 from ludovic111/fix/firework-entity-light
Draw flying firework rockets as their lit item model like vanilla
2026-10-15 09:31:33 +02:00
Ludovic Marie eb1467f45f Merge pull request #297 from ludovic111/fix/leaves-option-remesh
Rebuild every section when See-Through Leaves, Smooth Lighting or Biome Blend changes
2026-10-15 09:30:39 +02:00
Ludovic Marie bab7cf92a7 Merge pull request #296 from ludovic111/fix/reversed-z-depth
Render the world with reversed depth like vanilla (far fire no longer flickers)
2026-10-15 09:30:02 +02:00
Ludovic MarieandClaude Opus 5.5 cf67db1873 Render firework rockets as their lit item model like vanilla
FireworkEntityRenderer submits the rocket's item in the GROUND context,
turned to the camera (and over on its side when shot at an angle), at the
packed light of its eye. Horizon drew a flat 0.5-block sprite at full
brightness, so rockets glowed at night and had no item shading.

Fixes #279

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:24:19 +02:00
Ludovic MarieandClaude Opus 5.5 81b07d1dd9 Rebuild every section when a meshing option changes like vanilla
Options.cutoutLeaves, ambientOcclusion and biomeBlendRadius call
LevelExtractor.allChanged when they change. Horizon only handed the new
value to the mesher, so after turning See-Through Leaves off the loaded
sections kept their see-through leaves, pale against the sky, beside the
opaque ones of sections rebuilt later.

Fixes #273

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:24:19 +02:00
Ludovic MarieandClaude Opus 5.5 1bfef88477 Render the world with reversed depth like vanilla
Vanilla 26.3's Projection passes its planes reversed and every pipeline
tests GREATER_THAN_OR_EQUAL. Horizon kept forward depth with a 0.05 near
plane, so far geometry lost precision and fire_side's quad, 0.01 pixel in
front of the block it burns on, z-fought with it.

Fixes #272

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:24:19 +02:00
Ludovic MarieandClaude Opus 5.5 111b237b6d Bees live in hives and nests: they go home, come out in the morning and make honey (#208)
BeehiveBlockEntity (crate::beehive): up to three bees stored as entity
tags, out when their time is up (not at night, in the rain or through a
blocked front unless in an emergency), honey for nectar, the flower they
knew; vanilla's bees / flower_pos save format. Bees find a hive with room
(BeeLocateHiveGoal), fly home and go in (BeeEnterHiveGoal through
MobEvent::EnterHive). In the game hives tick, breaking one lets the bees
out angry unless smoked, fire empties it, dispensers release them.

mob_ai: bee_hive_night, _rain, _morning and _honey match vanilla.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:14:21 +02:00
Ludovic MarieandClaude Opus 5.5 5530d682ab Arrows interpolate from their last tick, not from where they were shot
arrows::tick never set the projectile's previous position (Entity.setOldPosAndRot
at the start of every tick); Projectile::tick does, but arrows don't go
through it. The renderer lerped from the spawn point to the current
position every frame, so a flying or stuck arrow jumped along its whole
path. The arrow harness now prints the old position too.

Fixes #278

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 09:03:39 +02:00
Ludovic MarieandClaude Opus 5.5 f88bfc66f8 Recipe toasts show the crafting station and cycle through every unlocked recipe (#283)
RecipeToast keeps the station and result of each display unlocked while it
is up, draws the station at 0.6 scale in the plaque's corner over the result,
takes turns through them over the display time and stays up five more seconds
after each unlock. Toasts slide in and out on ToastInstance's squared curve,
honour notificationDisplayTime and play ui.toast.in / ui.toast.out.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 08:55:36 +02:00
Ludovic MarieandClaude Opus 5.5 fa188fca42 mob_ai oracle: wait for the scene's light updates before ticking (#290)
The oracle started a scenario once hasLightWork() had been false for six
ticks, but light updates reach the light thread through the chunk task
dispatcher, where hasLightWork() can't see them. A drowned's first
sun-burn roll (Mob.isSunBurnTick draws only when the brightness at its
eyes is above 0.5) then read the dirt's light under a freshly filled
pool or the water's, depending on thread timing: one random draw more or
less, and drowned_pool / drowned_pool_swimmer failed at random.

Queue ThreadedLevelLightEngine.waitForPendingTasks on every forced chunk
after building the scene and tick only once they have all completed.

Fixes #290

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 08:34:05 +02:00
Ludovic Marie b5a2afb71e Merge pull request #291 from ludovic111/feat/bee-flight
Bees fly, pollinate flowers, get angry and sting
2026-10-15 08:19:07 +02:00
Ludovic Marie 77cad63374 Merge pull request #287 from ludovic111/fix/bat-flight
Bats hang upside down and fly, with their wing animations
2026-10-15 08:12:08 +02:00
Ludovic Marie 271a26515a Merge pull request #285 from ludovic111/fix/strider-lava
Striders stand on lava instead of bobbing in it
2026-10-15 08:08:58 +02:00
Ludovic MarieandClaude Opus 5.5 7c2a31206c Bees fly, pollinate flowers, get angry and sting (#208)
A port of vanilla 26.3 Bee: FlyingMoveControl and flying navigation,
hover wandering, flower search and pollination (nectar), growing crops,
tempting and breeding, persistent anger with the hurt-by alert, the sting
(poison, stinger lost, later death), drowning, staying home at night and
in rain, roll, textures and NBT. Hives as homes are not simulated yet.

FlyingMoveControl clamps the pitch like Entity.setXRot, so a rotlerp
that wraps to 359 gives 90 as in vanilla.

Mob AI parity: 9 bee scenarios, 3609/3609 ticks; full harness 120/120.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:57:51 +02:00
Ludovic MarieandClaude Opus 5.5 2bcb30b375 Bats hang upside down and fly, with their wing animations (#215)
Bats fell into the generic fallback AI and walked like land animals; their
animation states were never started. Port vanilla Bat: hanging from a solid
block until a player comes within 4 blocks or the block goes, the take-off
level event, customServerAiStep's flight towards random nearby air, Bat.tick
(held to the ceiling while resting, vertical speed scaled by 0.6 in flight),
setupAnimationStates (flying and resting keyframes), waking when hurt,
BatFlags in the save, no fall damage, movement events without sounds, the
lower voice pitch, and no omnidirectional air drag (vanilla gives that only
to bees, parrots and sulfur cubes).

Mob AI parity harness: six bat scenarios, 6/6 match (1906/1906 mob-ticks).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:57:51 +02:00
Ludovic MarieandClaude Opus 5.5 8cd97334bf Striders stand on lava instead of bobbing in it (#256)
Striders fell into the generic fallback AI, whose FloatGoal jumped them
up and down in lava. Port vanilla Strider: its goals (no FloatGoal,
StriderGoToLavaGoal, RandomStrollGoal every 60 ticks, LookAtPlayerGoal for
striders), floatStrider, standing on lava sources through the living
collision context and the half-block liquid shape, travelling in air where
lava holds it up, StriderPathNavigation's lava destinations, the walk target
value, going cold (suffocating speed modifier, cold texture) away from warm
blocks, the happy/retreat sounds and a lava-proof checkFallDamage.

Mobs now keep Entity.mainSupportingBlockPos from their last move, as
getBlockStateOnLegacy reads it.

Mob AI parity harness: five strider scenarios, 5/5 match (1105/1105
mob-ticks; 0/5 and 5/1105 before).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:57:51 +02:00
Ludovic MarieandClaude Opus 5.5 fb15822b3b Load PersistenceRequired as vanilla does: copper golems save 0 again
Mob.readAdditionalSaveData assigns persistenceRequired from the tag,
overriding the constructor's setPersistenceRequired (copper golems,
elder guardians). Horizon ORed it in, so a copper golem vanilla saved
with 0 came back with 1. The monument's elder guardian, which Horizon
builds from NBT where vanilla calls the constructor, now carries the
flag in its spawn NBT.

Fixes #289

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:41:31 +02:00
Ludovic Marie e626a727a1 Merge pull request #267 from ludovic111/feat/perf-mesh-once
Mesh each column once its neighbours' light has settled
2026-10-15 07:35:44 +02:00
Ludovic Marie 6dde5ec2d0 Merge pull request #288 from ludovic111/fix/save-roundtrip-macos
Run the save round-trip harness on macOS without vscreen
2026-10-15 07:26:54 +02:00
Ludovic Marie 282acfe086 Merge pull request #254 from ludovic111/feat/perf-battery-mode
Battery mode: an opt-in 60 FPS cap (30 in menus or unfocused) and half the worker threads
2026-10-15 07:23:31 +02:00
Ludovic Marie 0f569a4918 Merge pull request #261 from ludovic111/feat/launcher-perf
Launcher measurements: a session performance log and horizon-launcher benchmark
2026-10-15 07:20:59 +02:00
Ludovic Marie a6860bbec6 Merge pull request #263 from ludovic111/feat/benchmark-mode
horizon-client --benchmark SCENARIO: benchmark your own machine, report in the shared format
2026-10-15 07:20:54 +02:00
Ludovic Marie 18234d3a01 Merge pull request #264 from ludovic111/feat/perf-bench-report-v1
perf_bench.py: repeats with 95% CIs, the shared report format, loads end when meshing is done
2026-10-15 07:20:42 +02:00
Ludovic Marie 7b6ef36d90 Merge pull request #247 from ludovic111/feat/bench-report
Benchmark report format v1 (docs/benchmark-report.md, crates/horizon-bench)
2026-10-15 07:20:04 +02:00
Ludovic MarieandClaude Opus 5.5 0c685d9db4 Stop reloading saved columns every frame after the player moves
Generation asked for columns within the view distance + 3 or two of a
finished chunk, but a column that came back finished (loaded from the
save) was kept only within + 2 or one of a finished chunk. After a
teleport, saved columns in between were loaded, dropped, asked for and
loaded again on every frame, forever: 8 of them at render distance 16
held 8 of the 39 in-flight generation slots and kept the disk and a
worker busy. The requested, kept and unloaded ranges now live in Ranges
and nest; requested_columns_stay_loaded checks it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:14:31 +02:00
Ludovic Marie 375a685b84 Merge pull request #230 from rdbtCVS/perf/generation-scan-invalidation-20261014
perf(streaming): skip unchanged generation scans
2026-10-15 07:11:36 +02:00
Ludovic MarieandClaude Opus 5.5 e64c80243d Run the save round-trip harness on macOS without vscreen
On macOS the Horizon client renders offscreen (--offscreen) with audio off,
from the logged-in session; Linux keeps vscreen and the null ALSA device.
The vanilla side was already a headless dedicated server. --bin-dir is
resolved, since the client runs from the run folder. parity.py no longer
skips save_roundtrip off Linux; it stays local-only (no rendering over SSH).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:04:56 +02:00
Ludovic MarieandClaude Opus 5.5 78f206bc22 Mesh only when no neighbour is being lit; skip columns that can't be lit yet
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:04:25 +02:00
Ludovic MarieandClaude Opus 5.5 4f3326e983 Mesh a column once its neighbours' light has settled
A new chunk relights its eight neighbours, and every finished light job
dirties all sections of the 3x3 columns around it. Meshing waited only for
the column itself to be lit, so sections near the loading frontier were
meshed with half-settled light and again after each neighbour's relight:
about 2.25 meshes per section while a world loads. Wait until no column of the
3x3 is being lit or queued for light. The final meshes are the same; they are
built once.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:04:25 +02:00
rdbtCVS 69925a57c5 perf(streaming): skip unchanged exhausted generation scans 2026-10-15 07:04:23 +02:00
Ludovic Marie cfa6033535 Merge pull request #220 from rdbtCVS/perf/reuse-pack-overlays-20261014
perf: reuse unchanged resource-pack overlays after validation
2026-10-15 07:03:05 +02:00
Ludovic Marie ff29d50f73 Merge pull request #219 from rdbtCVS/fix/classic-title-menu-parity
Fix classic title menu layout and accessibility shortcut
2026-10-15 07:02:08 +02:00
Ludovic MarieandClaude Opus 5.5 146c0fd3ce benchmark: a load ends when every streaming stage is idle
Same rule as perf_bench: with status.streaming, the last sections are drawn
once no stage has held work for half a second, so the remeshing that
follows a load (fluids settling, random ticks) isn't counted as loading.
Without it, meshing still has to go quiet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:18 +02:00
Ludovic MarieandClaude Opus 5.5 014b1f5267 Benchmark reports go to the telemetry outbox, with the benchmark-upload consent only
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:18 +02:00
Ludovic MarieandClaude Opus 5.5 0f61ed6b63 benchmark: Apple GPUs by name (Metal has no vendor ID)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:18 +02:00
Ludovic MarieandClaude Opus 5.5 32695d4680 benchmark: a load ends when meshing goes quiet too
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:18 +02:00
Ludovic MarieandClaude Opus 5.5 309dea385b horizon-client --benchmark SCENARIO: the perf_bench run from inside the game, written as a report
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:18 +02:00
Ludovic MarieandClaude Opus 5.5 49b6367d2e perf_bench: a load ends when every streaming stage is idle
Builds that report status.streaming are loaded once chunk counts are
stable and no stage (generation, decoration, light, meshing) has held work
for half a second. Meshing going quiet also waited through the remeshing
that follows a load (fluids settling, random ticks: 1500 falling to 60
meshes/s for ~150 s at RD16), which is simulation, not loading. Older
builds keep the meshing-rate rule.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:03 +02:00
Ludovic MarieandClaude Opus 5.5 7d36d09edd perf_bench.py: a load ends when meshing goes quiet too
Sections wait for their neighbours' light before they are meshed, so the
chunk counts settled while edge sections were still undrawn.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:03 +02:00
Ludovic MarieandClaude Opus 5.5 2a91612928 perf_bench.py: repeats, and the benchmark report format v1
Each game runs --repeats times (3) per render distance and writes one v1
report per distance (benchmarks/perf/<label>-rd<N>.json): figures as means
with standard deviation and 95% CI, per-flight frame entries with the fixed
histogram, the hardware without the host name. frames() and summary() match
crates/horizon-bench value for value (tested on the same inputs).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:03 +02:00
Ludovic MarieandClaude Opus 5.5 bb1c292a40 Launcher benchmark reports go to the telemetry outbox with the benchmark-upload consent; tests
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:02 +02:00
Ludovic MarieandClaude Opus 5.5 c78f2d3e27 Launcher measurements: a session performance log and horizon-launcher benchmark
Each session rewrites benchmarks/launcher-<time>-session.json in the data
folder (report format v1): start to first frame, release list fetch,
install/update and prepare durations, Play to the game's first frame (the
game now logs its first frame), RSS, UI frame times, binary size.
horizon-launcher benchmark starts the launcher N times (cold, then warm),
switches pages, measures idle CPU and memory and the release list fetch,
and writes one report with means and 95% CIs. Nothing is uploaded.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:01:02 +02:00
Ludovic MarieandClaude Opus 5.5 650ad39d85 Benchmark report uploads are dated to the day, like every telemetry item
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:00:54 +02:00
Ludovic MarieandClaude Opus 5.5 a500e25705 horizon-bench: load average, power source, RSS and CPU time probes; launcher metric names
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:00:54 +02:00
Ludovic MarieandClaude Opus 5.5 e0ab3f8fcc Benchmark report format v1: docs/benchmark-report.md and crates/horizon-bench
One versioned JSON report for every benchmark Horizon writes (the game's
--benchmark, the launcher's measurements, tools/perf_bench.py): the local log
a player can attach and, with consent, what the telemetry upload sends.
Summaries over repeats (mean, stdev, 95% CI) and fixed-edge frame-time
histograms, never raw frame streams; no host, user or path in uploads.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:00:54 +02:00
Ludovic Marie c44d311d46 Merge pull request #239 from rdbtCVS/perf/chunk-membership-sync-20261014
perf(client): skip tick chunk synchronization when membership is unchanged
2026-10-15 06:58:40 +02:00
Ludovic Marie c8ce1e081d Merge pull request #184 from rdbtCVS/t3code/fix-effect-icon-rendering
Fix status effect icons and display effects in inventories
2026-10-15 06:58:33 +02:00
Ludovic Marie 9b0d8fd7d7 Merge pull request #204 from rdbtCVS/perf/entity-model-document-20261014
perf(client): share parsed entity models across startup batches
2026-10-15 06:58:11 +02:00
Ludovic Marie 639d315859 Merge pull request #210 from rdbtCVS/perf/single-state-model-parse-20261014
perf(client): reuse parsed model states during preparation
2026-10-15 06:56:45 +02:00
Ludovic Marie 407e863d9f Merge pull request #233 from rdbtCVS/perf/lighting-worker-results-20261014
perf: return only lighting from chunk light workers
2026-10-15 06:56:10 +02:00
Ludovic Marie 5071cd785a Merge pull request #237 from rdbtCVS/perf/entity-material-buckets-20261014
perf: reuse renderer entity material batching buffers
2026-10-15 06:55:45 +02:00
Ludovic Marie 3df34df87b Merge pull request #284 from ludovic111/fix/bastion-chunks
Save every generated chunk and decorated proto chunks, as vanilla does (#249)
2026-10-15 06:48:44 +02:00
Ludovic Marie 8965ca5e2b Merge pull request #274 from ludovic111/fix/mesh-out-of-range
Mesh columns loaded past the render distance once they come in range (#228)
2026-10-15 06:48:24 +02:00
Ludovic Marie 30144e478d Merge pull request #206 from ludovic111/feat/perf-bench
Benchmark Horizon against vanilla 26.3 and vanilla + performance mods (tools/perf_bench.py, docs/benchmark.md)
2026-10-15 06:38:45 +02:00
Ludovic MarieandClaude Opus 5.5 1c3fd6e23c Save every generated chunk and the proto chunks decoration wrote to (#249)
Horizon saved a chunk only once a player changed it and never saved proto
chunks, so leaving an area dropped decorated chunks while the final chunks
next to them stayed loaded (or were regenerated later). Coming back, those
chunks were generated again and their decoration was skipped beside a final
neighbour: whole chunks of a bastion lost their pieces, other chunks their
features. Like vanilla, generated chunks are now saved, proto chunks that
decoration wrote to are saved with their status (terrain or features) and
restored onto the chunk generated again, columns that finish after the player
left are saved, and saving waits for the decorations in flight.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 06:37:05 +02:00
Ludovic MarieandClaude Opus 5.5 4901bdf231 Mesh sections of columns that load past the render distance once in range (#228)
The mesh loop dropped every dirty section of a loaded column outside the
render distance. Columns load up to three chunks past it, and a column
loaded from a save with its light runs no light job, so nothing asked for
its sections again: once the player came closer it stayed invisible until
a block in it changed. Those sections now wait and are put back when the
centre, radius or forced chunks change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 06:12:18 +02:00
Ludovic Marie 087cbacdc4 Merge pull request #268 from Online5277/fix/entity-use-occlusion
Prevent block interactions through targeted entities
2026-10-15 05:38:42 +02:00
Ludovic Marie 416012ad4c Merge pull request #241 from ludovic111/feat/controllers2-focus
Controllers: focus navigation in menus, on-screen keyboard, menu navigation option
2026-10-15 05:25:30 +02:00
Ludovic Marie 5c2201a781 Merge pull request #200 from ludovic111/feat/friends-join
Play with friends (3/3): Join a friend with the code alone, in game and in the launcher; end-to-end harness
2026-10-15 05:07:05 +02:00
Ludovic Marie 44a78fe65e Merge pull request #199 from ludovic111/feat/friends-host
Play with friends (2/3): Invite friends in the pause menu (no server needed)
2026-10-15 05:06:36 +02:00
Ludovic MarieandClaude Opus 5.5 213af61b92 status: report each streaming stage's work
`status` gains `streaming` (queued jobs, chunks generating, protos waiting for
decoration, decorating, finishing, lighting, meshing) and `dirty_light`, so a
slow load shows which stage it waits on.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 04:55:14 +02:00
Ludovic Marie 12b5e39ac8 Merge pull request #192 from ludovic111/feat/friends-relay
Play with friends (1/3): invite codes that need no server, port mapping, STUN, a relay anyone can run
2026-10-15 04:49:42 +02:00
Ludovic Marie 7a184a41f0 Merge pull request #259 from Online5277/fix/options-list-clipping
Clip options rows smoothly at list boundaries
2026-10-15 04:39:25 +02:00
Ludovic Marie ef569d3201 Merge pull request #262 from Online5277/fix/spectator-movement
Prevent climbable blocks from slowing spectator flight
2026-10-15 04:39:22 +02:00
Ludovic Marie 20ecaf0254 Merge pull request #266 from Online5277/fix/gamemode-switcher
Add the F3+F4 game mode switcher
2026-10-15 04:39:17 +02:00
Ludovic Marie 503b91df33 Merge pull request #260 from Online5277/fix/cloud-settings
Honor Off, Fast and Fancy cloud settings
2026-10-15 04:38:40 +02:00
Ludovic MarieandClaude Opus 5.5 75a30185a5 Keep blank splash lines like SplashManager.prepare
Vanilla trims each line and drops only the hidden splash (hash 125780783);
a blank line stays a (blank) splash.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 04:37:23 +02:00
rdbtCVS bd4101e9d1 Update merged world-menu test for title resource loading 2026-10-15 04:37:23 +02:00
rdbtCVS a0f3315a79 Address title menu review: language, icon opacity, and splash behavior 2026-10-15 04:37:23 +02:00
rdbtCVS cccb5bff96 Match Minecraft integer centering for title menu icons 2026-10-15 04:37:08 +02:00
rdbtCVS 6cdcf6c85a Fix classic title menu layout and accessibility shortcut 2026-10-15 04:37:08 +02:00
Cosmic 22e548471c Keep entity item use from falling through to blocks 2026-10-14 22:22:01 -04:00
Cosmic 25858f63ae Add the F3+F4 game mode switcher 2026-10-14 22:09:12 -04:00
Ludovic MarieandClaude Opus 5.5 50a1649dea Pack small palettes without hashing
PalettedContainer::pack hashed all 4096 values with SipHash to build the
palette. It now shares from_values' scan, which only switches to a map
past 16 distinct values. Same palette order, same output.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 04:06:42 +02:00
Ludovic MarieandClaude Opus 5.5 ed8f3d70b8 Keep each worker's face visibility table across mesh jobs
Every mesh job cloned the whole FaceVisibility (every state, every face
VoxelShape and the occlusion cache) and dropped it afterwards: about half
of the workers' busy time while a world loads. Each worker now keeps its
copy, like vanilla's per-thread occlusion cache, and clones a new one only
when the mesh tables change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 04:06:42 +02:00
Cosmic 4c7d77352e Skip climbable movement limits for spectators 2026-10-14 21:55:34 -04:00
Cosmic 21411176a7 Honor Off and Fast cloud settings 2026-10-14 21:47:18 -04:00
Cosmic ede136bdd2 Clip partially visible options list rows 2026-10-14 21:42:07 -04:00
Ludovic MarieandClaude Opus 5.5 e6be303517 docs/benchmark.md: no unmeasured startup figure
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:40:12 +02:00
Ludovic MarieandClaude Opus 5.5 b691b5ebaa Benchmark Horizon against vanilla 26.3 and vanilla with performance mods
tools/perf_bench.py runs Horizon, the vanilla 26.3 client and vanilla with
Sodium, Lithium, FerriteCore and ImmediatelyFast through the same steps:
fresh world (seed 1234, creative) per render distance, start to title, start
to in-world, then per scene teleport, chunk load, settle and a fixed 192-block
flight. Every frame time is kept and one function computes average FPS, 1% and
0.1% lows, p50/p95/p99/p99.9 and a frame-time histogram for every game; RSS is
sampled from outside the process for every game. One options.txt (vanilla's
keys, Fancy preset values with a Custom preset so the render distance holds)
is written for all of them.

Vanilla is driven by a dev-only Fabric mod (mods/horizon/src/bench) compiled
against the user's own client jar: it creates the world with
WorldOpenFlows.createFreshLevel, teleports with /tp and places the player on
the path every frame as horizon-ctl fly does. Nothing of the game is
redistributed and the performance mods are fetched from Modrinth with the
hashes pinned in packs/mods.lock.json.

Horizon side: `fly ... PITCH raw` also replies with every frame time, and
--offscreen drives frames from the event loop, so a window nobody sees (a
locked macOS session) still renders.

docs/benchmark.md describes what is measured, how fairness is kept, the
caveats and how to reproduce it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:40:12 +02:00
Ludovic Marie ff5df6aa5e Merge pull request #257 from Online5277/fix/keybind-scrollbar
Make options list scrollbars draggable
2026-10-15 03:38:29 +02:00
Cosmic 7cfede86f4 Handle dragging in options list scrollbars 2026-10-14 21:34:04 -04:00
Ludovic MarieandClaude Opus 5.5 bf74ac6f30 Controllers: the Steam keyboard choice falls back to Horizon's without xdg-open
Picked by hand on macOS or Windows, A on a text field opened nothing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:10:27 +02:00
Ludovic MarieandClaude Opus 5.5 635622652e Controllers: options sub-pages keep the classic focus highlight under the Horizon style
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:10:15 +02:00
Ludovic MarieandClaude Opus 5.5 210a6f5ddd Controllers: focus follows scrolled lists, clipped targets, pad status shows focus
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:10:15 +02:00
Ludovic MarieandClaude Opus 5.5 9927d06049 Controllers: focus navigation in menus, on-screen keyboard, menu navigation option
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:10:15 +02:00
Ludovic MarieandClaude Opus 5.5 c9b3a06cf7 Launcher lockfile: horizon-friends' if-addrs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 7a475a948c Invite friends works with no relay: the code, and what friends can expect
Sharing no longer needs a relay. The panel shows the full invite code in
groups (monospace, wrapped) with Copy and Stop sharing, then who can join:
friends anywhere when the router opened the port or this computer has a
public address; otherwise what to do (UPnP, the port to forward and the
LAN address, a relay, a VPN; CGNAT called out) with a link to the
troubleshooting docs. A relay set in horizon.txt (friendsRelay) or
HORIZON_RELAY_URL adds its short code. horizon.txt keeps other lines when
the menu style is saved.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 fe7df463fa Play with friends: bound handshakes and the relay's first line in time, cap relay connections
A read timeout restarts with every byte, so a peer trickling one byte at
a time could hold the host's 8 handshake slots (or relay threads) for
hours. The host's openings and the relay's first line now end after 10 s
in all; the relay closes connections past RELAY_MAX_CONNECTIONS (4096).
The docs say what happens to a router mapping when the game crashes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 9e6d248fbe test_friends: --xvfb and --offscreen for headless Linux machines
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 872e77e19b Invite friends: who is here and notices read in the muted colour, the hint stays faint
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 a3913be641 Join a friend with the full code (no server) or a relay's short code
The game joins `friend:CODE` with either code: a full invite is dialled
directly, then through the relay it names; a short code goes through the
relay the player set. Join a friend gains a Relay (optional) field, saved
to horizon.txt (friendsRelay) and used for hosting too; the code field
shows the end of long codes and says what is wrong with one (typo, other
version, short code without a relay). The launcher validates both kinds.

tools/test_friends.py now runs (a) the code alone with no relay anywhere
and (b) a relay run locally with the short code; routers and STUN stay
out of tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 241dee2649 Invite friends: count direct and relayed sessions in friends status
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 341aa98a96 test_friends: --hold for the guest role, report chunks once they arrive
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 21a70c8e97 LAN: a guest's entity id no longer takes the host's
Hub::admit read the entity counter before incrementing it, while the game
increments first (the current value is the last id in use). The first
guest after Open to LAN got the host's own entity id, so its client took
the host's AddEntity for itself and never showed the host.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 c7f30d2105 Relay: RELAY_BIND listens on one address (tailnet-only test relays)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 7784350bad Play with friends: Invite friends in the pause menu
The Horizon pause menu gains "Invite friends" beside Open to LAN. It opens
the world to LAN if it isn't (Open to LAN's defaults) and shares that port
behind an invite code through the relay; the menu shows the code with Copy
and Stop sharing, who is here and why the code changed. Closing the LAN
server ends the code; stopping sharing closes LAN again if sharing opened
it. `horizon-ctl friends host|stop|status` drives it in harnesses.

Without HORIZON_RELAY_URL (the default until a relay is deployed) the button
is disabled and says the feature isn't available yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic MarieandClaude Opus 5.5 5d29f31663 Play with friends: Join a friend in game and in the launcher
The game joins `friend:CODE` addresses: the network thread resolves the code
through the relay, agrees on the key, settles on a direct or relayed stream
and connects the client to the tunnel's loopback port; everything after is
an ordinary join. Errors (unknown or ended code, wrong secret, host not
answering, version mismatch, rate limits) end on the Disconnected screen in
plain words. Shown and logged addresses hide the code's secret half.

Horizon's multiplayer page gains "Join a friend" (a code field); the classic
screens keep vanilla's buttons. The launcher's Play page gains a "Join a
friend" row (paste works) that starts the game straight into the join;
`horizon-launcher play --join CODE` does the same.

tools/test_friends.py runs a relay, a host Horizon sharing a world and a
guest Horizon, over plain LAN (--baseline), the direct path and the forced
relay path: chat, movement and blocks both ways, then the ended invite.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:08:07 +02:00
Ludovic Marie 6ddabae4dd Merge pull request #238 from ludovic111/fix/player-water-physics
Player water on #59: bubble columns, swim sounds, drown bubbles, vanilla fixes
2026-10-15 03:07:20 +02:00
Ludovic MarieandClaude Opus 5.5 dbc85822c1 Battery mode: a one-line description
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:07:02 +02:00
Ludovic Marie 6da701a669 Merge pull request #253 from ludovic111/feat/telemetry-privacy
website: privacy page for opt-in data collection
2026-10-15 03:06:13 +02:00
Ludovic MarieandClaude Opus 5.5 61b0aafbf8 Relay: no hosting platform in its comments
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:05:54 +02:00
Ludovic MarieandClaude Opus 5.5 5189a735c7 Invite codes: one address per LAN, no unique-local IPv6, the macOS firewall prompt in the docs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:05:54 +02:00
Ludovic MarieandClaude Opus 5.5 de464a8fc0 Play with friends without a server: endpoints and key in the code
Ludovic can't pay for a hosted relay, so nothing depends on one now. The
host's game finds how it can be reached on its own: its interface
addresses (LAN, VPNs such as Tailscale or ZeroTier, IPv6), a port opened
on the router for an hour at a time (PCP, then NAT-PMP, then UPnP IGD;
renewed while sharing, deleted on stop) and its public address from STUN
(Cloudflare's and Google's public servers by default, configurable). The
invite code carries those endpoints and an 80-bit secret in base32 groups
with a checksum; guests dial every endpoint at once and run the same
SPAKE2 + ChaCha20-Poly1305 handshake, no rendezvous involved. When nothing
can reach the host it says why and what to do (UPnP, the port to forward,
a relay, a VPN; CGNAT and double NAT detected).

The relay stays as something anyone can run (binary, Dockerfile, systemd
unit; Railway config removed): with one configured the host also gets a
short code, and the full code names the relay so guests fall back to it.
No relay by default.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:05:54 +02:00
Ludovic MarieandClaude Opus 5.5 74c1a90980 Relay: hand out IPv4 clients' addresses as IPv4
A dual-stack listener reports them as ::ffff:a.b.c.d, which the other end
can't dial from an IPv6-only socket.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:05:54 +02:00
Ludovic MarieandClaude Opus 5.5 60ddf3daf8 Play with friends: invite codes, the relay and the encrypted tunnel
horizon-friends: codes (Crockford base32, nameplate + secret), the relay's
JSON-line protocol, SPAKE2 then ChaCha20-Poly1305 frames keyed off the
code's secret, direct connections (candidates, TCP simultaneous open from
a reuse-port socket) with the relay as fallback, and the host and guest
ends that carry the game's TCP stream between loopback ports.

horizon-relay: the service (codes, rendezvous, byte relay, rate limits,
bandwidth caps, idle timeouts, counts only), its Dockerfile and Railway
config. Nothing is deployed and nothing in the game uses it yet.

Design: docs/play-with-friends.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 03:05:54 +02:00
Ludovic Marie 186cf8c320 Merge pull request #251 from ludovic111/feat/telemetry-server
Opt-in data collection (4/5): the ingest server (SQLite, rollups, retention, aggregate endpoint)
2026-10-15 03:04:31 +02:00
Ludovic Marie 56861be08c Merge pull request #252 from ludovic111/feat/telemetry-game
Opt-in data collection (3/5): the game keeps crash reports and session summaries only with consent
2026-10-15 03:01:37 +02:00
Ludovic Marie f12578238e Merge pull request #248 from ludovic111/feat/telemetry-consent
Opt-in data collection (1/5): consent, payloads, outbox and a gated uploader
2026-10-15 03:01:26 +02:00
Ludovic MarieandClaude Opus 5.5 b3755bd6b1 website: privacy page for opt-in data collection
/privacy says what the launcher may send when a player allows it (performance
summaries, crash and bug reports, benchmark uploads), why, on what basis,
where it is kept and for how long, and how to delete it. The footer links it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:59:29 +02:00
Ludovic MarieandClaude Opus 5.5 12c1af0261 Opt-in data collection (4/5): the ingest server
crates/horizon-telemetry-server, its own workspace like the launcher's (the
game's workspace never builds a web server):
- POST /v1/batch (zstd, decoded and checked by horizon-telemetry), DELETE
  /v1/installs/<id>, GET /v1/aggregate (cached 10 min, CORS for the website),
  GET /healthz.
- SQLite: machine descriptions stored once, one row of columns per session
  with 80-byte summary blobs, zstd bodies for crash/bug/benchmark, daily totals
  rebuilt when a day changes and kept after raw rows expire (180 days). About
  190 bytes per session on disk.
- Per-address token bucket (addresses in memory only), per-install daily cap,
  groups under 5 install-days hidden from the totals.
- Tests: refusals, rate limit, daily cap, deletion (rows and totals), retention,
  storage size, and end to end with the launcher's uploader.
- Dockerfile and a path-filtered CI workflow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:53:59 +02:00
Ludovic MarieandClaude Opus 5.5 d7b975185c Opt-in data collection (3/5): the game obeys the player's consent
The game never sends anything itself; it keeps items in the outbox for the
launcher, and only for kinds the player allows:
- Crash reports: crash::deliver keeps a scrubbed copy (error, stack, thread,
  Horizon version, graphics adapter and render settings; never the log, world,
  server or resource packs; the world's name and folder and the server address
  are scrubbed wherever they appear). Without consent crash-reports/ stays
  local, as before.
- Performance: a Session records frame times while playing and the integrated
  server's tick times into fixed-size Timings, with the time to the title
  screen and to the world; on leaving a world or quitting, a session of a
  minute or more becomes a summary (under 1 KiB) when the player allows it.
- The GPU, its driver and backend come from the wgpu adapter.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:51:02 +02:00
Ludovic MarieandClaude Opus 5.5 a2b2b3f776 Player water on #59: bubble columns, swim sounds, drown bubbles, vanilla fixes
Builds on Cosmic's #59 (player fluid travel, swimming, air supply) and
changes only what differs from vanilla 26.3 or what it lacks:

- BubbleColumnBlock.entityInside for the player (isPrecise, onAbove /
  onInsideBubbleColumn, not while flying) with its splash/bubble particles.
- LocalPlayer.goDownInWater before LivingEntity.aiStep's velocity cleanup.
- The aiStep jump phase as vanilla: nothing while flying, the fluid jump
  threshold from the eye height (also in travelInLava).
- Player.travel: swim steering samples y + 1.0 - 0.1, and LivingEntity.travel
  checks fluids before gliding; water and lava no longer end a glide.
- LocalPlayer.isUnderWater is wasUnderwater; sprint conditions get shallow
  water, flight and gliding; no flight toggle while swimming; the base tick
  runs before local crouching; the desired pose puts swimming before gliding.
- decreaseAirSupply creates the oxygen_bonus instance (getAttribute).
- Swim sounds and muffled steps in water; entity event 67 drown bubbles.
- Scene motion harness: swim_corpus (player travel in water and lava, bubble
  columns, air supply) and sprint-swim cases for --sprint-input.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:45:13 +02:00
Ludovic Marie 89b58991bb Merge pull request #246 from rdbtCVS/perf/save-batch-entity-grouping-20261014
perf: group block entities once per save batch
2026-10-15 02:38:17 +02:00
Ludovic MarieandClaude Opus 5.5 cc8744a06b Trim synthetic overlay benchmarks; record Mac real-pack numbers
The real-pack benchmark on the production resource_root path stays as the
reproducible measurement. On the Mac mini it saves 1.18 s (Faithful 32x) and
5.29 s (FPBR) per startup with the pack enabled.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:26:46 +02:00
Ludovic MarieandClaude Opus 5.5 0229615560 Battery mode: an opt-in frame cap and fewer worker threads
A Horizon graphics setting (Performance, off by default, batteryMode in
horizon-graphics.txt): at most 60 frames per second in a world, 30 in menus
without a world or behind other windows, and half the automatic worker
threads. It only changes when frames are drawn; ticks and what frames show
are untouched.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:24:57 +02:00
Ludovic MarieandClaude Opus 5.5 43138159b2 Opt-in data collection (1/5): consent, payloads, outbox and a gated uploader
horizon-telemetry, shared by the launcher, the game and the ingest server:
- consent.json in the game folder: four switches, all off until the player
  answers, a consent version that re-asks when what is collected changes, the
  answer's time, and a random install ID made at the first yes.
- Payloads: perf summaries (percentiles + 14 frame-time buckets from a
  fixed-size Timings recorder), crash and bug reports, and benchmark reports
  carried as docs/benchmark-report.md defines them; size caps per kind.
- A scrubber for user folders, user names, e-mail and IP addresses, UUIDs and
  caller-known private terms.
- The outbox: only allowed kinds get in, daily caps, 200 items / 2 MiB.
- zstd batches with bounded decoding; the uploader re-reads the consent and
  drops withdrawn items before connecting, backs off and caps batches a day.
- tests/consent_gating.rs: a local mock server sees zero connections with the
  consent missing, outdated or withdrawn.

No server is set (DEFAULT_ENDPOINT is None): nothing is sent yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 02:21:13 +02:00
rdbtCVS 1295fccd17 perf(client): validate overlay reuse with source stamps and benchmark real packs 2026-10-15 02:19:11 +02:00
rdbtCVS 8177726f70 perf: reuse validated resource-pack overlays 2026-10-15 02:19:11 +02:00
rdbtCVS dd5a361a58 bench(client): measure state reuse after slice reader changes 2026-10-15 02:18:30 +02:00
rdbtCVS cb28f691ff perf: return only lighting from chunk light workers 2026-10-15 02:18:30 +02:00
rdbtCVS ded40d60c6 perf(client): reuse parsed model states during preparation 2026-10-15 02:18:30 +02:00
rdbtCVS 2746802152 perf(client): synchronize tick chunk membership only on changes 2026-10-15 02:14:16 +02:00
rdbtCVS 4cac0a13cd perf(client): track structural chunk membership revisions 2026-10-15 02:14:16 +02:00
rdbtCVS 5c076ca38f perf(client): parse entity model document once for startup batches 2026-10-15 02:14:04 +02:00
Ludovic Marie 44144373ea Merge pull request #240 from rdbtCVS/perf/reuse-entity-geometry-20261014
perf: reuse entity geometry vertex storage between frames
2026-10-15 02:13:54 +02:00
Ludovic Marie da0c985d1d Merge pull request #244 from rdbtCVS/fix/launcher-desktop-wrapper
Preserve package wrappers in launcher desktop entries
2026-10-15 02:09:35 +02:00
rdbtCVS a794c05417 bench: measure dense entity geometry buffer reuse 2026-10-15 02:08:23 +02:00
rdbtCVS 90bdf5bb1a perf: retain entity geometry vertex storage between frames 2026-10-15 02:08:23 +02:00
rdbtCVS 34628c1471 perf: group block entities once per save batch 2026-10-15 01:07:56 +01:00
Ludovic Marie 8df59b96a9 Merge pull request #243 from rdbtCVS/perf/visibility-shortcuts-20261014
perf(mesher): short-circuit section visibility flood fills
2026-10-15 02:06:31 +02:00
Ludovic Marie de75330b21 Merge pull request #245 from rdbtCVS/fix/launcher-warning-wrap
fix(launcher): wrap long warnings within the window
2026-10-15 02:06:19 +02:00
rdbtCVS 2491d49bf5 perf: reuse entity material batching scratch buffers 2026-10-15 02:05:41 +02:00
Ludovic Marie 142b8da33e Merge pull request #236 from ludovic111/feat/pr-ready
pr_ready: one self-check for agents and contributors, CONTRIBUTING.md and a PR template
2026-10-15 02:04:01 +02:00
rdbtCVS 954b67ffa2 Merge main and preserve both HUD regression tests 2026-10-15 01:00:00 +01:00
rdbtCVS f9fdcd2912 fix(launcher): let warning text wrap within the page 2026-10-15 00:58:00 +01:00
rdbtCVS 930f6fa19e Honor package wrappers in launcher desktop entries 2026-10-15 00:49:41 +01:00
rdbtCVS 90f84ac10d perf(mesher): short-circuit section visibility flood fills 2026-10-15 00:45:44 +01:00
Ludovic Marie e96e1571e9 Merge pull request #59 from Online5277/fix/vanilla-item-use-animations
Fix animations, axolotls, fluids, fire and world progress isolation
2026-10-15 01:36:40 +02:00
Ludovic Marie af0e0db4ec Merge pull request #205 from rdbtCVS/perf/buffer-json-readers-20261014
perf(client): buffer model and render JSON reads
2026-10-15 01:21:21 +02:00
Ludovic Marie adbbff5904 Merge pull request #234 from ludovic111/fix/horizon-menus-delete-world
Horizon menus: delete singleplayer worlds
2026-10-15 01:18:39 +02:00
Ludovic Marie 1ac9e4860a Merge pull request #207 from rdbtCVS/perf/slice-large-json-20261014
perf(client): parse large fact JSON from in-memory bytes
2026-10-15 01:17:38 +02:00
Ludovic Marie 51a939bd00 Merge pull request #225 from rdbtCVS/perf/single-release-fetch-20261014
perf(launcher): fetch startup releases once for list and updates
2026-10-15 01:17:31 +02:00
Cosmic ccbf6f09c6 Merge latest main without duplicate hurt sounds 2026-10-14 19:17:30 -04:00
Ludovic Marie 61cb0c92bb Merge pull request #190 from Online5277/fix/crosshair-attack-indicator
Match crosshair alpha cutoff and ready-target checks
2026-10-15 01:16:41 +02:00
Ludovic Marie fa8056e172 Merge pull request #226 from ludovic111/feat/rust-edition-title
Title screen: "RUST EDITION" under the logo
2026-10-15 01:16:08 +02:00
Cosmic a18410f92f Merge main while preserving fluid phases and baked arrow rendering 2026-10-14 19:14:59 -04:00
Ludovic MarieandClaude Opus 5.5 48c85fa19f Add tools/pr_ready.py, CONTRIBUTING.md and a pull request template
pr_ready is the one self-check to run before asking for review: from the
files a branch changes it runs rustfmt, clippy with warnings denied, the
tests of the touched crates (mapped through cargo metadata), the launcher's
own workspace when it is affected, the tokens.css check, the Cargo.lock
rule, the Python tests and the public-tree check, and the vanilla harnesses
the change can affect, picked by tools/parity.py exactly as CI's parity job
picks them. It runs locally or on a fleet machine through ~/fleet/rbuild;
on the Mac mini the harnesses use the parity runner's own workspace and
scripts. It prints one Markdown block for the pull request body and exits
non-zero on any failure.

tools/parity.py gains --changed-files for copies without Git history, and
tools/ci/vanilla-data.sh accepts the preparation key from outside.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 01:13:39 +02:00
Ludovic Marie f02db7aede Merge pull request #232 from ludovic111/fix/explorer-maps-147
Explorer, treasure and abandoned camp maps work (#147)
2026-10-15 01:13:24 +02:00
Ludovic MarieandClaude Opus 5.5 4d7ca0fc93 Horizon menus: delete singleplayer worlds
The Horizon-style Singleplayer page had no way to delete a save. A Delete
(danger) button now shows beside Play when a world is selected and opens a
confirmation page in the design language: the world's name and last-played
date in a notice led by the danger dot, "It will be lost forever. This
can't be undone.", then Delete world / Cancel. After deleting, the list
refreshes and the selection moves to the world that took the deleted row
(or the new last one). A failure shows a Horizon error page whose Back
returns to the question.

Both menu styles share world_management::delete, now a port of
LevelStorageAccess.deleteLevel: it takes the world's session lock first, so
a world open in this or another instance is refused, deletes everything but
the lock (retrying five times, 500 ms apart), then releases and removes the
lock and the folder. Only a single plain folder name directly in saves is
accepted, and links inside the world are removed, never followed.

Leaving a world now flushes the region writer and releases the session
lock (vanilla closes the storage access), so the world just played can be
deleted from the title.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 01:12:18 +02:00
Ludovic Marie b980ae9150 Merge pull request #188 from rdbtCVS/fix/title-panorama-quality
Fix pixelated Classic menu panorama
2026-10-15 01:10:47 +02:00
Ludovic Marie b6f1ca63ba Merge pull request #231 from ludovic111/ci/runner-disk
CI disk: short artifact retention, runner cleanup, sccache on the Mac runners
2026-10-15 01:10:25 +02:00
Ludovic MarieandClaude Opus 5.5 2ce2ddcd4d Explorer, treasure and abandoned camp maps work (#147)
Vanilla 26.3 has a MapItem per explorer map (buried_treasure_map,
abandoned_camp_map, woodland_mansion_map...) and treats any stack with a
map_id as a map. Its ExplorationMapFunction finds the nearest structure of
the tag, makes an unlimited tracking map centred on it, draws the biome
preview (MapItem.renderBiomePreviewMap) and adds the target decoration
(MAP_DECORATIONS, drawn by tickCarriedBy). Horizon only recognised
filled_map, turned trade maps into filled_map, cleared every decoration but
the player's each tick, and chest loot only flagged the map as found: the
treasure maps of shipwrecks and underwater ruins and the maps of 26.3's
abandoned camps had no map id, no target and no picture.

- map_id: any stack with the component.
- tick_maps: the item's map_decorations (red X, mansion, camp...) are drawn
  as addDecoration places them (off the map only when unlimited).
- render_biome_preview: vanilla's water outline picture from the noise
  biomes at sea level (new generator query noise_biomes, fuzzed through
  BiomeManager's zoom) and #water_on_map_outlines.
- Chest loot (rolled with the chunk here) keeps the function's search in
  minecraft:custom_data; opening the chest runs it from the chest (vanilla
  runs it when the chest is unpacked on first open), else reaching the
  inventory runs it from the player. Nothing found drops the item, as the
  tables' filtered map_id check does.
- Trades keep their map item.

Fixes #147

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 01:07:48 +02:00
Ludovic MarieandClaude Opus 5.5 7a07251acf CI disk: short artifact retention, runner cleanup, sccache on the Mac runners
Releases now ship as often as changes land, so nothing they leave behind may
grow without bound. Workflow uploads keep 3 days (nightly parity logs 7); the
releases carry their own assets.

tools/ci/runner-gc.sh, run every 6 hours by launchd on the Mac mini from a copy
of main, skips a runner in a job, removes a checkout's cargo build folders past
12 GB and harness work folders under .local/ untouched for 3 days, and keeps the
2 newest shared preparations while no runner works. The runners build through
the machine's sccache, so what it removes comes back from the cache.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 01:05:59 +02:00
Ludovic Marie cc0d6736a1 Merge pull request #229 from ludovic111/ci/release-debounce
Release train: ship every settled player-facing change, no 3-hour gap
2026-10-15 01:01:37 +02:00
Ludovic MarieandClaude Opus 5.5 86e0e122f4 Release train: ship every settled player-facing change, no 3-hour gap
Ludovic wants releases as often as changes land. A kind now releases when
player-facing pull requests merged since its last release and the newest of
them merged 15 minutes ago (a burst of merges becomes one release), or the
oldest an hour ago when merges never pause; release-now still ships at once.
There is no minimum time between releases. The scheduled checks run every 10
minutes (game at :02, launcher at :07) so a settled release goes out without
another merge.

Release titles keep proper nouns (Horizon's mark, Microsoft, LAN, ...) when
they lowercase the clauses after the first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 01:01:26 +02:00
Ludovic Marie 4552494550 Merge pull request #216 from ludovic111/fix/berry-prick-sound-144
Play the player's hurt sound for every damage, by its damage effects (#144)
2026-10-15 00:56:39 +02:00
Ludovic Marie 339bed0b7d Merge pull request #218 from ludovic111/fix/pickup-anim-142
Items, orbs and arrows fly to whoever picks them up (#142)
2026-10-15 00:56:30 +02:00
Ludovic Marie 440d9257ed Merge pull request #214 from ludovic111/fix/lan-name-195
LAN: offline players get a kept generated name instead of Player (#195)
2026-10-15 00:55:56 +02:00
Ludovic MarieandClaude Opus 5.5 8f3f72c7ef Title screen: "RUST EDITION" under the logo
The classic title screen's banner now reads "RUST EDITION". It is rebuilt
at load time from the player's own textures/gui/title/edition.png:
"EDITION" is kept column for column, the "T" is lifted out of it, and R, U
and S are Horizon's own glyphs (rectangles in title_edition.rs) drawn the
way the texture's letters are built, in shades sampled from it. "RUST"
spans "JAVA"'s columns, so the banner stays centred. Only vanilla 26.3's
exact texture (pixel fingerprint) is rebuilt: a resource pack's banner is
left as drawn. No Mojang pixels are added to the repository.

The logo and banner are now blitted as LogoRenderer does: the logo's top
44 of 64 rows and the banner's top 14 of 16 rows at y = 30 + 44 - 7
(the banner was 20 px too low and squeezed 16 rows into 14).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:54:50 +02:00
rdbtCVS aec1519f91 perf(launcher): share startup release response with update check 2026-10-14 23:52:59 +01:00
Ludovic Marie d85aa27aa8 Merge pull request #212 from ludovic111/fix/website-favicon-cache
Website: the new favicon reaches browsers at once, and /favicon.ico exists
2026-10-15 00:51:51 +02:00
rdbtCVS 8b6a2861b5 Merge main and retain both HUD regression tests 2026-10-14 23:33:46 +01:00
Ludovic MarieandClaude Opus 5.5 a3fcacb212 Website: the new favicon reaches browsers at once, and /favicon.ico exists
The icon files kept their names while the server lets browsers cache /favicon*
for a week, so visitors still saw the old mark. The pages now link each icon
with its content hash (?v=…), and the build writes /favicon.ico (the 32-pixel
PNG in an ICO container) for browsers that ask for it on their own.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:32:42 +02:00
Ludovic MarieandClaude Opus 5.5 aec497c94b Items, orbs and arrows fly to whoever picks them up (#142)
Vanilla's ClientPacketListener.handleTakeItemEntity adds an
ItemPickupParticle for every take: the taken entity's render state
(extracted at partial tick 1) moves to the collector's x, (y + eyeY) / 2, z
along ((life + partial) / 3)^2 over three ticks, the target lerped between
ticks (ItemPickupParticleGroup). Horizon removed taken entities at once.

game/pickups.rs keeps those particles (joining the group at the end of the
particle tick, as ParticleEngine.tick does) and the item, orb and arrow
renderers draw them frozen at the moving position. Takes by the player
(items, orbs, arrows), by mobs (allays, villagers, piglins, sulfur cubes,
raid banners), by LAN guests on the host, and ClientboundTakeItemEntity on
a LAN guest or server all add one.

Fixes #142

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:31:19 +02:00
Cosmic e08687f362 Merge main and retain remaining crosshair parity fixes 2026-10-14 18:30:06 -04:00
rdbtCVS 576e88bd8c Zero-pad inventory effect duration fields 2026-10-14 23:29:29 +01:00
Ludovic MarieandClaude Opus 5.5 bf7b3d140f Play the player's hurt sound for every damage, by its damage effects (#144)
Vanilla plays the hurt sound on the client from broadcastDamageEvent
(LivingEntity.handleDamageEvent -> Player.getHurtSound, the damage type's
DamageEffects sound, pitch (r - r) * 0.2 + 1). Horizon only played
entity.player.hurt by hand for falls and mob hits, so sweet berry bushes
(poking -> hurt_sweet_berry_bush), fire and lava (burning -> hurt_on_fire),
drowning, freezing, cactus and the rest were silent.

The combat port's broadcast_damage now carries its damage source
(HealthEvent::DamageBroadcast, same trace line as before) and the game plays
hurt_sound(effects) for it; the two hand-written plays are gone.

Fixes #144

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:24:16 +02:00
Ludovic MarieandClaude Opus 5.5 dacdf69293 LAN: offline players get a kept generated name instead of Player (#195)
Every offline Horizon player joined as Player, the LAN host's own offline
profile, so the host refused every guest with "You logged in from another
location". Vanilla's client defaults --username to Player + millis % 1000
and the launcher passes the account's name. Horizon now generates
Player + five digits once and keeps it in horizon-player.txt next to
options.txt (same name, same offline UUID, same inventory on a friend's
world). --name, HORIZON_PLAYER_NAME and a signed-in account still win.

tools/test_lan_lifecycle.py: two default guests join one host together,
keep their names across rejoins, and a guest named Player is refused.

Fixes #195

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:24:16 +02:00
Ludovic Marie 830e8adbe5 Merge pull request #203 from ludovic111/fix/dedicated-server-spawners
Loaded spawners keep their mob; chunk block entities in vanilla's order
2026-10-15 00:23:26 +02:00
rdbtCVS 2217ebcb33 perf(client): parse large fact JSON from in-memory bytes 2026-10-14 23:21:03 +01:00
Ludovic Marie 02df01adbb Merge pull request #174 from ludovic111/feat/design-website
Website in the new design language
2026-10-15 00:18:33 +02:00
Ludovic Marie fe1b08f83a Merge pull request #173 from ludovic111/feat/design-menus
Game menus (Horizon style) in the new design language
2026-10-15 00:18:17 +02:00
Ludovic Marie b009c7652f Merge pull request #168 from ludovic111/feat/design-launcher
Launcher in the new design language
2026-10-15 00:18:02 +02:00
Ludovic Marie 0a0504dd63 Merge pull request #167 from ludovic111/feat/design-icon
Horizon's mark and its icon everywhere
2026-10-15 00:17:45 +02:00
Ludovic Marie 792aa79b0a Merge pull request #166 from ludovic111/feat/design-tokens
Design system: one set of tokens for the launcher, menus and website
2026-10-15 00:17:29 +02:00
rdbtCVS 99514c4b79 perf(client): buffer model and render JSON reads 2026-10-14 23:16:21 +01:00
Ludovic MarieandClaude Opus 5.5 8a95aa79a7 Website and README: the round-2 menus and launcher screenshots
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 5763ec7e58 Game menus: AA veils over bright backdrops, a whole wordmark on the home page
Every page and the in-world screens veil the backdrop at 0.90; the home page at 0.80, with its
secondary text in ink_soft (Ui::muted). Muted text over the backdrop is BACKDROP_MUTED. The home
page's faint wordmark is now whole: as wide as the content column, above the footnote, instead
of cut off at the bottom right.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 3e39dfae33 Launcher: a development-build override of the Microsoft endpoint, for the sign-in panel
HORIZON_MSA_MICROSOFT_ENDPOINT (debug builds only) points the device-code and token requests at
a local mock, so the restyled code panel can be seen and screenshotted without Microsoft.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 a248e9242a Ship the launcher as Horizon.app in a .dmg, and in Linux's menus
macOS: packaging/macos/package.sh (run by launcher.yml) builds Horizon.app (Info.plist, bundle
id dev.horizon.launcher, macOS 11+, the .icns), signs it ad hoc, and makes the two release
assets: horizon-launcher-macos-arm64.dmg, the installer (the app and an Applications link over
a background, laid out by dmgbuild without a GUI), and the .zip the launcher updates from. A
launcher inside the app replaces the whole bundle: copied beside it with ditto, swapped in by
renames, restarted; a bare binary, as older launchers are, still finds its binary in the zip.
A macOS test zips, unpacks, swaps and re-verifies a signed bundle. Signing for real is a
MACOS_SIGN_IDENTITY away (packaging/macos/README.md, with what Gatekeeper asks meanwhile).

Linux: release builds keep horizon-launcher.desktop (with the binary's current path),
horizon.desktop (hidden, for the game window's icon) and the hicolor icons under
$XDG_DATA_HOME, without root; `horizon-launcher desktop-entry --remove` takes them out and
stops it, `desktop-entry` puts them back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 cd39680534 Show the new launcher and menus on the website and in the README
The README banner is redrawn in the new design (docs/media/banner.html), and the launcher and
menu screenshots (README and website) are the restyled ones. The website's launcher section
gains a Launcher tab: its screenshots no longer show the old background, whose licence was
never confirmed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 2094fb58ad Describe the game menus' sidebar and plates as built
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 275f60efec Launcher settings: a switch for the entry in Linux's applications menu
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 fcbbff26a7 Give Horizon a mark, and its icon everywhere
The mark is an H whose crossbar is the horizon: a violet line edge to edge, the stems above it
and their reflection below at a third, on whole units of a 16-unit grid so it stays sharp at
16 px. docs/media/brand holds the SVG masters (square icon, macOS tile, avatars, the mark for
light and dark backgrounds), the two alternatives that were shown with it, the GitHub social
preview and the Discord banner, and a README of what goes where and how to upload what only
Ludovic's accounts can.

`cargo run -p xtask -- icons` renders the masters (rsvg-convert) and packs, in plain Rust:
packaging/icons/horizon.ico and horizon.icns, Linux's hicolor icons 16–512 and the scalable
SVG, the game's run-time window icon, the avatars and the website's favicons.
packaging/linux has .desktop entries for the launcher and the game.

On Windows, build.rs embeds the .ico as icon resource 1 in horizon-client (and its tools) and
horizon-launcher (winresource, a Windows-only build dependency); gpui loads that resource as
the launcher's window icon. The game window sets the icon itself (X11, Windows) and names
itself `horizon` on Wayland so the desktop entry matches.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 c49a91a22c Restyle the website in the new design language
The page now reads the design tokens generated from crates/horizon-theme (src/tokens.css, put
before style.css by build.mjs), and follows the system's light or dark appearance, with a
toggle that remembers the choice. The full-screen sunset hero is replaced by type: a headline,
one paragraph, the download, and an index list of what the page holds. Every section is a mono
label, a display heading and its content as numbered rows with one-pixel rules: the facts, the
fourteen subsystems, the launcher's features, the community links. Rows fade a soft plate in
under the pointer; content arrives with a short fade, rise and unblur. The footer ends on the
giant faint wordmark. The 404 page and the social preview (og.html) follow.

Instrument Serif, the hero images, the parallax, the statement fill and the magnetic buttons
are gone; the icons come from Horizon's new mark (xtask icons). Touch targets are 44 px high.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 7df75b9d3b Restyle the game's Horizon menus in the new design language
Only Horizon's own style changes (what HORIZON_MENU_STYLE=horizon and "Menu style: Horizon"
show); vanilla's classic screens and the HUD are untouched.

The shared components in ui_theme follow the launcher: pill buttons, the sidebar as text items
with a soft sliding pill under the mark and a name instead of a tinted panel, the segmented
control's ink pill, a 36x20 switch, a thin ink slider, fields without borders, display-size page
titles, mono capitals for status lines and section labels. Settings rows, worlds and servers are
numbered index lists (01, 02…) with one-pixel rules; list rows fade a soft plate in under the
pointer and keep it under the selection. Plates are translucent ink so they read the same over
any backdrop. The veil over the live backdrop is flat (no gradients), lighter on the home page,
which ends on the faint wordmark. The opening's wordmark is "horizon" in Geist.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 86149f7da6 Restyle the launcher in the new design language
A top bar (the mark, Horizon, the pages as text) replaces the sidebar; a mono footer carries
the launcher's version, its update and the community links. Every page is a display title, a
short muted line, then an index list: Play's resources and folders, the versions with their
names large and their size and state in mono, the patch notes, the settings. Buttons are pills,
the main action is the one violet thing on the screen, selection is an ink pill, the console,
notices and the crash report sit on soft plates without borders. The Play page ends with the
faint wordmark, half set below the window's edge.

The sunset photograph and its veils are gone (and the `image` dependency with them): the
window is the page colour, light or dark with the system. The opening draws the wordmark
letter by letter, then the launcher rises into place. HORIZON_LAUNCHER_APPEARANCE=light|dark
overrides the system's appearance, for screenshots and tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 7d26cb0a5b Hold the game menus' text to AA over the brightest backdrops
The veil goes to 0.90 (0.80 on the title's home page, which keeps to ink and ink_soft), and
muted text over the backdrop is lifted to #9fa3ae; a test checks every pair over a backdrop of
luminance 0.77 (the snowiest title panorama measured reaches 0.49), bare and on a row's plate.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:22 +02:00
Ludovic MarieandClaude Opus 5.5 1a730659f0 Add a design system: one set of tokens for the launcher, menus and website
docs/design-system.md describes the new design language (after mkdir.directory: type as the
interface, numbered index lists with hairline rules, one violet accent, space instead of
borders, quiet motion, a faint wordmark) and its tokens, components, surfaces and mark.

crates/horizon-theme now holds the whole system: the two palettes (cool neutrals, light and
dark, each text colour checked against WCAG AA on every background by a test), the type scale
with web sizes, spacing, radii, rules, control heights and motion with CSS easing curves.
Instrument Serif is gone; display type is Geist at medium weight.

`cargo run -p xtask -- tokens` writes website/src/tokens.css from the crate, and a test fails
when the file is out of date. The launcher and the game's menus read the new names through
small adapters; the restyles follow in their own changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:08:22 +02:00
Ludovic Marie 4b4b36b716 Merge pull request #191 from rdbtCVS/t3code/classic-video-gui-button
Fix GUI Scale button in classic Video Settings
2026-10-15 00:08:20 +02:00
Ludovic Marie a5bd5ebf7a Merge pull request #201 from ludovic111/fix/cactus-mips-110
Sprite mips from vanilla's MipmapGenerator: no cactus corner gaps
2026-10-15 00:04:25 +02:00
Ludovic Marie c8dbb00031 Merge pull request #177 from rdbtCVS/t3code/classic-singleplayer-ui-parity
Fix Classic singleplayer world management screens
2026-10-15 00:04:20 +02:00
Ludovic Marie 288ea9dfa1 Merge pull request #198 from ludovic111/fix/end-fog-103
The dragon fight's world fog and the End's void darkness floor
2026-10-15 00:02:15 +02:00
Ludovic Marie e17a40fc6b Merge pull request #197 from ludovic111/fix/end-crystal-102
End crystals from EndCrystalModel: lit, with their base and beams
2026-10-15 00:02:09 +02:00
Ludovic Marie b91288a937 Merge pull request #196 from ludovic111/fix/crosshair-97
Inverting crosshair and a working attack indicator
2026-10-15 00:02:02 +02:00
Ludovic Marie 1643b78d7b Merge pull request #194 from ludovic111/fix/creeper-swell-157
Creepers swell and flash for LAN guests; load ignited from NBT
2026-10-15 00:01:56 +02:00
Ludovic MarieandClaude Opus 5.5 d93b347b41 Loaded spawners keep their mob; chunk block entities in vanilla's order
A saved spawner's block entity id is minecraft:mob_spawner, not its block's
name, so decode_block_entity found no block entity for it and dropped it:
every spawner loaded from a save (a vanilla world's dungeons and mineshafts,
or Horizon's own after a reload) lost its spawn data, and the server sent
its chunk with no update tag. The id now maps to the spawner block.

The chunk packet lists block entities in LevelChunk.blockEntities' order,
which Horizon reproduces from the position hashes; positions sharing a
bucket keep their insertion order, which for a loaded chunk is the save's
block_entities list (SerializableChunkData -> pendingBlockEntities). That
list order is now kept with the chunk and used as the insertion order.

dedicated_server: 542 transcript lines identical (was 10 differing).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 00:00:37 +02:00
Ludovic MarieandClaude Opus 5.5 95db0fce9d Sprite mips from MipmapGenerator: cutout edges keep their coverage
Horizon averaged each mip level's alpha plainly, so a cutout texture's
transparent edges grew past the alpha test with every level: the cactus
side's transparent border columns opened see-through slits along its
corners from about 40 blocks, more than vanilla shows. The sprite array's
mips now come from a port of MipmapGenerator.generateMipLevels: the
texture's .mcmeta mipmap_strategy (auto: cutout when a pixel is fully
transparent) and alpha_cutoff_bias, solidify or the dark fill on the base,
meanLinear or darkenedAlphaBlend, and scaleAlphaToCoverage keeping every
cutout level's alpha-test coverage at the base level's.

tools/test_mipmap_parity.py runs vanilla's MipmapGenerator and the port on
every static 16x16 block texture and a sample of item textures.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 23:59:47 +02:00
rdbtCVS b48539197a Use the current framebuffer for GUI Scale cycle limits 2026-10-14 22:59:27 +01:00
Ludovic Marie 73a019967e Merge pull request #193 from ludovic111/fix/arrow-pickup-119
Arrows can be picked up (#119)
2026-10-14 23:46:15 +02:00
Ludovic Marie 3bf8387ca8 Merge pull request #189 from ludovic111/fix/arrow-fire-124
Burning arrows: lava, fire, Flame and what they light (#125, #124)
2026-10-14 23:45:54 +02:00
Ludovic Marie d6f729321b Merge pull request #187 from ludovic111/fix/arrow-water-127
Arrows get vanilla's water physics (#127)
2026-10-14 23:45:32 +02:00
Ludovic Marie de5fb47174 Merge pull request #186 from ludovic111/fix/water-fall-damage-180
Water cancels the player's fall damage (#180)
2026-10-14 23:45:20 +02:00
Ludovic MarieandClaude Opus 5.5 3319e6e204 The dragon fight's world fog, and void darkness from each dimension's floor
EnderDragonFight's boss event sets createWorldFog, and while such a bar
shows AtmosphericFogEnvironment.setupFog pulls the fog in (start at most
10, end at most 96, sky and cloud fog ending there): Horizon never did, so
the End stayed clear during the fight. FogInputs gains boss_world_fog,
set while the dragon's bar shows.

FogRenderer's void darkness starts voidDarknessOnsetRange (32) above
level.getMinY(), which is 0 in the Nether and the End; Horizon used the
Overworld's -64 everywhere, so the End's fog never darkened below y 32.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 23:41:22 +02:00
Ludovic MarieandClaude Opus 5.5 ee697cadc6 End crystals from EndCrystalModel, lit, with their base and beams
The crystals were a hand-built mesh without normals (so unshaded), without
the bedrock base and without beams. They now draw the baked
minecraft:end_crystal#main layer under EndCrystalRenderer's transform
(scale 2, down 0.5, not flipped) with EndCrystalModel.setupAnim's poses
(end_crystal::poses: the base shown per showsBottom, the glass raised by
half the bob, outer glass, inner glass and cube turned with rotateBy), the
entity light at their block, and the beam to their target
(submitCrystalBeams from the target's centre up to the crystal) while the
spikes are being summoned back. Crystals placed outside the End draw too.

The entity model harness no longer skips end_crystal: the oracle runs
EndCrystalModel.setupAnim on EndCrystalRenderState and the fixture poses
the layer with end_crystal::poses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 23:40:18 +02:00
Ludovic MarieandClaude Opus 5.5 6ab958a423 Crosshair through the inverting CROSSHAIR pipeline, with the attack indicator
Hud.extractCrosshair draws every crosshair sprite with
RenderPipelines.CROSSHAIR, whose BlendFunction.INVERT (ONE_MINUS_DST_COLOR,
ONE_MINUS_SRC_COLOR, ONE, ZERO) inverts the colour under it; Horizon drew it
alpha-blended white. GuiDraw sprites now carry their pipeline, the HUD batch
records the vertex ranges that invert and the HUD renderer draws them with a
second pipeline.

The attack indicator (crosshair or hotbar, per the Attack Indicator option)
now shows Player.getAttackStrengthScale(0) from the attack strength ticker
instead of a constant full strength, and the full indicator shows at full
strength on a living entity under the crosshair with a weapon slower than
MIN_CROSSHAIR_ATTACK_SPEED.

The HUD harness records every sprite's pipeline on both sides and gives the
crosshair a stand-in crosshairPickEntity (alive or not) and attack delay.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 23:32:36 +02:00
Ludovic MarieandClaude Opus 5.5 087b2526c6 Creepers swell for LAN guests and load ignited from NBT
The host sends Creeper.DATA_SWELL_DIR and DATA_IS_IGNITED with the
creeper's entity data, and a guest runs the client half of Creeper.tick
on them, so the swell and white flash CreeperRenderer draws now show on
the guest too. Creeper.readAdditionalSaveData's ignited lights the fuse
(summon creeper ~ ~ ~ {ignited:1b}).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 23:28:35 +02:00
rdbtCVS e8efd36e5b Integrate world management with Classic button click sounds 2026-10-14 22:20:20 +01:00
rdbtCVS e57a43745a Fix GUI Scale button in classic Video Settings 2026-10-14 22:20:13 +01:00
Ludovic MarieandClaude Opus 5.5 89eaaab2ee Arrows can be picked up (#119)
Players could never pick up arrows: arrows had no pickup rule and no
item, nothing checked a player touching them, and arrows from saves were
loaded into a separate list that never ticked.

Arrows now carry AbstractArrow's pickup rule and pickupItemStack. The
player's bow and crossbow give them the drawn ammo (ProjectileWeaponItem
.useAmmo: creative, Infinity and multishot's extra arrows draw intangible
ammo, so those arrows are CREATIVE_ONLY), setOwner(player) turns
DISALLOWED into ALLOWED, dispensers make them ALLOWED, mobs' stay
DISALLOWED. Each tick the player touches the arrows in its box grown by
(1, 0.5, 1) (Player.aiStep): a stuck arrow that has stopped shaking goes
into the inventory (ALLOWED), or just goes for a creative player
(CREATIVE_ONLY, or ALLOWED with a full inventory), with the item pickup
sound at the arrow.

Saved arrows load as live arrows (life, shake, inGround, inBlockState,
pickup, item, fire) and live arrows are saved, so stuck arrows survive a
reload and despawn on time; the legacy never-ticked arrow list is gone,
and /kill, /tp and /data reach the live arrows.

The arrow harness adds who shot the arrow, intangible ammo and
dispensers' ALLOWED, then touches in flight, while shaking and when stuck
by survival and creative players with empty, partly and fully filled
inventories, against the real setOwner and playerTouch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 23:17:07 +02:00
rdbtCVS 24d8c57932 Make filtered world selection regression deterministic 2026-10-14 22:06:48 +01:00
rdbtCVS f8341dc415 Ignore generated world backups 2026-10-14 22:06:48 +01:00
rdbtCVS aa5305772d Fix backup completion flow and localize world management 2026-10-14 22:06:48 +01:00
rdbtCVS b37db61713 Fix world selector clipping lint on Rust 1.99 2026-10-14 22:06:48 +01:00
rdbtCVS 329334723d Fix classic singleplayer world management UI parity 2026-10-14 22:06:48 +01:00
Ludovic Marie 94aeab9a42 Merge pull request #185 from Online5277/fix/prepare-relative-root
Resolve relative preparation roots before running Java exporters
2026-10-14 23:04:32 +02:00
Ludovic Marie cab02f7e5e Merge pull request #183 from Online5277/fix/rabbit-animation
Drive rabbit hop and idle animations from runtime controls
2026-10-14 23:04:26 +02:00
Ludovic Marie 237e9b9ff3 Merge pull request #181 from Online5277/fix/falling-block-model
Render falling blocks with their actual block models
2026-10-14 23:04:20 +02:00
Ludovic Marie c176b4f8bc Merge pull request #179 from Online5277/fix/dragon-egg-particles
Render dragon egg teleport particles
2026-10-14 23:04:15 +02:00
Ludovic Marie 7d1b2a5777 Merge pull request #176 from rdbtCVS/t3code/fix-screenshot-seed-actions
Fix screenshot, seed, and locate chat click actions
2026-10-14 23:04:09 +02:00
Ludovic Marie b857fc2b72 Merge pull request #182 from rdbtCVS/t3code/fix-classic-ui-menu-sounds
Fix classic menu click sounds to match vanilla
2026-10-14 23:04:03 +02:00
Ludovic Marie 4704e98bda Merge pull request #137 from ludovic111/feat/extras-reconnect
Horizon extras: auto-reconnect (off by default)
2026-10-14 23:00:07 +02:00
Cosmic 2f34bf7b46 Invert crosshair rendering and show attack cooldown indicators 2026-10-14 16:57:51 -04:00
rdbtCVS 42eda649a8 Render Classic menu panorama with vanilla cube-map filtering 2026-10-14 21:54:22 +01:00
Cosmic e7e35fa6e1 Correct resident fluid phase and breathing decisions 2026-10-14 16:53:10 -04:00
Cosmic 792a681497 Seed falling block models from their spawn cell 2026-10-14 16:51:30 -04:00
Cosmic f465e1b6ae Avoid verbatim preparation paths on Windows 2026-10-14 16:49:07 -04:00
Cosmic 07f1c34f96 Merge remote-tracking branch 'origin/main' into fix/dragon-egg-particles
# Conflicts:
#	crates/horizon-client/src/game.rs
2026-10-14 16:49:02 -04:00
Ludovic MarieandClaude Opus 5.5 37043b3dff net harness: the Disconnected screen gained auto-reconnect's retry
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:44:56 +02:00
Ludovic MarieandClaude Opus 5.5 228bdda201 Burning arrows: lava, fire, Flame and what they light (#125, #124)
Arrows never caught fire: nothing ignited them (lava, fire blocks, a
Flame bow's projectile_spawned ignite), so they never set mobs, TNT,
campfires or candles alight. Flame only worked for mobs' bows, as a
5-second ignite on hit.

Arrows now keep Entity.remainingFireTicks: the blocks along their path go
through InsideBlockEffectApplier.StepBasedCollector (fire and soul fire
fireIgnite to 8 s, lava LAVA_IGNITE to 15 s, water EXTINGUISH with the
extinguish sound), the player's bow and mobs' bonus ignite them for 100 s
at spawn, and the fire burns down in flight but not while stuck. A
burning arrow sets its target alight for 5 s, primes TNT, lights
campfires, candles and candle cakes (onProjectileHit, mob_griefing for
mobs' arrows), and blows up a TNT minecart; arrows now hit minecarts like
other entities (VehicleEntity damage). Burning arrows show
FlameFeatureRenderer's fire quads.

The arrow harness adds lava pools, lava/water walls, fire and soul fire,
Flame arrows, and burning/non-burning hits on TNT, campfires, candles and
candle cakes against the real blocks' onProjectileHit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:44:37 +02:00
Ludovic MarieandClaude Opus 5.5 1d93642094 Arrows get vanilla's water physics (#127)
Arrows flew through water with a point check for the 0.6 drag and nothing
else: no bubbles, no splash, no currents, no bubble columns, and the
stuck arrow logic (nudging back by the normalized motion, no falling
out, a 1200-tick age) was not AbstractArrow's.

Port AbstractArrow.tick for arrows (arrows.rs, state in
Projectile::arrow): the in-block check, the water inertia from the last
base tick's wasTouchingWater with four bubbles behind it, crit trails,
lerped rotation, the COLLIDER clip with entity hits first, the effects
of the blocks along the path (bubble columns push, water extinguishes),
air drag and gravity, then the base tick's updateFluidInteraction
(currents while not stuck, splash sound/particles), sticking 0.05 back
along each moving axis with the arrow's own random for the hit sound,
falling out when the block goes, and despawning 1200 ticks after
sticking.

New harness tools/test_arrow_parity.py drives real vanilla Arrow entities
(VanillaArrowOracle) and Horizon's arrows::tick (examples/arrow_probe.rs)
over the resident scene.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:44:31 +02:00
Ludovic MarieandClaude Opus 5.5 645109d427 Keep the scene motion scope text a valid string
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:44:31 +02:00
Ludovic MarieandClaude Opus 5.5 f442374e6d Format the player fluid binding
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:44:31 +02:00
Ludovic MarieandClaude Opus 5.5 60d9bffc86 Water cancels the player's fall damage (#180)
The player's movement treated every fluid as empty: is_in_water was
always false, LivingEntity.checkFallDamage's updateFluidInteraction was
a no-op and Entity.move's fall-reset ray ignored water. A player landing
in water (or a waterlogged block, a bubble column, kelp) still took the
whole fall.

Bind vanilla's Entity.updateFluidInteraction to the player over the
existing horizon-world kernels (EntityFluidInteraction heights, eyes and
currents, entity_fluid_tick, water_splash, fluid_flow): run it in the
base tick and from checkFallDamage, read wasTouchingWater for
isInWater, query the water's (first-query cached) shape in the
FALLDAMAGE_RESETTING ray, halve the fall in lava after the first tick,
and play the splash sound with bubble and splash particles.

The scene motion harness gains water/lava fixtures (fluid_tick plus
scripted falls through the real Entity.move) against the real vanilla
updateFluidInteraction with the #water/#lava tags bound.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:44:31 +02:00
Ludovic MarieandClaude Opus 5.5 ce9c1d3a5c Auto-reconnect: never after account session refusals, retry when session servers are down
Classifies the online-mode login outcomes from #161: invalid session,
banned from playing online, multiplayer disabled, no account signed in
and the server failing to verify the username are never retried;
unreachable session servers (the client's or the server's) are. A retry
of an online-mode server joins with the account held in memory for the
whole run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:41:14 +02:00
Ludovic MarieandClaude Opus 5.5 5797cf2702 Auto-reconnect retries with the session's player name
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:39:51 +02:00
Ludovic MarieandClaude Opus 5.5 43b45fabc7 Horizon extras: auto-reconnect, off by default
On the Disconnected screen after a lost multiplayer connection, a
countdown "Reconnecting in N s" with a Cancel button, then the same
address again. Attempts back off (5, 10, 20, 40, 60 s) and stop after
five; the count resets only after a minute connected. Only failed
connections and the server's shutdown, restart, time-out or full
reasons are retried, never kicks, bans, whitelists, version refusals or
duplicate logins: the network thread now says whether the server gave
the reason (login refusals included).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:39:36 +02:00
Ludovic Marie 21aab8b164 Merge pull request #136 from ludovic111/feat/extras-minimap
Horizon extras: minimap (off by default)
2026-10-14 22:38:32 +02:00
Ludovic Marie 35120b0e91 Merge pull request #135 from ludovic111/feat/extras-core
Horizon extras: zoom, FPS counter, keystrokes and the Extras page (off by default)
2026-10-14 22:38:01 +02:00
Ludovic Marie 294010913b Merge pull request #143 from ludovic111/ci/release-train-nightly
Release train 4/4: nightly parity audit with parity-regression issues
2026-10-14 22:28:57 +02:00
Ludovic Marie ae460db2e8 Merge pull request #141 from ludovic111/ci/release-train-launcher
Release train 3/4: automatic launcher releases, version built in from the tag
2026-10-14 22:28:36 +02:00
Ludovic Marie af6bb6bc8c Merge pull request #138 from ludovic111/ci/release-train-games
Release train 2/4: automatic game releases
2026-10-14 22:28:13 +02:00
Cosmic 7566a4753c Merge PR 186 fluid foundation and preserve swimming and fire behavior 2026-10-14 16:28:07 -04:00
Ludovic Marie 12e8d5b71e Merge pull request #133 from ludovic111/ci/release-train
Release train 1/4: cached verify, and a parity job on the Mac mini for what a PR can affect
2026-10-14 22:27:33 +02:00
rdbtCVS c166ea57d1 fix: match vanilla screenshot and seed link behavior 2026-10-14 21:22:19 +01:00
Ludovic MarieandClaude Opus 5.5 beac11eaa5 Nightly parity audit on the Mac mini, with an issue per regressed harness
nightly.yml runs every harness from scratch on main at 03:00 Paris time on the Mac mini's runner, after
preparing the resources again if the preparer changed. tools/ci/parity_issues.py compares the results with
the previous audit: a harness that passed and now fails gets one issue labelled parity-regression (an open
one is commented on), and an issue closes when its harness passes again. The bugs session picks them up.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:18:31 +02:00
Ludovic MarieandClaude Opus 5.5 98ca844f07 launcher: the Microsoft sign-in's User-Agent says the built-in version too
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:18:31 +02:00
Cosmic e57c32efb8 Merge current main and preserve axolotl damage behavior 2026-10-14 16:18:08 -04:00
Ludovic MarieandClaude Opus 5.5 76f3e7c2a8 launcher.yml: GPUI's runtime shaders on a Mac runner without the Metal toolchain (the Mac mini)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:46 +02:00
Ludovic MarieandClaude Opus 5.5 fa61f262c3 launcher: automatic releases, the version built in from the tag
launcher.yml releases the launcher by itself: after a push to main that changes launcher/,
crates/horizon-prepare or crates/horizon-theme, hourly, and by hand, with the game's rules
(tools/release_train.py decide --kind launcher: player-facing pull requests and a 3-hour cooldown,
release-now, skip-release, RELEASES_PAUSED). launcher-vX.Y.Z is the next patch, or the next minor after a
pull request labelled feature. Linux on ubuntu-22.04, Windows on GitHub, macOS on the Mac mini's runner;
published with --latest=false.

No version-bump commits: VERSION reads HORIZON_LAUNCHER_VERSION with option_env!, falling back to
Cargo.toml's, and --version, the User-Agent and the self-update comparison use it; each build checks
--version says the release's version.

With several game releases a day, the newest launcher release soon falls out of the newest 100 (launcher)
or 30 (website) releases: both now look the newest launcher-v tags up one by one when the list has none.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:46 +02:00
Ludovic MarieandClaude Opus 5.5 6d759dc7bb release_train: name a feature split over several pull requests once in the title; no leading Fix
Today's main would have been titled "Controllers, controllers, controllers and 17 more changes".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 9e016b6235 vanilla-data.sh: clone the sounds into each preparation instead of linking them
Vanilla's resource packs refuse symbolic links inside a pack: with linked sounds the vanilla sound oracles found
no sound files while Rust did (sound_event, sound_engine on #133's parity run).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 fb256809a7 release: the macOS smoke run draws 1500 frames; 300 end before the world has loaded
Checked on the Mac mini: 1500 offscreen frames in 12 s, 81 chunks generated, 4153 sections meshed, a player.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 cfad57d0b1 Mac runner: the game's sounds in each preparation; save_roundtrip Linux-only
The first audit on the Mac mini failed 7 audio harnesses (no sounds in the prepared resources: the Mac mini has
no official launcher for horizon-prepare sounds to copy from) and save_roundtrip (it needs vscreen). The
sounds depend only on the Minecraft version: kept once in shared-local/sounds/<version>/ and linked into each
preparation.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 e994c8ab95 release: the macOS smoke run opens a world (from a scratch folder) and checks it drew one
Without --world the client stays on the title screen: 300 frames and no chunks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 7b82ee8c16 Two Horizon runners on the Mac mini: one preparation at a time; docs
A second runner (ludovics-mac-mini-2, same labels) shares the first one's vanilla data through a link, so
vanilla-data.sh prepares under a lock; a 30-minute audit no longer holds a release's macOS build back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 7adfe44f6c launcher: rustfmt the rollback test
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 f6191fe8ee parity_hosts.json: linux_only, empty: the four harnesses that once differed on macOS pass there
options, chunk_generation, world_border_render and mob_ai all pass on the Mac mini (7.3 min).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 8aacb48798 release: automatic game releases after main's green checks
release.yml now releases the game by itself: after every green checks run of a push to main, every hour
(a release the cooldown held goes out without another merge) and by hand. tools/release_train.py decides
from the pull requests merged since the last published game release: a release when one changed what
players run and the last release is 3 hours old, at once for a pull request labelled release-now;
skip-release pull requests don't count. RELEASES_PAUSED=1 stops it. Tags vYYYY.MM.DD, then .1, .2 the
same UTC day.

Linux (ubuntu-22.04) and Windows build on GitHub with Cargo caches, macOS on the Mac mini's runner
(MAC_RUNNER=macos-latest sends it to GitHub). Each builds horizon-client, horizon-ctl and horizon-prepare
(all three named: --bin selects only the named binaries), checks all three exist, checks their libraries,
starts each one, packages with xtask and archives; the Mac also runs the game offscreen for 300 frames on
a new world with resources prepared from its own Minecraft. The notes: New (label feature), Fixed (the
rest), Known issues (docs/known-issues.md). A hand-started run off main, or with dry_run, builds
everything and writes the notes but publishes nothing.

docs/release-flow.md describes the flow, the labels, pausing and rolling back; the launcher gets a test
that a release turned back into a draft is never offered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 989f843b1c vanilla-data.sh: keep everything horizon-prepare writes per preparer version, beside the shared data
The first parity run kept only .local/horizon-client per preparer version; the exporters' outputs beside it
stayed in the checkout, and the dedicated server, which finds registries.json at
<resources>/../../datagen, didn't find it next to the prepared folder (world_spawn failed).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 874d111d60 checks: cached verify, and a parity job on the Mac mini for the harnesses a PR can affect
verify keeps its dependencies and workspace build in a cache saved by main's runs (Swatinem/rust-cache).
The new parity job runs on the Mac mini's self-hosted runner (label horizon-game), which holds the
maintainer's own Minecraft files: tools/ci/vanilla-data.sh links .local/ to the runner's copy and prepares
the resources with the pull request's own horizon-prepare, once per preparer version; then
tools/parity.py --changed <base> runs only the harnesses whose traced dependencies changed since the merge
base and that have no pass for their current inputs. A fork's pull request runs it only when a maintainer
adds run-parity, once per label, on the commit it had then.

parity.py: --changed REF, and linux_only in tools/parity_hosts.json for harnesses that differ on other
platforms for a reason that is not a Horizon bug (skipped there with the reason, unless named).

docs/release-flow.md starts with the pull request checks and merging.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:17:20 +02:00
Ludovic MarieandClaude Opus 5.5 03309dee95 Format the player fluid binding
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:13:34 +02:00
Ludovic Marie 7338f55b9a Merge pull request #164 from ludovic111/feat/msa-launcher
Microsoft account (c): launcher sign-in, keychain, session handoff to the game
2026-10-14 22:12:11 +02:00
Ludovic Marie 4559a92942 Merge pull request #161 from ludovic111/feat/msa-online-mode
Microsoft account (a): join online-mode servers (session join, RSA, AES/CFB8), skins over HTTPS
2026-10-14 22:10:58 +02:00
Ludovic MarieandClaude Opus 5.5 e9da898f97 Water cancels the player's fall damage (#180)
The player's movement treated every fluid as empty: is_in_water was
always false, LivingEntity.checkFallDamage's updateFluidInteraction was
a no-op and Entity.move's fall-reset ray ignored water. A player landing
in water (or a waterlogged block, a bubble column, kelp) still took the
whole fall.

Bind vanilla's Entity.updateFluidInteraction to the player over the
existing horizon-world kernels (EntityFluidInteraction heights, eyes and
currents, entity_fluid_tick, water_splash, fluid_flow): run it in the
base tick and from checkFallDamage, read wasTouchingWater for
isInWater, query the water's (first-query cached) shape in the
FALLDAMAGE_RESETTING ray, halve the fall in lava after the first tick,
and play the splash sound with bubble and splash particles.

The scene motion harness gains water/lava fixtures (fluid_tick plus
scripted falls through the real Entity.move) against the real vanilla
updateFluidInteraction with the #water/#lava tags bound.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 22:07:48 +02:00
Cosmic 6c4ad9d825 Resolve preparation root before changing exporter directories 2026-10-14 16:06:18 -04:00
Ludovic Marie 70fd5f5c77 Merge pull request #178 from Online5277/fix/reuse-imported-minecraft
Reuse verified Minecraft imports when preparing new versions
2026-10-14 22:04:25 +02:00
Cosmic 88b9a82688 Select baby rabbit model for summoned negative ages 2026-10-14 16:01:30 -04:00
Ludovic Marie 9ae39fac28 Merge pull request #170 from rdbtCVS/fix/lan-host-tab-list
Fix tab list for singleplayer LAN hosts
2026-10-14 21:59:55 +02:00
Ludovic Marie f04d47e14d Merge pull request #165 from rdbtCVS/t3code/fix-inventory-banner-rendering
Fix inventory banner face depth ordering
2026-10-14 21:59:49 +02:00
Cosmic af8700bd20 Drive rabbit hop and idle animations from runtime controls 2026-10-14 15:46:01 -04:00
rdbtCVS d456dadafa Match vanilla inventory effect duration text color 2026-10-14 20:45:33 +01:00
Ludovic Marie d299d1f07a Merge pull request #162 from rdbtCVS/t3code/fix-classic-ui-background
Fix missing background in Classic menus
2026-10-14 21:43:28 +02:00
Ludovic Marie 7156602a7f Merge pull request #171 from rdbtCVS/t3code/disable-lan-on-leave
Fix LAN shutdown when leaving a singleplayer world
2026-10-14 21:43:23 +02:00
Ludovic Marie 1f8a2b28d6 Merge pull request #172 from rdbtCVS/t3code/fix-lan-world-menu-pause
Fix LAN worlds pausing when the host opens menus
2026-10-14 21:43:16 +02:00
Cosmic 8caee51897 Regenerate preparation metadata when reusing imports 2026-10-14 15:37:32 -04:00
rdbtCVS d69a380851 Fix classic menu click sounds to match vanilla 2026-10-14 20:35:30 +01:00
rdbtCVS 2fbbe1c5e2 Fix status effect icons and render inventory effect panels 2026-10-14 20:35:18 +01:00
rdbtCVS 79ab688bda Fix banner rendering test lint on Rust 1.99 2026-10-14 20:34:26 +01:00
rdbtCVS 322a87cf93 Fix Clippy warnings in LAN tab list regression tests 2026-10-14 20:34:25 +01:00
Cosmic 517e275c79 Render falling blocks with their baked models 2026-10-14 15:33:44 -04:00
Ludovic Marie cb3b5abf6b Merge pull request #175 from ludovic111/fix/maces-105
Maces: smash attacks, Density, Breach, Wind Burst
2026-10-14 21:33:02 +02:00
Cosmic 1df16591b4 fix(client): render dragon egg teleport particles 2026-10-14 15:24:41 -04:00
Ludovic MarieandClaude Opus 5.5 56aae0e902 Maces smash: fall damage bonus, Density, Breach, Wind Burst, knockback
A mace hit after falling more than 1.5 blocks is now a smash attack
(MaceItem): the fall-based damage bonus plus Density, mace_smash damage,
the stopped fall with its damage waived, the ground/air smash sounds, the
dust pillars (level event 2013) and the knockback of the creatures around
the target, then the fall reset and landing particles. Breach thins the
target's armor (CombatRules.getDamageAfterAbsorb), Wind Burst bursts at
the player's feet (ExplodeEffect, trigger), and weapons wear by their
weapon component and award the used statistic.

Vanilla details matched on the way: the hurt knockback is 0.4F and reads
the live knockback-resistance attribute, explosion exposure uses the
exact COLLIDER clip, a burst posts the explode game event and ends the
impulse grace unless it is a wind charge's, visible armor stands feel
bursts that affect block-like entities, attack sounds play at the player.

tools/test_mace_parity.py compares the hit with VanillaDispenserOracle's
real MaceItem / hurtServer / post-attack effects: 3000/3000.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 21:23:57 +02:00
Ludovic Marie e15c879fe7 Merge pull request #169 from ludovic111/fix/bed-explosions-101
Beds and straw beds blow up when used in the Nether and the End
2026-10-14 21:23:09 +02:00
Ludovic Marie 11b7038b39 Merge pull request #163 from ludovic111/fix/respawn-anchors-99
Respawn anchors charge, set the respawn point, explode outside the Nether
2026-10-14 21:17:29 +02:00
Cosmic 20988e810e fix(prepare): reuse verified imports from installed versions 2026-10-14 15:14:10 -04:00
rdbtCVS 9f07f64bff fix: unify locate teleport suggestion links 2026-10-14 20:13:59 +01:00
rdbtCVS d25d6184c2 fix: enable screenshot and seed chat click actions 2026-10-14 20:04:08 +01:00
Cosmic ba3f4003cd Merge current main and preserve PR 59 review fixes 2026-10-14 14:56:18 -04:00
rdbtCVS 0ed50ae6ae Fix LAN worlds pausing when the host opens menus 2026-10-14 19:53:45 +01:00
rdbtCVS 1b1e129112 Fix LAN shutdown when leaving a singleplayer world 2026-10-14 19:51:23 +01:00
rdbtCVS 72074eb080 Fix LAN host tab list to include connected guests 2026-10-14 19:50:21 +01:00
Cosmic 027ac3cdf1 Address final axolotl bucket and fire review corrections 2026-10-14 14:39:49 -04:00
Ludovic MarieandClaude Opus 5.5 190f89b214 Beds and straw beds blow up when used in the Nether and the End
A right click on a bed in the Nether or the End tried to sleep in it (and
set the respawn point) as in the Overworld.

AbstractBedBlock.useWithoutItem reads the dimension's bed rule, which in
the Nether and the End is destroy_on_use: BedBlock.destroyOnUse removes the
head, then the foot behind it if it is still the bed, and explodes at the
head (power 5, fire, BLOCK interaction, the bad_respawn_point damage source:
"Intentional Game Design"); StrawBedBlock.destroyBed plays
block.straw_bed.break_leave and removes it.

tools/test_use_item_on_parity.py clicks beds and straw beds (head or foot,
whole or missing their other half, among blocks) in the Nether and the End,
through vanilla's real explosion; the oracle gains the End.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 20:24:55 +02:00
Ludovic MarieandClaude Opus 5.5 1596210bba Respawn anchors charge, set the respawn point, explode outside the Nether
A right click with glowstone on a respawn anchor did nothing and a charged
anchor never became the respawn point: the block reported the use and the
game dropped it.

RespawnAnchorBlock is now played out (game/respawn_anchor.rs): useItemOn
charges with glowstone (the block change, block.respawn_anchor.charge, the
used item and the charge_respawn_anchor criterion), passing to the off
hand's glowstone; useWithoutItem sets the respawn point in the Nether
(block.minecraft.set_spawn once, respawn_anchor.set_spawn) and elsewhere
explodes: the anchor goes, then a power 5 fiery BLOCK explosion with the
bad_respawn_point damage source whose centre resists like water when water
would flow into it. Dying with an anchor as the respawn point travels to
its dimension and respawns at findStandUpPosition (DismountHelper's safe and
unsafe passes, facing the anchor with calculateLookAtYaw), using a charge
and playing respawn_anchor.deplete; a missing or empty anchor falls back to
the world spawn with block.minecraft.spawn.not_valid. The point is saved in
the player's respawn compound with its dimension; a bed or /spawnpoint
replaces it. Dying in the Nether without one now respawns in the Overworld.

Explosions gained what these need: a damage type, a block resistance
override, BaseFireBlock.getState for their fire, the explosion radius in the
block loot context (survives_explosion and explosion_decay drawing from the
table's random sequence) and TntBlock.wasExploded without a game event.

tools/test_use_item_on_parity.py now charges, uses and blows up anchors in
both dimensions through vanilla's real ServerExplosion on the stand-in
level, and respawns at anchors among blocks through
ServerPlayer.findRespawnAndUseSpawnBlock.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 20:18:49 +02:00
rdbtCVS aab88753b6 Keep title panorama optional during full resource preparation 2026-10-14 19:15:16 +01:00
rdbtCVS 8987369b07 Fix inventory banner face depth ordering 2026-10-14 19:09:42 +01:00
Ludovic MarieandClaude Opus 5.5 d4e0dc4917 Settings subtitle mentions accounts
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 20:07:47 +02:00
Ludovic MarieandClaude Opus 5.5 6bed9b92ca launcher.yml: build in HORIZON_MSA_CLIENT_ID from the repository variable
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 20:07:47 +02:00
Ludovic MarieandClaude Opus 5.5 324eb2836c Launcher README: Microsoft accounts
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 20:07:47 +02:00
Ludovic MarieandClaude Opus 5.5 82bee83dc5 Launcher: Microsoft account sign-in, keychain and the game's session
Device-code OAuth, Xbox Live, XSTS, Minecraft login, ownership and profile;
secrets in the OS keychain (oo7 on Linux, keyring on macOS/Windows), accounts.json
without tokens; Settings account rows, 'Playing as' on the Play page; CLI
'account' and MCP account tools; the game gets a 0600 session file it deletes.
Client ID is configuration (HORIZON_MSA_CLIENT_ID), empty = not configured.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 20:07:47 +02:00
Ludovic MarieandClaude Opus 5.5 f38e8cc393 Skins over HTTPS: fetch textures with ureq (rustls)
Players' skins on online servers come from https://textures.minecraft.net;
the old plain-HTTP fetch left everyone with their default skin.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:57:34 +02:00
Ludovic MarieandClaude Opus 5.5 0acd686720 rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:55:57 +02:00
Ludovic MarieandClaude Opus 5.5 6957d74742 docs: Minecraft login endpoint
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:55:57 +02:00
Ludovic MarieandClaude Opus 5.5 ac97e9c0b9 Harness: online-mode login against vanilla's server and a mock session service
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:55:57 +02:00
Ludovic MarieandClaude Opus 5.5 89b2ca64a9 Join online-mode servers with the launcher's account
Read the signed-in account from a session file (--session-file, deleted
on read), answer ClientboundHelloPacket like vanilla: shared secret, server
hash, session join through the services discovery document (authlib's
error mapping and messages), RSA-wrapped key packet, AES/CFB8 both ways.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:55:57 +02:00
Ludovic MarieandClaude Opus 5.5 c8629f3378 Protocol: RSA public keys and PKCS#1 encryption, server hash, secrets
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:55:57 +02:00
Ludovic MarieandClaude Opus 5.5 c6634830d3 WIP: Microsoft account design note and RSA (not wired yet)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:55:57 +02:00
Ludovic Marie f83bc0ab70 Merge pull request #146 from ludovic111/fix/spawners-95
Monster spawners spawn, spin their mob and take spawn eggs
2026-10-14 19:54:54 +02:00
rdbtCVS eebf5621bf Fix classic menu panorama resource preparation 2026-10-14 18:54:51 +01:00
Ludovic Marie d1517fa79b Merge pull request #158 from Online5277/fix/arrow-hit-sound
Play normal arrow impact audio for player hits
2026-10-14 19:54:48 +02:00
Ludovic Marie b7f14763a7 Merge pull request #149 from ludovic111/feat/controllers-rumble
Controllers: rumble
2026-10-14 19:43:33 +02:00
Ludovic MarieandClaude Opus 5.5 663f61c8c3 Horizon extras: a minimap, off by default
A corner map of the loaded chunks in vanilla's map colours with the map
item's height and water shading: square or round, three sizes, four
zooms, north up or turning with the player, with the player arrow. In
the Nether, underground and under a roof it maps the floor at the
player's height and cuts walls. Each loaded chunk keeps a 16x16 tile,
filled nearest first within 0.3 ms a frame and rescanned after block
changes; the image is recomposed only when the view or a tile changed
and uploaded into its own atlas slot. Nothing runs while it is off.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:41:01 +02:00
Ludovic MarieandClaude Opus 5.5 365d35f53a Extras: the zoom key zooms only while playing and never takes keys
The zoom key went to the zoom on every screen, so with zoom on, Z could
not be typed in screens with text fields that share the game's key
handler. Now it zooms only while playing with no sign or book open, lets
go when a screen opens, and always passes the key on, like a vanilla key
mapping. A vanilla mapping bound to the same key still acts; the Extras
page marks the zoom key "Also bound" and names it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:41:01 +02:00
Ludovic MarieandClaude Opus 5.5 a08577e301 Extras: horizon-ctl key and mouse reach the zoom key and keystrokes
Agents press keys and buttons through the control socket, which skipped
the keyboard and mouse hooks; under control the window may also lack
focus without pausing, so the zoom no longer lets go then.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:39:38 +02:00
Ludovic MarieandClaude Opus 5.5 c4b0e8efe0 Horizon extras: zoom, FPS counter and keystroke overlay, off by default
An Extras section in Horizon's Options holds optional additions saved in
horizon-extras.txt beside options.txt. Zoom divides the field-of-view
target vanilla's Camera.tickFov eases toward (the spyglass path), with a
wheel-adjustable level and lower mouse sensitivity; scoping keeps the
spyglass view. The FPS counter (with minimum and 1% low) and the keystroke
overlay (WASD, space, mouse buttons with clicks per second) draw in the
HUD layer, hidden with F1. docs/extras.md describes all the extras.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:39:20 +02:00
Ludovic Marie b7fc86279c Merge pull request #151 from rdbtCVS/t3code/fix-creative-fall-damage-sound
Fix fall damage sounds in creative mode
2026-10-14 19:37:28 +02:00
Ludovic MarieandClaude Opus 5.5 40fce014f1 Controllers: hurt rumble only within one player's life
The health baseline (HealthWatch) is forgotten when there is no player,
on the title screen, and whenever a new player entity takes over (spawn
and respawn, joining a server, End and Nether dimension changes), so
arriving with less health than the last player had isn't damage.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:37:04 +02:00
Ludovic MarieandClaude Opus 5.5 ccdc4fe682 Controllers: rumble
Short, light pulses through gilrs force feedback, on by default
(Vibration in horizon-controller.txt): damage taken (stronger with the
damage, from any source, here or on a server), a block broken, an
explosion nearby (fading over four times its radius), a totem of undying.
Only the pad that is playing vibrates; macOS has no force feedback in
gilrs and stays still. pad status reports the last vibration asked for.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:36:52 +02:00
Ludovic Marie b61455e562 Merge pull request #145 from ludovic111/feat/controllers-options
Controllers: Controller options, button binds and glyphs
2026-10-14 19:36:29 +02:00
Ludovic Marie d8ad1dad7a Merge pull request #156 from rdbtCVS/t3code/fix-classic-ui-scroll-limit
Fix classic options scroll limits
2026-10-14 19:34:45 +02:00
Ludovic Marie 3dcbd2228b Merge pull request #154 from rdbtCVS/t3code/fix-world-options-menu
Fix World Options pause and Escape behavior
2026-10-14 19:34:26 +02:00
Ludovic Marie 1be820b091 Merge pull request #150 from Online5277/fix/startup-settings
Apply saved audio and GUI settings at startup
2026-10-14 19:34:17 +02:00
Ludovic Marie 97a65cd5aa Merge pull request #155 from rdbtCVS/fix/keybind-category-translations
Fix keybind category translations
2026-10-14 19:34:10 +02:00
Ludovic Marie 61e5b70fde Merge pull request #153 from ludovic111/gitignore-run-files
Ignore the files the client writes to the repo root
2026-10-14 19:34:03 +02:00
Ludovic Marie 4ac53c0867 Merge pull request #152 from rdbtCVS/fix/options-held-input
Fix stuck keys when opening Options
2026-10-14 19:33:42 +02:00
Ludovic Marie afce3f7aa1 Merge pull request #56 from Online5277/fix/creative-inventory-toggle-drop
Fix creative inventory tab and toggle-sprint item drops
2026-10-14 19:33:37 +02:00
Ludovic MarieandClaude Opus 5.5 79e04e22d6 Monster spawners spawn, spin their mob and take spawn eggs
Spawners were never ticked: Horizon kept their block entity as loaded NBT,
and a freshly generated dungeon or mineshaft spawner lost even that, so no
mob ever came out, nothing turned inside and a spawn egg used on one spawned
a mob next to it instead of setting the spawner's.

The spawner is now a modelled block entity (mobs::spawner): BaseSpawner's
load and save with SpawnData's codec (normalised ids, custom spawn rules,
weighted potentials, the next data shared with the one potential when the
potentials are missing), serverTick (the player range, spawner_blocks_work,
the delay, getOrCreateNextSpawnData, Pos, the spawn box against blocks and
solid shulkers, custom light rules and peaceful, SpawnPlacements, the nearby
cap, the yaw, checkSpawnRules and checkSpawnObstruction, finalizeSpawn for
an id alone, the 2004 burst, entity_place and the spawn poof) and delay with
its block event, in the level random's order. The client copy keeps its own
delay for the spin and puffs smoke and flames; SpawnerRenderer draws the
next mob small and turning. SpawnEggItem.useOn on a spawner sets its mob
(setEntityId), tells the player when spawner_blocks_work is off and fails in
peaceful for monsters. Breaking one pops 15 + nextInt(15) + nextInt(15)
experience whatever the tool. LAN guests get the update tag, the block event
and the entity event.

tools/test_spawner_parity.py ticks vanilla's SpawnerBlockEntity on the
natural spawn oracle's level against mobs::spawner on the same worlds (6,000
cases); tools/test_use_item_on_parity.py now covers spawn eggs on spawners.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:33:25 +02:00
Cosmic db1a895c05 fix(client): play the arrow impact sound for player hits 2026-10-14 13:22:12 -04:00
Ludovic Marie b5690ad295 Merge pull request #128 from ludovic111/perf/terrain-vertex-32
Terrain gets its own 28-byte vertex without a normal (was 36)
2026-10-14 19:20:17 +02:00
Ludovic MarieandClaude Opus 5.5 32bb3612fb Controllers: × for the PlayStation cross (the game fonts lack ✕)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:12:24 +02:00
Ludovic Marie e8ca05af19 Controllers: deadzone percentages rounded 2026-10-14 19:12:24 +02:00
Ludovic MarieandClaude Opus 5.5 ce85fd98ed Controllers: Controller options, button binds and glyphs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:12:24 +02:00
Ludovic Marie 2470ba9b83 Merge pull request #129 from ludovic111/feat/controllers-menus
Controllers: menus, screens and inventories (virtual cursor)
2026-10-14 19:12:05 +02:00
rdbtCVS 318988d767 Fix classic options scrolling at list boundaries 2026-10-14 18:10:11 +01:00
rdbtCVS 25d1d3cc07 Fix keybind category translations 2026-10-14 18:08:06 +01:00
Ludovic MarieandClaude Opus 5.5 840e8ad4a8 Give terrain its own 28-byte vertex without a normal
Since #52 the shared vertex carried an RGBA8_SNORM face normal for
entity.wgsl's directional light, so every section vertex grew from 32 to
36 bytes although vs_terrain never reads it. Vanilla's terrain uses
DefaultVertexFormat.BLOCK (position, colour, UV0, UV2: 28 bytes): the face
shade is baked into the colour by ModelBlockRenderer and terrain.vsh only
multiplies it by the lightmap.

Sections now mesh into TerrainVertex: position, UV, the sprite layer as a
u16 (bit 15 marks opaque leaves), the two light bytes as a u16 and the
RGBA8 colour, 28 bytes. Every value the shader reads is unchanged; entity
vertices keep their normal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:07:01 +02:00
Ludovic MarieandClaude Opus 5.5 ea93297579 Report the section arena and device memory in the control status
The status reply's renderer block gains the section vertex arena's buffer
bytes, the bytes resident sections use in it, and the backend allocator's
allocated/reserved device memory (Vulkan), to measure terrain memory.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:06:49 +02:00
Ludovic Marie 51dc44f64f Merge pull request #121 from ludovic111/fix/creeper-white-flash
OverlayTexture texels from one tested table; creepers flash white while swelling
2026-10-14 19:06:16 +02:00
rdbtCVS 90115e5574 Fix World Options pause and Escape behavior 2026-10-14 18:05:30 +01:00
Ludovic MarieandClaude Opus 5.5 5cf5b6bfd2 Ignore the settings and files the client writes to the repo root
options.txt, horizon.txt, horizon-graphics.txt and the rest showed up as
untracked after running the game from the checkout.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 19:05:30 +02:00
Ludovic Marie 02104eab29 Merge pull request #148 from ludovic111/release/launcher-0.1.5
Launcher 0.1.5
2026-10-14 19:04:55 +02:00
rdbtCVS 28b01e9eca Fix fall damage sounds in creative mode 2026-10-14 18:02:51 +01:00
rdbtCVS b6df5a91a9 Fix held keys getting stuck when opening Options 2026-10-14 18:02:35 +01:00
Ludovic MarieandClaude Opus 5.5 2edc69ef99 Launcher 0.1.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:59:23 +02:00
Cosmic 0dd8ed546a fix(client): apply saved settings before the title screen 2026-10-14 12:59:05 -04:00
Ludovic Marie 52975ad988 Merge pull request #132 from ludovic111/fix/release-yml-prepare
release.yml: build horizon-prepare's binary too
2026-10-14 18:46:54 +02:00
Ludovic MarieandClaude Opus 5.5 79ea17ffc5 Controllers: classic sliders are focus targets; the D-pad nudges with A held
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:42:19 +02:00
Ludovic MarieandClaude Opus 5.5 b58e96436a Controllers: Horizon-style menus' controls are focus targets too
Ui::interact records every enabled control (sidebar items, switches,
sliders, segments) as a D-pad focus target, apart from the labelled
button list horizon-ctl clicks by name.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:40:31 +02:00
Ludovic MarieandClaude Opus 5.5 cbf4b53b0c Controllers: menus, screens and inventories with a virtual cursor
The left stick moves a cursor drawn over the screen, the D-pad steps
between slots and buttons (focus_step), and A / X / the right stick send
the window the pointer events a mouse would, so every screen keeps its
own mouse behaviour (drags, sliders, scrollbars). Y quick-moves in
inventories, LB/RB switch creative tabs, B and Start go back. Focus lands
on the first button, or the held hotbar slot, when a menu opens while the
pad is in use; moving the real mouse hands the pointer back.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:40:31 +02:00
Ludovic Marie e145a32322 Merge pull request #120 from ludovic111/feat/controllers-input
Controllers: design note, gilrs input layer and gameplay
2026-10-14 18:40:10 +02:00
Ludovic MarieandClaude Opus 5.5 a28667923a release.yml: build horizon-prepare's binary too
With --bin flags, cargo builds only the named binaries of every selected
package, so -p horizon-prepare built nothing and the import checks failed on
target/release/horizon-prepare (every run since #92).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:38:13 +02:00
Cosmic f1e0b093a5 Merge newer main while retaining consumable guard and review fixes 2026-10-14 12:27:15 -04:00
Ludovic MarieandClaude Opus 5.5 e70b5e2882 Controllers: a pad press lasts at least one game tick
Vanilla samples keys once per tick, so a stick click shorter than 50 ms
(sprint) could come and go between two ticks and be lost: its release
waits for the next tick.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:25:33 +02:00
Ludovic Marie d1d727f838 Merge pull request #123 from ludovic111/feat/sounds-rust
horizon-prepare sounds: sound copy in Rust, run by the launcher (no Python for players)
2026-10-14 18:25:04 +02:00
Ludovic Marie 98c71567e3 Merge pull request #126 from ludovic111/feat/package-rust
xtask package: the release folder in Rust, replacing packaging/package.sh
2026-10-14 18:24:27 +02:00
Cosmic e9e4ef96a7 Merge main and address PR59 bucket, fire, mipmap and AI review 2026-10-14 12:19:54 -04:00
Ludovic MarieandClaude Opus 5.5 842d11efc4 xtask package: the release folder in Rust, replacing packaging/package.sh
`cargo run -p xtask -- package BINARY OUTDIR` does what package.sh did:
OUTDIR wiped and recreated, the `git archive HEAD tools
mods/horizon/src/test/java crates/horizon-prepare research-lock.json LICENSE`
tree extracted (the tar read in Rust, executables kept executable), the client,
horizon-ctl and horizon-prepare copied (.exe beside an .exe, the same error when
one is missing) and PLAY.txt. release.yml calls it; package.sh is gone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:16:20 +02:00
Ludovic Marie 425021dda5 Merge pull request #122 from ludovic111/fix/nether-portals-94
Nether portals: vanilla timing and linking; items and mobs travel
2026-10-14 18:15:59 +02:00
Ludovic MarieandClaude Opus 5.5 b7330ac0cc Controllers: gilrs input layer, in-game movement, camera, actions and hotbar
Vanilla 26.3 has no gamepad input, so this is Horizon's own, on Bedrock's
default layout (docs/controllers.md). gilrs reads the pads; the pure part
(bindings, radial deadzones, the look curve, button edges, the
horizon-controller.txt settings file) is in gamepad.rs with unit tests.

Buttons act as the vanilla key mapping they're bound to, through the same
path a rebound keyboard key takes (the keyboard's post-rebinding handling
moves into Game::mapped_key). The left stick is an analog move vector,
the right stick turns the view per frame, LB/RB step the hotbar, B and
Start leave screens and A respawns. horizon-ctl pad injects a virtual pad.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:15:40 +02:00
Cosmic e905c10400 Address creative inventory review on current main 2026-10-14 12:11:53 -04:00
Ludovic MarieandClaude Opus 5.5 8355a6ff14 horizon-prepare sounds: the sound copy in Rust, run by the launcher
tools/fetch_sounds.py (and the lab.py functions it used) becomes
`horizon-prepare sounds` (horizon_prepare::sounds): the pinned asset index,
sounds.json and every .ogg from the player's own launcher install, each SHA-1
checked, into .local/horizon-client/<version>. The launcher runs it as part of
Prepare (in-process, the version's own binary when its sources differ and it
knows the subcommand, in-process for older versions), and a launcher install
without the assets only logs that the game will be silent. Player docs no
longer mention Python for sound.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:10:34 +02:00
Ludovic MarieandClaude Opus 5.5 74821bf188 Overlay texels from OverlayTexture, and the creeper's white flash
The hurt red and the white row's alphas come from overlay.rs, which
reproduces OverlayTexture's texels (checked against values printed by
the 26.3 JVM) and is prepended to entity.wgsl; a test parses and
validates the composed shader with naga.

Swelling creepers flash white as CreeperRenderer.getWhiteOverlayProgress
says (the white row's column, red winning while hurt; layers keep the
red only), and CreeperRenderer.scale's wobble uses the unclamped
swelling as vanilla does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:07:31 +02:00
Ludovic MarieandClaude Opus 5.5 0818190ee4 docs: controller support design note
Vanilla 26.3 has no gamepad code; Horizon's own design follows Bedrock's
default controller layout. Mapping, menus, glyphs, options file, rumble,
Steam Deck and the PR plan.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:06:50 +02:00
Cosmic 767ed4cb47 Use physical Ctrl state for stack dropping, not toggle sprint 2026-10-14 12:06:41 -04:00
Ludovic MarieandClaude Opus 5.5 1f06156649 Nether portals: vanilla timing, linking, and items and mobs travel
The player's portal timer reset to zero on any tick outside a portal and
came back from a trip with a 300-tick cooldown that only ran down outside
portals; the overworld exit search covered 32 blocks of loaded chunks;
nothing but the player could use a portal.

The player now follows Entity.setAsInsidePortal / handlePortal with
PortalProcessor (decay by 4, the cooldown of 10 that a portal keeps
resetting, players_nether_portal_default/creative_delay), and
NetherPortalBlock.getPortalDestination through the new
horizon_world::level::portal_travel: PortalForcer.findClosestPortalPosition
(16 / 128 blocks, loaded and saved chunks), createPortal,
BlockUtil.getLargestRectangleAround, PortalShape.getRelativePosition and
findCollisionFreePosition, with the turned yaw and motion and
block.portal.travel. LocalPlayer.handlePortalTransitionEffect closes
screens and plays block.portal.trigger. Items and mobs go through after one
tick with a 300-tick cooldown and wait as saved entities until their
dimension loads around the exit.

tools/test_nether_portal_parity.py compares the destination with vanilla's
getPortalDestination over two headless levels; the scene motion harness
gains portal fixtures for the player's processor and cooldown.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 18:06:24 +02:00
Cosmic 9f0df29d6c Keep the inventory tab in the creative screen 2026-10-14 12:05:59 -04:00
Ludovic Marie b2462d54c4 Merge pull request #116 from ludovic111/fix/world-spawn-seed
Find a new world's spawn as vanilla does (NoiseSpawnFinder, setInitialSpawn, PlayerSpawnFinder)
2026-10-14 18:04:54 +02:00
Ludovic Marie eccb222e9f Merge pull request #115 from ludovic111/fix/sweet-berries-93
Sweet berries can be planted; picking and bone meal work
2026-10-14 18:04:47 +02:00
Ludovic Marie 6915757dd4 Merge pull request #118 from ludovic111/test/entity-model-normals
entity_model harness: compare per-vertex normals with vanilla
2026-10-14 18:04:39 +02:00
Ludovic Marie 1c957610bc Merge pull request #117 from ludovic111/fix/hurt-tint-order
Apply the entity hurt and white-flash overlay in vanilla's order
2026-10-14 18:04:26 +02:00
Ludovic MarieandClaude Opus 5.5 3f61995c8b test(entity_model): compare per-vertex normals with vanilla
The entity model parity harness now draws each posed model on both sides
under LivingEntityRenderer's root transform (body yaw, scale(-1, -1, 1),
the renderer's own scale) and compares every vertex's normal as the
signed bytes written to the vertex buffer: vanilla's ModelPart.render /
Cube.compile / PoseStack.Pose.transformNormal into a capturing
VertexConsumer, packed with BufferBuilder's own normalIntValue, against
Horizon's mobs::render::draw RGBA8_SNORM normals. A part-scale override
covers negative and non-uniform part scales (trusted sign flips and
untrusted 1/scale normalisation). A one-step difference is accepted only
where vanilla's float sits at a truncation step; a posed position
checksum per drawn part is compared too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:52:01 +02:00
Ludovic MarieandClaude Opus 5.5 a3d3297840 Apply the entity hurt/white overlay in vanilla's order
entity.fsh mixes the OverlayTexture texel into the textured, cardinal-lit
colour and only then multiplies by the lightmap. Horizon applied the lightmap
first and mixed a 0.3 red into the vertex colour, so the red was multiplied
by the texture and never darkened: hurt mobs glowed red at night and in caves.

The vertex stage now passes the lightmap colour and the overlay texel
(0xB2FF0000 hurt red, white alpha 63 for OverlayTexture.u(1.0)) to the
fragment stage, which mixes the overlay, then the lightmap, then glint and fog.

Layers vanilla submits with OverlayTexture.NO_OVERLAY no longer take the hurt
tint: armour (EquipmentLayerRenderer, glint stays), held items
(ItemInHandLayer) and the enderman's block (CarriedBlockLayer). The TNT
minecart flash uses the white overlay on the cart's light
(TntMinecartRenderer.submitWhiteSolidBlock) instead of plain full-bright white.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:50:22 +02:00
Ludovic MarieandClaude Opus 5.5 7ace13cc82 Find a new world's spawn as vanilla does
Horizon searched its own spiral of 48-block steps from 0 0 for a dry,
non-leaf top block, so seed 1891623539983467248 spawned at -48 -48 where
vanilla puts the world spawn at 144 71 144 (the player then lands within
the respawn radius, 152 145 in the report).

Vanilla (MinecraftServer.setInitialSpawn): NoiseBasedChunkGenerator.
getOrigin runs NoiseSpawnFinder over the noise settings' spawn_target
points (SpawnTargetPoint.sampleFitness, a 2048/512 then 512/32 radial
search biased towards 0 0); an 11 by 11 chunk spiral around that chunk
takes the first column PlayerSpawnFinder.getSpawnPosInChunk accepts
(getLevelRespawnPos: MOTION_BLOCKING, WORLD_SURFACE and OCEAN_FLOOR
heights, no liquid, a full-topped collision shape); without one, the
origin chunk's centre at the spawn height. The first player is then
placed by PlayerSpawnFinder.findSpawn: the respawn-radius square in a
random coprime order, a free player box with liquids colliding, else the
spawn with fixupSpawnHeight; adventure mode uses the spawn as is.

horizon-world gains worldgen::spawn_finder and OverworldGenerator::origin;
the client's world_spawn module and game/initial_spawn.rs follow
setInitialSpawn and PlayerSpawnFinder, for single player and the
dedicated server alike. Flat worlds use FlatLevelSource's origin and
spawn height.

tools/test_world_spawn_parity.py compares, for the report's seed, the
chunk harness's seeds and 50 random ones, the origins
(VanillaWorldSpawnOracle against the spawn_origin example) and the
level.dat spawn of worlds created by the vanilla dedicated server and by
Horizon's. Vanilla is not deterministic on chunk corners where trees of
neighbouring chunks overlap (decoration order follows its worker
threads), so a mismatching seed reruns vanilla up to three times.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:49:15 +02:00
Ludovic MarieandClaude Opus 5.5 80645bf0de Sweet berries, carrots and potatoes are planted instead of eaten
A right click with food that is also a block item tried to eat it before
placing it: in creative always, in survival whenever the player was
hungry. BlockItem.useOn places first and only eats a consumable that could
not be placed (counting the use, as ItemStack.useOn does). Picking a sweet
berry bush or cave vines dropped nothing: the harvest loot
(Block.dropFromBlockInteractLootTable) is now rolled and popped. Bone meal
on a bush that can still grow grows it (SweetBerryBushBlock.useItemOn
passes it on) instead of picking it, and counts the use with its
item_interact_finish vibration. Every block placement played its sound
twice; BlockItem.place's level event is now the only one.

tools/test_use_item_on_parity.py drives vanilla's real
ServerPlayerGameMode.useItemOn (and Minecraft.startUseItem's useItem
fallback) against use_item_as_player in a headless game.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:43:24 +02:00
Ludovic Marie 45663c9e39 Merge pull request #98 from ludovic111/feat/logs-crash-reports
Logs and crash reports: game, launcher, CLI and MCP
2026-10-14 17:28:44 +02:00
Ludovic Marie f22e18114d Merge pull request #113 from ludovic111/feat/ctl-mouse-move
horizon-ctl: mouse-move, and turn/look-at --over through the player's mouse path
2026-10-14 17:27:01 +02:00
Cosmic 29fbebf3d7 Merge main and retain Dolphin Grace and Weaving effect flags 2026-10-14 11:25:55 -04:00
Ludovic MarieandClaude Opus 5.5 2cfeed118b horizon-ctl: mouse-move and eased turns through the player's mouse path
mouse-move DX DY (MCP mouse_move) adds relative motion to MouseHandler's
accumulated movement, so the next frame turns the player with
turnPlayer's sensitivity curve ((s*0.6F+0.2F)^3*8, no 8 while scoping),
the inverted axes and the cinematic camera, then Entity.turn. The motion
counts as a grabbed pointer in an active window until the real pointer
is grabbed or released again.

turn and look-at (and look-at-block/look-at-entity) take --over SECONDS:
the turn becomes that motion fed over the time with ease-in-out (the
shorter way round for look-at), replying once the last of it has been
turned. Without --over they still jump. turn is now an MCP tool. stop
cancels a turn in progress.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:18:12 +02:00
Ludovic Marie 452e2b7a9f Merge pull request #112 from ludovic111/fix/stuck-in-blocks
Cobwebs and sweet berry bushes slow the player
2026-10-14 17:16:19 +02:00
Ludovic MarieandClaude Opus 5.5 66c6bd6b13 F3 + C writes a crash report
The debug crash from #90 printed a stand-in report; it now ends the game
with a DebugCrash error that main reports as "Manually triggered debug
crash" with the stack where it was raised. The game keeps the error that
ends it as an error, not a string, so main can tell. Leading std backtrace
frames are dropped (macOS keeps them).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:15:20 +02:00
Ludovic Marie 6c210fe9fd Merge pull request #111 from rdbtCVS/fix/website-footer-links
Fix footer links blocked by decorative Horizon word
2026-10-14 17:13:29 +02:00
Ludovic MarieandClaude Opus 5.5 39e8bbb2f4 Cobwebs and sweet berry bushes slow the player
Entity.applyEffectsFromBlocks now runs WebBlock.entityInside and
SweetBerryBushBlock.entityInside for the player through
Player.makeStuckInBlock (no slowdown while flying, impulse context reset),
with Weaving's lighter cobweb hold and the sweet_berry_bush damage of a
grown bush while the known movement is at least 0.003 on X or Z. The scene
motion harness gains cobweb and berry-bush fixtures run through vanilla's
real applyEffectsFromBlocks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 17:10:01 +02:00
Ludovic Marie 2b9674af8f Merge pull request #108 from ludovic111/fix/wayland-fullscreen-clipboard
Keep the compositor's fullscreen; copy and paste in every text field
2026-10-14 17:08:33 +02:00
rdbtCVS 9bc9a1e159 fix(website): allow clicks through decorative footer word 2026-10-14 16:03:35 +01:00
Cosmic e828354040 Apply fluid currents to primed TNT and show fire in inventory preview 2026-10-14 11:02:27 -04:00
Ludovic MarieandClaude Opus 5.5 744b61efc3 Crash stacks start at the panicking frame, without the build machine's paths; multi-line log messages as log4j writes them
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:58:35 +02:00
Ludovic MarieandClaude Opus 5.5 1569572ba0 Game logs and crash reports; launcher crash notice; logs in the CLIs and MCP
The game writes logs/latest.log in its home like vanilla's log4j config
(client-1.21.2.xml): [HH:mm:ss] [thread/LEVEL]: message, rolled at start and
at midnight to logs/<date>-<n>.log.gz, seven a day. Messages go through the
log facade and still print their old text on stderr.

A main-thread panic or a fatal error writes
crash-reports/crash-<date>_<time>-client.txt (error, stack, Horizon and
Minecraft versions, OS, CPU, memory, GPU adapter, render settings, resource
packs, world, last 50 log lines). Development builds crash on purpose with
HORIZON_DEBUG_CRASH.

The launcher shows "Horizon crashed" when the game it started ends badly,
with Open report, Copy report, Open logs folder and Report on Discord;
Settings gets a Logs row. horizon-launcher logs and horizon-ctl logs
(--lines N, --crash) print the log's end or the newest report, and both MCP
servers have a logs tool.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:58:35 +02:00
Ludovic MarieandClaude Opus 5.5 832a8e3f46 Keep the compositor's fullscreen, and copy/paste in every text field
Fullscreen: applying settings (any option button, joining a world,
travelling, reloading packs) compared the Fullscreen option with what the
window reported and forced the window back to the option. A window made
fullscreen by the compositor (a Hyprland keybind or window rule) left
fullscreen on the next button click. The window now follows blaze3d
Window's fullscreenRequested/fullscreen pair: it is only asked to change
when the option changes (updateFullscreenIfChanged), a change the window
system makes is adopted by the option (updateFullscreenState ->
Minecraft.fullscreenStateChanged), and the window is created fullscreen
when options.txt says so.

Clipboard: Ctrl+A/C/V/X (Cmd on macOS) in the chat, signs, book and quill
(page and title), anvil, creative and recipe-book searches, the language
and pack searches, the LAN port, world name and seed, and the server name
and address boxes, through the arboard clipboard (Wayland data-control,
falling back to X11). Shortcuts follow InputWithModifiers.isCopy/isPaste/
isCut/isSelectAll on the modifier state and the layout's letter; pasted
text goes through each field's own vanilla rules: StringUtil.filterText
and setMaxLength for EditBox, line breaks kept and the 1024-character and
14-line limits for MultiLineEditBox, formatting stripped and whole-or-
nothing width checks for TextFieldHelper on signs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:57:49 +02:00
Ludovic Marie ead31a40f9 Merge pull request #100 from ludovic111/fix/launcher-self-update-message
Launcher: say the self-update succeeded (not "No such file or directory") and restart into it
2026-10-14 16:57:17 +02:00
Ludovic Marie ac96218bfe Merge pull request #104 from ludovic111/fix/particles-63-item-emitters
Particle emitters: waxing, scraping, sparks, eating, snowballs, eggs, slimes (part of #63, stacked on #96)
2026-10-14 16:51:59 +02:00
Ludovic Marie dc74a3fe71 Merge pull request #96 from ludovic111/fix/particles-63-missing-types
Particles: 29 missing vanilla particle types (part of #63)
2026-10-14 16:51:35 +02:00
Ludovic Marie 51601ba2a3 Merge pull request #91 from ludovic111/fix/particles-63-emitters
Entity particle bursts: five angry villager particles and the other bursts as in vanilla (part of #63)
2026-10-14 16:51:30 +02:00
Ludovic Marie b746580c50 Merge pull request #92 from ludovic111/rust/prepare
Prepare resources in Rust: horizon-prepare replaces the Python preparer
2026-10-14 16:43:36 +02:00
Ludovic MarieandClaude Opus 5.5 70583cbf2a Particle emitters: waxing, scraping, sparks, eating, snowballs, eggs, slimes
The new particle types now come from the events that spawn them in
vanilla.

- Level events 3003 (wax on), 3004 (wax off), 3005 (scrape):
  ParticleUtils.spawnParticlesOnBlockFaces, three to five particles on
  each face, from the client level's random. They are sent by honeycomb
  on a block (HoneycombItem.useOn), axe scraping and wax removal
  (BlockTransformer's TransformParticle.send), dispensed honeycomb, and
  copper golems being waxed or scraped.
- Level event 3002: a struck lightning rod sends sparks along its axis
  (ParticleUtils.spawnParticlesAlongAxis); without an axis they cover
  the block's faces.
- Eating: LivingEntity.spawnItemParticles, five crumbs every
  four ticks and sixteen when consumed (Consumable.onConsume), placed in
  front of the eyes and thrown along the look, as item particles in full
  colour. They were greyed terrain crumbs above the eyes. They now
  follow Consumable.shouldEmitParticlesAndSounds with the remaining ticks
  before the countdown, as LivingEntity does: six times over 32 ticks,
  not seven, each one a tick earlier.
- Snowballs (Snowball.handleEntityEvent(3)): eight item crumbs at rest.
  Eggs (ThrownEgg): eight scattered by up to 0.04 a tick.
- Slime, magma cube and sulfur cube landings (AbstractCubeMob.tick):
  size × 16 item_slime, flame or sulfur_cube_goo particles around the
  body, from draws the mob's random also makes on the server.

New harness tools/test_emitter_particles_parity.py: the real
ParticleUtils emitters and LivingEntity.spawnItemParticles.

Part of #63

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:38:38 +02:00
Cosmic cadc4698c1 Merge current main; restore player hurt sounds and bucket fluid updates 2026-10-14 10:33:06 -04:00
Ludovic MarieandClaude Opus 5.5 158e0c6346 Launcher: a self-update after the binary was replaced says it updated, and Restart re-runs it
On Linux, once the launcher's file has been replaced under the running
process (an update from the command line or another window), current_exe()
is "<path> (deleted)" and self_replace failed with "No such file or
directory". The new binary now goes to the path the launcher started from
(copy beside it, rename over it; Windows still uses self_replace), and an
update the file already has is not downloaded again. The message reads
"Updated to X. Restart the launcher to use it."; Restart execs the new
binary with the same arguments (spawn and exit on Windows) and says so if
it cannot start.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:33:02 +02:00
Ludovic MarieandClaude Opus 5.5 63bb9bc37c compare_prepare.py: a tar of the Python tree for machines without the repository; launcher formatting
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:29:33 +02:00
Ludovic MarieandClaude Opus 5.5 a995fd3b46 Prepare with horizon-prepare: launcher, release folders, messages and docs
The launcher prepares a version in-process when it ships the preparer sources
the launcher was built with, with the version's own horizon-prepare when they
differ, and with the Python script only for versions made before it. Release
folders ship horizon-prepare and its sources; resources are reused between
versions with the same preparer. The game's messages, PLAY.txt, the docs and
release builds name horizon-prepare, and tools/prepare_native_client.py is a
wrapper of it for the development tools.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:29:33 +02:00
Ludovic MarieandClaude Opus 5.5 9fa3a684c6 horizon-prepare: the resource preparation in Rust
A port of tools/prepare_native_client.py and the helpers it imported from
lab.py and the test_*_parity.py modules: the player's pinned game files are
imported and checked against research-lock.json, the client's assets and data
copied, the vanilla exporters compiled and run with the JDK (JAVA_HOME, the
PATH, or java_home on macOS, at the pinned java_major), and the resources and
their manifest written byte for byte as the script wrote them, with its
sha256-keyed skips. tools/compare_prepare.py checks that against the Python
preparer.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:29:14 +02:00
Ludovic MarieandClaude Opus 5.5 efa2f0e3be Particles: 29 missing vanilla particle types
Horizon's engine knew 91 of vanilla's 128 particle types. These come from
their real providers, constructor to tick:

- sweep_attack (AttackSweepParticle)
- glow, wax_on, wax_off, electric_spark, scrape (GlowParticle and its
  providers)
- squid_ink, glow_squid_ink (SquidInkParticle: sinks through air)
- item, item_slime, item_snowball, item_cobweb, sulfur_cube_goo
  (BreakingItemParticle: a quarter of the item's ground-model sprite in
  full colour, unlike terrain crumbs)
- flash (FireworkParticles.OverlayParticle, its sine pulse and fading
  alpha), which firework explosions now show as vanilla's Starter does
- firefly (FireflyParticle: wanders, fades in and out, vanishes inside
  blocks)
- trial_spawner_detection(_ominous) (TrialSpawnerDetectionParticle)
- trial_omen, raid_omen (SpellParticle)
- ominous_spawning (FlyStraightTowardsParticle, colour lerped like
  ARGB.srgbLerp)
- spit (ExplodeParticle falling at 0.5), fishing (WakeParticle),
  dust_plume (DustPlumeParticle)
- red/orange/yellow_poplar_leaves (FallingLeavesParticle.PoplarProvider)
- pause_mob_growth, reset_mob_growth (SimpleVerticalParticle)
- block_marker (BlockMarker)

ParticleType.getOverrideLimiter now lists every type vanilla registers
with it (gust, sonic_boom, sculk charges, campfire smoke, vault_connection
and the new ones were missing), so they show beyond 32 blocks.

The /particle commands take the new types; item particles resolve the
stack's ground model.

The particle_providers harness now builds all 120 types Horizon implements
through the real providers (1428 cases).

Part of #63

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:25:24 +02:00
Ludovic MarieandClaude Opus 5.5 383fc116c9 Entity particle bursts: as many particles as vanilla, about the body
Villagers showed one angry, happy or heart particle where vanilla's
AbstractVillager.addParticlesAroundSelf shows five, spread over the body
with Gaussian motion. Taming and love bursts were spread about the middle
of the body rather than over it, and drew from the world random.

particles::around_self places a burst as the client handlers do: per
particle three Gaussian speeds, then getRandomX(1), getRandomY() + y,
getRandomZ(1). Burst holds the counts, speeds and heights vanilla uses,
and entity_event_burst maps entity events to them. The client side uses
the particle engine's random, so no server draw moves.

- villager hurt by a player, failed breeding (13), breeding hearts and
  the child's (12), trades, job sites and beds (14): five particles about
  the villager, not one 1.8 above its feet.
- wolf, cat, parrot, nautilus and horse taming (7/6): seven hearts or
  smoke about the body.
- allay duplication (18): three hearts about the allay.
- llama growth from food: one particle at rest about the body.
- animals in love: the heart moves at the Gaussian speeds already drawn,
  exactly where vanilla puts it; forced growth's particle sits where it
  was placed (sendParticles with no spread) instead of being jittered.

New harness tools/test_entity_particles_parity.py: the real client
handleEntityEvent of Villager, Animal, TamableAnimal, AbstractHorse,
Ocelot, Dolphin and Allay against entity_event_burst and around_self.

Part of #63

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:13:38 +02:00
Ludovic Marie 27fc327195 Merge pull request #90 from ludovic111/fix/f3-combos-73
F3 key combinations, as 26.3's KeyboardHandler runs them
2026-10-14 16:12:40 +02:00
Ludovic Marie ada71df410 Merge pull request #89 from ludovic111/fix/particles-63-providers
Particles: vanilla random streams, and fixes to 20 providers (part of #63)
2026-10-14 16:08:48 +02:00
Cosmic 2236c9607f Apply burning-time scaling to Fire Aspect ignition too 2026-10-14 10:08:37 -04:00
Ludovic MarieandClaude Opus 5.5 70fad91ee5 F3 key combinations, as 26.3's KeyboardHandler runs them
F3 only toggled the debug overlay. 26.3 makes the debug keys rebindable
mappings (key.debug.*): the modifier (F3) held with another key runs
handleDebugKeys, released alone toggles the overlay unless it was used as
a modifier; F3+Escape pauses without the menu; F3+C held ten seconds
crashes the game.

- debug_keys: KeyboardHandler.keyPress's state (usedDebugKeyAsModifier,
  the modifier's down state, debugCrashKeyTime) and tick, with the actions
  in handleDebugKeys' order; unit tests replay key sequences.
- gizmos: 26.3's gizmo lines (colour, width in pixels, near-plane clip as
  GizmoFeatureRenderer.buildLines), ChunkBorderRenderer's geometry and
  EntityHitboxDebugRenderer's boxes, eye lines and view arrows; a coloured
  line pipeline draws them, depth tested or always on top.
- game/debug_keys: the actions. F3+A rebuilds every section, B hitboxes,
  C copies the location (/execute in ... run tp @s, %.2f half up), D
  clears chat, G chunk borders, H advanced tooltips (options.txt), I copies
  /setblock or /summon with data (Shift: client side), N toggles spectator
  and the previous mode with /gamemode's feedback, P pause on lost focus,
  T reloads resource packs, V dumps the version, X improved transparency;
  F4 without permission says debug.gamemodes.error. Messages carry the bold
  [Debug]: prefix in yellow (red for the crash countdown).
- PauseScreen(false): only "Game Paused" at the top; the
  pauseOnLostFocus option now decides whether losing focus pauses.
- The clipboard through arboard; `horizon-ctl status` reports the debug
  state and the text last copied.

Fixes #73

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 16:08:26 +02:00
Cosmic f3dda9c412 Address PR59 review: axolotl timers, fluid and fire parity, persistence and Rust tests 2026-10-14 10:05:41 -04:00
Ludovic Marie f881917d91 Merge pull request #88 from ludovic111/fix/powdered-snow-62
Powder snow: sinking, freezing, leather boots, buckets and falling blocks
2026-10-14 15:57:54 +02:00
Ludovic MarieandClaude Opus 5.5 d9461c6d2d Particles: build each one with vanilla's random streams, fix the providers that differed
Every vanilla Particle owns a RandomSource.create() of its own; providers
draw from ParticleEngine.random, a few from ClientLevel.random, and spells
from SpellParticle.RANDOM. Horizon drew everything from one generator, so
draws landed on the wrong stream. Particles now carry their own random,
and provider, level and spell draws use theirs, as in vanilla.

Fixed against the real providers:
- gust / small_gust: SingleQuadParticle(x, y, z) constructor, so the
  12..15 tick lifetime comes out of the right draws.
- explosion_emitter, gust emitters: NoRenderParticle draws no quad size.
- effect, instant_effect, entity_effect, witch, infested: x/z motion from
  SpellParticle.RANDOM; the witch's brightness from the provider.
- landing_honey, landing_obsidian_tear, falling_nectar, spore_blossom_air,
  crimson_spore, warped_spore, white_ash, sculk_charge(_pop), dolphin:
  provider draws (lifetimes, motion, alpha) from the provider random, after
  or before the sprite as the provider orders them; crimson spore motion
  scaled by the float constants; composter lifetime from the level random.
- enchanted_hit: MagicProvider's 0.3/0.8 tint after the constructor tick;
  damage_indicator lives 20 ticks (DamageIndicatorProvider).
- note: colour from Mth.sin's table.
- shriek: one random sprite, not animated.
- trail: Particle(x, y, z, xa, ya, za) constructor, ARGB.scaleRGB on the
  8-bit channels, Mth.lerp towards the target including the last tick.
- firework sparks: full bright (SimpleAnimatedParticle.getLightCoords).

New parity harness tools/test_particle_providers_parity.py: the real
ParticleResources providers build every type Horizon implements in a
stand-in ClientLevel (air, optionally a stone floor); the oracle recovers
each particle's clock-seeded random and the probe replays it; state,
requested particles and sounds are compared tick by tick.

Part of #63

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:53:34 +02:00
Ludovic MarieandClaude Opus 5.5 6ce83021b5 Powder snow: sinking, freezing, leather boots, buckets and falling blocks
Powder snow was inert: the player's collision context never carried its
fall distance or boots, block-inside effects never ran for the player,
frozen ticks stayed 0 and the empty bucket only took fluids.

Player (PlayerMotion, LivingEntity.aiStep order):
- PowderSnowBlock.getCollisionShape gets the player's fall distance and
  leather boots: it sinks through, walks on top in leather boots (sinks
  when crouching), lands on the 0.9-high shape after a fall of more
  than 2.5 blocks.
- Entity.applyEffectsFromBlocks over this tick's movement path (the
  ported block sweep, StepBasedCollector steps): entityInside makes it
  stuck (0.9, 1.5, 0.9) while its feet are in powder snow and sends the
  server's snowflake from the level random; FREEZE sets isInPowderSnow
  and adds a frozen tick per step; EXTINGUISH destroys the snow if the
  player burns and puts the fire out. ServerPlayer.onInsideBlock fires
  enter_block for every block entered (which also unlocks the boat
  recipes in water, and the end gateway advancement).
- baseTick's wasInPowderSnow lets leather boots climb out (living_air).
- Server freezing: thawing 2 a tick, the powder_snow frost modifier
  (-0.05 x percent frozen, not over air), freeze damage every 40 ticks
  when fully frozen; leather armor (#freeze_immune_wearables) and
  spectators don't freeze.
- HUD: the powder snow outline overlay and frozen hearts.

Items and blocks:
- BucketItem.use on powder snow: pickupBlock (2001), used statistic,
  fill sound, FLUID_PICKUP, createFilledResult, filled_bucket trigger.
- SolidBucketItem: the empty_powder_snow place sound and an empty bucket
  back in survival.
- Falling blocks land on powder snow, or end up inside it and break
  after a fall of more than 2.5 blocks.

test_native_scene_motion gains powder snow fixtures ("snow_tick": the
oracle runs vanilla's real applyEffectsFromBlocks and freezing) and
prints frozen ticks, the snow flags and the stuck multiplier.

Fixes #62

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:45:55 +02:00
Ludovic Marie 6f2823b652 Merge pull request #87 from ludovic111/fix/physical-shift-77
Read the physical Shift keys in container screens and drop a stack clicked outside
2026-10-14 15:44:49 +02:00
Ludovic Marie 4e36b2a217 Merge pull request #85 from ludovic111/fix/resource-packs-72
Resource packs: reload everything in game and merge stacked files like vanilla (fixes #72)
2026-10-14 15:44:44 +02:00
Ludovic Marie 4ce9a5642d Merge pull request #86 from ludovic111/fix/wolf-advancements-65
Match the variant components of entity predicates (taming grants only Best Friends Forever)
2026-10-14 15:42:26 +02:00
Ludovic Marie 2b5313b943 Merge pull request #81 from ludovic111/fix/feeding-sounds-68
Feeding sounds: each animal's own eating sound, or none, as in vanilla
2026-10-14 15:42:21 +02:00
Ludovic Marie 6ca6d0b919 Merge pull request #83 from ludovic111/fix/hand-sway-66
Hand sway: the first-person hands lag behind the view, as in vanilla
2026-10-14 15:42:12 +02:00
Ludovic Marie a56d63d03f Merge pull request #82 from ludovic111/fix/gamerules-persist-74
Game rules: save them with the world once, as they are now; save on Quit
2026-10-14 15:42:01 +02:00
Ludovic Marie 8dd63c69ef Merge pull request #84 from ludovic111/fix/fire-charge-pitch
Give the fire charge's use sound its own pitch
2026-10-14 15:41:51 +02:00
Ludovic MarieandClaude Opus 5.5 0b362e270f Match the variant components of entity predicates
Taming any wolf also granted The Whole Pack and A Complete Catalogue: entity
predicates treated minecraft:components as always true, so every
tame_animal criterion of those advancements (one per wolf or cat variant)
matched the first animal tamed. EntityPredicate tests them with
DataComponentExactPredicate against what the entity reports through
Entity.get (Wolf.get(WOLF_VARIANT) and so on): mobs now report their variant
component (wolf, cat, frog, pig, cow, chicken, zombie nautilus) and the
predicate compares it, an absent component never matching.

Checked against the real EntityPredicate of every criterion of the variant
advancements on real entities of every variant by
tools/test_entity_components_parity.py.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:33:50 +02:00
Ludovic MarieandClaude Opus 5.5 0d0378916b Resource packs: reload everything in game and merge stacked files like vanilla (#72)
Choosing packs in the Resource Packs screen only reloaded the GUI atlas
(and only when it kept its size), item models and languages; block
textures and models changed after a restart, and sounds, clouds and the
world border never did. Block textures were also squeezed to 16x16, and
the pack overlay took every file from the top pack, so a pack's own
en_us.json, sounds.json, font or atlas definition replaced vanilla's
instead of adding to it (all other text, or every vanilla sound, gone).

- Minecraft.reloadResourcePacks: rebuild block sprites and models, mesh
  tables, the shared atlas, item models, sounds, languages, GUI
  metadata, clouds.png and forcefield.png from the new overlay; swap the
  mesher's context (workers read it per job), mesh every loaded section
  again (LevelRenderer.allChanged) and build a renderer with the new
  textures. Nothing switches if loading fails.
- The block sprite array takes the largest texture's resolution (power
  of two, at most 256 MiB), so 32x/64x packs keep their detail;
  animations upload at that size.
- Files vanilla reads as resource stacks are merged in the overlay:
  ClientLanguage (keys override), SoundManager (sounds add up unless an
  event replaces; a sounds.json Gson rejects is skipped whole),
  FontManager (top pack's providers first), SpriteSourceList (sources
  bottom up). Languages are read from every namespace, not only
  minecraft.
- Missing or broken block textures use vanilla's missing texture; packs
  that still break startup fall back to the default resources
  (Minecraft.rollbackResourcePacks).
- Open Pack Folder opens the folder on macOS and Windows too.

tools/test_resource_pack_parity.py checks pack discovery, overlays,
filters, which pack provides a file and the merged languages, sounds,
fonts and atlases against vanilla's FolderRepositorySource,
MultiPackResourceManager and reload listeners.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:33:34 +02:00
Ludovic MarieandClaude Opus 5.5 d75ad778e3 Read the physical Shift keys in container screens and drop a stack clicked outside
Quick move, the recipe book's place-all, its search box and the hold-Shift
tooltips read self.keys, which holds remapped and toggled keys: with toggle
sneak, a Left Shift press behind a screen is dropped by the sneak mapping and
sync_toggle then removes ShiftLeft. Vanilla reads the event's own modifiers
(InputWithModifiers.hasShiftDown) or Screen.hasShiftDown: the physical keys.
Track them in physical_keys and read them through has_shift_down.

Clicking outside the window did nothing. AbstractContainerScreen.mouseClicked
sends slot -999 when hasClickedOutside (AbstractRecipeBookScreen's rule when
the screen has a book): a held stack starts a quick craft drag whose release
sends PICKUP -999, which AbstractContainerMenu.doClick turns into a drop of
the stack (left) or one item (right), thrown from the hand with a swing. The
mouse handling is now horizon_client::container_screen, checked against the
real screens by tools/test_container_screen_parity.py; servers get the same
ContainerClick.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:31:49 +02:00
Ludovic MarieandClaude Opus 5.5 84adffc3f2 Hand sway: the first-person hands lag behind the view, as in vanilla
Vanilla keeps xBob and yBob on the LocalPlayer: applyInput eases them
halfway to the player's rotation every tick, and
FirstPersonHandsAndItemsRenderer turns both hands by
(viewXRot - xBob) * 0.1 degrees about X, then (viewYRot - yBob) * 0.1 about
Y, before drawing either (FirstPersonHandsAndItems.extractRenderState
interpolates the bobs). Horizon drew the hands fixed to the view.

- first_person::HandSway: the bobs, applyInput's tick and the rotation.
- The game ticks it with the hands and resets it where vanilla makes a new
  LocalPlayer (joining, respawning, changing dimension, leaving the End);
  hand_geometry turns the arm, held items and maps by it.

The first-person harness's steps can turn the player: the oracle sets the
LocalPlayer's rotation and calls the real applyInput, and both sides print
xBob, yBob, xBobO and yBobO every tick (turning scenarios plus random turns
in the random cases).

Fixes #66

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:30:30 +02:00
Ludovic MarieandClaude Opus 5.5 162e3d36f7 Give the fire charge's use sound its own pitch
Placing fire with a fire charge played item.firecharge.use at the flint and
steel's pitch (nextFloat * 0.4 + 0.8, one draw). FireChargeItem.playSound
uses (nextFloat - nextFloat) * 0.2 + 1.0, two draws from the level random.
The pitch is now horizon_client::items::fire_starter_pitch, checked against
the real FireChargeItem.playSound by tools/test_fire_starter_sound_parity.py.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:27:13 +02:00
Ludovic MarieandClaude Opus 5.5 9bbb674184 Game rules: save them with the world once, as they are now; save on Quit
Game rules lived twice: Level (loaded when the world opened, written to
data/minecraft/game_rules.dat by Level::write) and the rules the game and
/gamerule use. Every save wrote the file first with the rules loaded at
open, then again with the current ones; a failed second write (on Windows a
file just renamed into place can be held briefly by the indexer or an
antivirus) was only logged, leaving the old rules on disk, so the world
opened with them again.

- sync_level copies the current rules into Level, and Level::write is the
  only writer of game_rules.dat (written as vanilla writes saved data:
  `_new`, then renamed over the old file).
- The world is saved when the application ends without a window close
  (ApplicationHandler::exiting): on macOS, Quit (Cmd+Q) ends the
  application through applicationWillTerminate, while vanilla's GLFW window
  turns it into a window close and Minecraft.stop saves the world. Window
  close, `horizon-ctl quit` and exiting share save_for_exit, which saves
  once.

Tests: a unit test writes changed rules through Level::write and reads them
back (GameRules::load and Level::read); the save round-trip harness has
Horizon's player change a rule with /gamerule before saving and requires the
new value in the world vanilla then loads.

Fixes #74

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:16:32 +02:00
Ludovic MarieandClaude Opus 5.5 f1cc118df0 Feeding sounds: each animal's own eating sound, or none, as in vanilla
Animal.mobInteract plays playEatingSound(), which is empty in Animal and
overridden only by armadillos, cats, foxes, frogs, goats, pigs, sniffers and
sulfur cubes (plus nautili). Horizon fell back to entity.generic.eat for every
other animal (cows, sheep, chickens, rabbits, turtles, bees...), with a level
random pitch instead of each class's volume and pitch.

- mobs::ai::eating_sound: the overrides with their exact volume and pitch
  (makeSound with the voice pitch, playSound(1, 1), or Level.playSound with
  Mth.randomBetween(0.8, 1.2)); silent otherwise.
- mobs::ai::feed_animal: Animal.mobInteract's food part, shared by the game
  and the mob AI probe; Strider.mobInteract adds entity.strider.eat.
- AgeableMob.ageUp(seconds, true): forcedAge and the forced-age particle
  timer, whose positions draw from the mob's random on the server.
- Tame wolves and cats healed with food: TamableAnimal.feed (wolves silent).
- Parrots: Parrot.isFood is false; wild ones take parrot food with
  entity.parrot.eat and a one-in-ten taming chance.
- Baby pigs and chickens use their sound variant's baby_sounds.

The mob AI harness gains a `feed TICK MOB ITEM` event (the oracle calls the
real Animal.mobInteract) and feeding scenarios for adult and baby cows, pigs,
sheep and chickens.

Fixes #68

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:15:15 +02:00
Ludovic Marie 66ce394d2d Merge pull request #80 from ludovic111/fix/composters-70
Composters take compostable items by hand, from hoppers and from droppers
2026-10-14 15:09:21 +02:00
Ludovic Marie b4c63fa207 Merge pull request #78 from ludovic111/fix/rain-length-71
Rain and snow: tile the weather texture like WeatherEffectRenderer (fixes #71)
2026-10-14 15:09:11 +02:00
Ludovic Marie 97d3282161 Merge pull request #79 from ludovic111/fix/cloud-distance-67
Clouds: draw to the Cloud Distance option, not the render distance (fixes #67)
2026-10-14 15:09:07 +02:00
Ludovic Marie 115b0b856b Merge pull request #76 from ludovic111/fix/furnace-progress-69
Furnaces keep their cooking progress across menu clicks
2026-10-14 15:09:03 +02:00
Ludovic MarieandClaude Opus 5.5 0d3628a035 Composters take compostable items by hand, from hoppers and from droppers
Right-clicking a composter with wheat (or any compostable item) did
nothing: ComposterBlock.useItemOn wasn't implemented, only emptying a
full composter. Hoppers and droppers didn't see the composter as a
container either, and a hopper under one sucked items through it.

- useItemOn: below level 7 a compostable item adds a layer with the
  chance of its compostable component's provider (evaluated in the
  block-interaction loot context, drawing from the level random), then
  level event 1500, the used statistic and one item consumed (none in
  creative); level 7 still consumes the action; a full composter falls
  through to useWithoutItem and empties.
- Level event 1500 (handleFill): composter.fill(_success) and ten
  composter particles above the compost.
- getContainer: the input container takes one compostable item from
  above (hoppers, droppers, crafters), the output container gives a
  hopper below the bone meal of a full composter, emptying it twice as
  vanilla's setChanged calls do (and losing it when the hopper is full);
  levels 7 and other faces refuse.

tools/test_composter_parity.py runs right-clicks, hoppers above and
below, and droppers into composters at every level through
VanillaDispenserOracle (new "use" and "hopper" actions) and the game's
dispense fixture.

Fixes #70

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 15:00:41 +02:00
Ludovic MarieandClaude Opus 5.5 12eca8a5c1 Clouds: draw to the Cloud Distance option, not the render distance (#67)
The cloud mesh radius came from the render distance, the far plane was
capped at max(4 x render distance, 1024) and the cloud fog end was a
constant 2048, so lowering the render distance cut the clouds short.
Vanilla ties all three to options.cloudRange: CloudRenderer.prepare
builds ceil(range * 16 / 12) cells, Camera.depthFar is
max(4 x render distance, range * 16) (also the hand projection, the
frustum and the world border), and AtmosphericFogEnvironment ends
cloud fog at min(range * 16, visual/cloud_fog_end_distance).

The cloud render harness now checks the radius for Cloud Distance
2..128 against the shipped mesh builder, and the environment harness
covers visual/cloud_fog_end_distance.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 14:38:52 +02:00
Ludovic MarieandClaude Opus 5.5 8c0586db4b Furnaces keep their cooking progress across menu clicks
A click in the furnace menu reset the cooking timer whatever it did.
AbstractFurnaceBlockEntity.setItem restarts cooking only when the input
slot gets something other than the same item with the same components,
and menu clicks that take part of the input or merge into it never call
it. Furnace::input_clicked applies that after each click, with the new
input's total cook time.

test_menu_click_parity gains furnace_be, blast_furnace_be and smoker_be:
the server's furnace menus over real block entities, comparing the
cooking data slots after every click.

Fixes #69

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 14:34:32 +02:00
Ludovic MarieandClaude Opus 5.5 b723ef9828 Rain and snow: tile the weather texture like WeatherEffectRenderer (#71)
Horizon stretched a quarter of rain.png over each whole column, up to
20 blocks tall, so streaks were about five times too long. Vanilla
advances v by a quarter per block and lets the sampler repeat, so the
texture repeats every 4 blocks. Port createRainColumnInstance,
createSnowColumnInstance and prepareInstances exactly (seeded column
speed, game-time scroll, snow drift and brightening, camera-block size
table, square radius from the Weather Radius option, alpha falloff,
precipitation at the camera's y), and split each quad at the texture
seams so the atlas sprite repeats.

tools/test_weather_render_parity.py compares the columns and quads
with the shipped renderer.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 14:34:26 +02:00
Cosmic 726f88fcfc Fix axolotl AI, fluid and fire integration, and world-local progress
Bind resident environment kernels and real fire clocks, fix sprite uploads and flame material, restore swim speed, throttle item lava audio, and emit fire extinguish events. Reset world-entry progress state without deleting saved data. Exact axolotl replay parity remains deferred to issue #64.
2026-10-14 02:20:13 -04:00
Cosmic 778890207a Merge remote-tracking branch 'origin/main' into fix/vanilla-item-use-animations 2026-10-13 22:41:21 -04:00
Cosmic 5903b5981d Fix item-use feedback, ranged poses, arrows and elytra rendering 2026-10-13 22:41:21 -04:00
Ludovic Marie 6c1000a374 Merge pull request #58 from ludovic111/remove-roadmap
Remove the roadmap
2026-10-14 02:24:25 +02:00
Ludovic MarieandClaude Sonnet 5.5 71cee5279c Remove the roadmap from the README, the website and the launcher
The README keeps the parity table, and its known differences move to a
Known issues section. The website drops the What's next section and its
nav links, and no longer fetches or requires a Roadmap section. The
launcher drops its What's next page, `next` subcommand and `roadmap`
MCP tool.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-14 02:18:29 +02:00
Ludovic Marie d1cf9b4930 Merge pull request #57 from ludovic111/website/contributors
Website: add a Contributors block to the community section
2026-10-14 02:06:21 +02:00
Ludovic MarieandClaude Sonnet 5.5 2b7c72255c Website: add a Contributors block to the community section
Lists the GitHub contributors of ludovic111/horizon (bots left out, the
owner first) with avatar, login, commit count and a link to the profile.
Built in by build.mjs like the releases (the build still succeeds when
GitHub does not answer, and the block stays hidden until the page loads
it) and refreshed by the page from the API. Adds a nav and menu entry,
lets avatars.githubusercontent.com through img-src, and updates the
README, LEGAL.md and the privacy note.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-14 02:01:43 +02:00
Ludovic Marie e5c061dba6 Merge branch 'pr-54' into merge-54 2026-10-14 01:07:56 +02:00
Ludovic Marie 3879ca8ec7 Merge remote-tracking branch 'origin/worldgen-trees' into merge-55 2026-10-14 00:51:14 +02:00
Ludovic MarieandClaude Opus 5.5 069acd9aba Streaming: wait only for lower-ranked chunks that can be decorated
A chunk in the decoration range whose diagonal neighbour falls outside the
generation range never gets its 3x3 protos, so it must not hold back the
higher-ranked chunks within two of it. Render distances 2, 5 and 12 load and
keep loading while flying without stalling.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:19:43 +02:00
Cosmic 1499c2a888 Fix GUI item lighting, preview seams and glyph bleeding 2026-10-13 18:16:09 -04:00
Ludovic MarieandClaude Opus 5.5 2c57fcc09f decorated_region: compare fully decorated regions decorated in vanilla's order
A new harness decorates a 13x13-chunk area around each site, on both sides,
in the order vanilla's chunk scheduler uses around a player standing there
(chunk_dump HORIZON_LIST_ORDER prints decoration_order::vanilla_order), and
compares every block state, quart biome, block entity and scheduled tick:
the two reported spots on seed 1891623539983467248 (taiga trees at
204 -239; a stronghold with sculk and a geode at 4870 401), eleven tree-heavy
biomes and the nearest mineshaft, village, ancient city and trial chambers of
two seeds. 21 sites, 3,549 chunks, 0 differences.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:09:59 +02:00
Ludovic MarieandClaude Opus 5.5 317da28481 Structure pieces schedule the fluid ticks of the fluids they place
StructurePiece.placeBlock schedules a tick for the fluid of every block it
sets (the lava of a stronghold's portal room, a fortress's lava wells, water
in a monument or a mineshaft); in a WorldGenRegion it lands in the proto
chunk and runs once the chunk is live. The port treated it as a no-op, so
those fluids sat still until a neighbour changed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:04:56 +02:00
Ludovic MarieandClaude Opus 5.5 147ea6661f Decorate chunks around the player in vanilla's order
Biome decoration is order dependent: a chunk's features write into its
neighbours, so a tree, ore blob or sculk patch placed first changes where the
next chunk's features fit and how many random draws they take. Horizon's
streamer decorated whichever chunk had its 3x3 protos ready, nearest first but
spread over non-overlapping regions for parallelism; around a teleported
player that swapped 45% of the overlapping chunk pairs against vanilla (whose
own runs swap 6%), and grew visibly different forests (seed
1891623539983467248 at 204 108 -239), ore veins, sculk and geodes.

worldgen::decoration_order replays vanilla's chunk scheduler for a standing
player: loading tickets ring by ring in fastutil hash order, four in flight,
FULL tasks decorating their 3x3 squares x-outer by level, INITIALIZE_LIGHT
tasks themselves, a ticket released once its 5x5 square is full. The streamer
ranks chunks with it whenever the player's chunk or the render distance
changes and decorates a chunk only when no lower-ranked chunk within two of it
is still waiting, so chunks further apart still decorate in parallel. Around
that spot the decorated blocks that differ from a vanilla server fall from
about 9000 to about 1000 (two vanilla runs differ by about 200).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:55:01 +02:00
Ludovic Marie 19ec3213fd Merge remote-tracking branch 'origin/review-52' into merge-52 2026-10-13 23:38:55 +02:00
Ludovic MarieandClaude Opus 5.5 4c4e579d3f Generated chunks keep the ticks their features scheduled
VanillaTerrain::finish dropped the proto chunk's block and fluid ticks; vanilla's
LevelChunk takes them over from the ProtoChunk (unpackBlockTicks), so the leaf
re-measurements and the fluid ticks of lakes and springs run once the chunk is
live. They now travel in the chunk's ChunkExtras, like a saved chunk's ticks,
and register with the level's scheduler on arrival; block ticks are translated
from worldgen's default state ids to the game's block indices.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:38:02 +02:00
Ludovic MarieandClaude Opus 5.5 2c8de2b015 chunk_generation: compare scheduled ticks; HORIZON_ORDER decoration order
Both dumps list each proto chunk's scheduled block and fluid ticks in
scheduling order (`t block|fluid NAME X Y Z PRIORITY`) and the harness
compares them: they run once the chunk is live, and the leaf ticks of
updateShapeAtEdge were missing without any block differing at FEATURES.

HORIZON_ORDER names a file of `x z` lines both sides decorate in, instead of
row-major: decoration is order dependent (a chunk's features write into its
neighbours), and vanilla's chunk system decorates around a player in its own
order.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:38:02 +02:00
Ludovic MarieandClaude Opus 5.5 897ca2aa5e Worldgen shape updates schedule their ticks in the proto chunks
StructureTemplate.updateShapeAtEdge (every tree, structure pieces) and
Block.updateFromNeighbourShapes run updateShape on a WorldGenRegion, where
LeavesBlock.updateShape schedules a one-tick block tick to re-measure its
distance and waterlogged blocks schedule fluid ticks: vanilla keeps them in
ProtoChunkTicks and runs them once the chunk is live. Horizon ran updateShape
against a throwaway tick scheduler and lost them, so leaves where trees
overlap kept the distance their own tree gave them (one more than vanilla's
for thousands of leaves in a taiga), and could decay where vanilla's don't.

level::Ticks gains a capture mode; the decoration world schedules what a
shape update captured, in order, before the update's own setBlock.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:38:02 +02:00
Ludovic Marie 8ad1e52067 Merge remote-tracking branch 'origin/trading' into merge-50-53 2026-10-13 23:30:15 +02:00
Ludovic Marie 373fa31a35 Merge remote-tracking branch 'origin/agent-control' into merge-50-53 2026-10-13 23:30:15 +02:00
Ludovic MarieandClaude Opus 5.5 0944280fb3 Merge PR #52 (entity directional lighting) into review-52
Conflicts with #51: entity.wgsl keeps the crumbling sprite UVs and
samples with the per-face colour; gfx.rs keeps crumbling_sprite and
outline_params and puts the Nether flag in time.y; game.rs keeps #51's
breaking and cloud geometry. #51's new vertices (breaking decals,
cloud faces, the batching test) get the new zero normal, so they stay
unshaded.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:18:40 +02:00
Ludovic Marie a72dd98e2a Merge pull request #51 from ludovic111/review-cosmic
Cosmic's camera, breaking, clouds and outline fixes (#42 + #47), integrated
2026-10-13 23:14:30 +02:00
Cosmic 7b21d4bc6c fix(client): restore directional lighting for mob models 2026-10-13 17:08:34 -04:00
Ludovic MarieandClaude Opus 5.5 c810a3213c Wandering traders trade again: only villagers refuse while asleep
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:07:02 +02:00
Ludovic Marie 193c08e90f Merge remote-tracking branch 'origin/main' into review-cosmic 2026-10-13 23:06:15 +02:00
Ludovic MarieandClaude Opus 5.5 393d113dfb Merchant screen: the restock tooltip over an out-of-stock result
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:02:59 +02:00
Ludovic MarieandClaude Opus 5.5 92209ddeee Trading on the dedicated server, compared with vanilla's
test_dedicated_server_parity summons a librarian beside the spawn and the
vanilla protocol client right-clicks it: the OpenScreen packet (title as
Entity.getDisplayName, UUIDs left out) and the MerchantOffers packet must
match vanilla's server. Villagers keep Xp, LastRestock and RestocksToday
before their offers are made (vanilla's null offers).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:01:02 +02:00
Ludovic MarieandClaude Opus 5.5 5cb14ee496 Trade over the network: LAN guests and Horizon as a client
The host hands a trading screen a guest's interaction opens to that guest:
OpenScreen (minecraft:merchant), MerchantOffers when the offers change,
the select trade packet, container clicks run on the merchant menu engine,
the TRADE reputation event and prices for the guest's UUID, the payment back
on close. As a client, Horizon shows a server's trading window from its
MerchantOffers and sends select trade and clicks. Stored enchantments, dyed
colours and map ids now travel in item stacks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:44:16 +02:00
Ludovic Marie 5a5e8ffa71 Merge pull request #49 from ludovic111/creative
Creative inventory: every tab and the search as vanilla builds them; scrollbar drag
2026-10-13 22:41:39 +02:00
Ludovic MarieandClaude Opus 5.5 d17e5da848 Merge origin/main into review-cosmic
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:32:35 +02:00
Ludovic MarieandClaude Opus 5.5 7fab5ec1ff test_creative_parity: no Rust scope (creative.rs reaches item_data and save)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:30:39 +02:00
Ludovic MarieandClaude Opus 5.5 43cff3b44e Trade in game through the verified merchant menu
The trading screen runs MerchantMenu on the menu engine with the villager's
merchant::Session: level-ups add offers while it is open, prices follow the
TRADE reputation event a tick later, orbs drop at the villager with its own
random, the yes/no voice and regeneration as vanilla; special prices stay
after closing. Offers use the world's RandomSequences (now saved as
random_sequences.dat), the villager's position, its namespaced type (desert,
snow... trades) and exploration maps found through /locate.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:30:33 +02:00
Ludovic MarieandClaude Opus 5.5 2e7e249096 Merge #47 (selection outline width and depth) into review-cosmic
Resolve the gfx.rs conflict with #42 and keep the shared Globals uniform
consistent: Rust, terrain.wgsl and entity.wgsl now all end with
time, crumbling_sprite, outline_params. The automatic merge left
terrain.wgsl reading outline_params at crumbling_sprite's offset. A test
compares the three declarations.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:29:31 +02:00
Ludovic Marie 59ce240633 Merge pull request #48 from ludovic111/sound-menus
Fix the looping grass-step sound; classic menus lead back to Horizon's
2026-10-13 22:28:47 +02:00
Ludovic MarieandClaude Opus 5.5 502c8b9311 agent_control_e2e: pick up a drop from within a block (it can land under the trunk)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:28:14 +02:00
Ludovic Marie 2ee7d7af9f Merge branch 'pr-42' into review-cosmic 2026-10-13 22:26:55 +02:00
Ludovic MarieandClaude Opus 5.5 a3dd34a8f3 Trading parity harness: offers, prices, restocks, the merchant menu and NBT against vanilla
VanillaTradingOracle runs villagers, wandering traders and MerchantMenu on a
real flat server; trading_fixture runs horizon_client::merchant and a new
merchant kind of the menu engine (MerchantContainer, MerchantResultSlot,
tryMoveItems, quick move) over a merchant::Session. Generation now covers
random dyes, random potions, stew effects, exploration maps (a MapMaker hook),
sum/binomial providers and the trade's max uses / xp / discount providers;
getRecipeFor honours the selection hint as vanilla, Offers leave defaults out.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:25:27 +02:00
Ludovic MarieandClaude Opus 5.5 299280baa2 Classic menus: Menu Style on the Video Settings page leads back to Horizon's
Choosing Classic in Options > Interface left no way back. The classic
Video Settings page, which already starts with Horizon's graphics row,
gets a Horizon-only "Menu Style: Classic" button below it: it switches to
Horizon's menus, saves horizon.txt and opens Options > Interface. The
classic main Options screen keeps vanilla's exact layout.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:24:57 +02:00
Ludovic MarieandClaude Opus 5.5 60fc617402 Sound: player footsteps once per metre walked, not every tick
The client's MotionWorld.apply_movement_emission pushed a footstep event
on every Entity.move, and the game played the block's step sound for
each. Gravity moves a grounded player every tick, so standing on grass
played block.grass.step 20 times a second, overlapping into an endless
rustle (19 instances alive at once). The audio stream had been muted by a
saved WirePlumber setting until v2026.10.13.1, which hid it.

Route the player through horizon_world::movement_emission (vanilla's
applyMovementEmissionAndPlaySound: moveDist, nextStep, the supporting
block checks) with Player.getMovementEmission (nothing while flying or
sneaking on the ground). The status sound census now lists the events
holding channels, which is how the loop was found.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:24:57 +02:00
Ludovic MarieandClaude Opus 5.5 cac89a9995 Creative inventory: every tab and the search as vanilla builds them; scrollbar drag
The creative-tabs.json export failed to build the functional blocks tab (no
data-pack registries: banner patterns), and its fallback read decompiled
sources from a path that no longer exists, so the tab was empty and anvils,
crafting and smithing tables were missing from the tabs and the search. The
search also matched only an approximate display name.

VanillaCreativeTabsExporter now builds every tab with vanilla's own
CreativeModeTabs.tryRebuildTabContents over the vanilla data pack's
registries and writes creative-inventory.json: stacks with components, and
the search tab's creative tooltip lines and tags. The client searches them
as SessionSearchTrees does (FullTextSearchTree, IdSearchTree after '#').
Changing tab empties the search box, as in selectTab.

The scrollbar only jumped to the pressed point; holding it now scrolls as
the mouse moves, anywhere, until release (mouseClicked/mouseDragged), and
the wheel and the scroller follow ItemPickerMenu.

tools/test_creative_parity.py compares every tab and 6,793 searches with
the vanilla client's own search trees. horizon-ctl `type` also fills the
creative search box.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:24:55 +02:00
Cosmic 5ea60fbd8d fix(client): match vanilla block selection outline width and depth
Hardware LineList forced one-pixel strokes, while the guessed 0.002 endpoint growth did not separate the edges from block surfaces. Render screen-space strips with vanilla framebuffer width scaling and perspective/view depth layering, leaving the shape edges unchanged. Apply normal outline fog and add three regression tests.

Offline gate passed on this main-based branch. Actual vanilla GLSL vs Horizon WGSL GPU comparison covers 3,072 vertices; maximum projected difference is 0.0036621 pixels. No code from PR #42 is included.
2026-10-13 16:04:10 -04:00
Ludovic MarieandClaude Opus 5.5 c0f468a871 horizon-ctl: horizon-ctl - returns the last failure's status
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 22:00:44 +02:00
Ludovic MarieandClaude Opus 5.5 6716b0d953 Docs: agent control with horizon-ctl and its MCP server
README gets an Agent control section (out of the roadmap: it's done), the
native client guide describes every command group, the blocking semantics,
exit codes, launch discovery, MCP and the two transports, and PLAY.txt tells
release players about horizon-ctl.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:59:35 +02:00
Ludovic MarieandClaude Opus 5.5 601fbb533a Ship horizon-ctl in the release folders
release.yml builds horizon-ctl beside the client (checked for system-only
imports like it), packaging/package.sh copies it from beside the client binary
and refuses to package without it (the macOS folders made by hand go through
the same script), and package_native_client.py adds it to private archives.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:59:34 +02:00
Ludovic MarieandClaude Opus 5.5 772e0a7070 tools/agent_control_e2e.py: play a survival start through the CLI and MCP
On a virtual screen: create a world through the title menus, walk to a tree,
break a log, craft planks in the inventory screen, place one and read it
back, once with horizon-ctl commands and once over horizon-ctl mcp.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:57:09 +02:00
Ludovic MarieandClaude Opus 5.5 24a70e84a8 horizon-ctl: help for every command, launch from the launcher, MCP server
One command table drives horizon-ctl help, COMMAND --help (with examples)
and the MCP tools. Replies stay one JSON line; errors are error objects with
exit status 1 (game), 2 (usage) or 3 (unreachable). script runs a file or
stdin with shell-like quoting. launch finds the game beside horizon-ctl or
the newest launcher install (--version, --game), with its prepared resources
and the game home, and --wait waits for the world. horizon-ctl mcp serves
MCP over stdio in the launcher's style, one tool per command, with the
screenshot returned as an image. Existing commands and replies are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:57:09 +02:00
Ludovic MarieandClaude Opus 5.5 7bb3347edd Agent control: observe and act from the control socket
game/agent.rs adds commands an agent can play with: state, looking-at,
entities, block, blocks, find-block, inventory, screen and messages read the
game as JSON; move, jump, goto (A* over standable blocks), look-at, attack,
break, place, interact, use-item, select, drop, open-inventory, click-button,
click-at, command, respawn, pause, wait and stop act like a player. Actions
that take time run as a task advanced every frame and reply when done, with
what happened (break reports drops and pickups, place the block placed).

Buttons are clicked by label: the classic and Horizon button drawers record
what they draw each frame (widgets.rs), and a click is a synthesized pointer
move and press, so it behaves exactly like the mouse on every screen.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:57:09 +02:00
Ludovic MarieandClaude Opus 5.5 2df60cd388 Control socket: a token-guarded localhost TCP transport beside the Unix socket
Windows has no Unix domain sockets, so the control endpoint there is a random
127.0.0.1 port described by a JSON file (port and a 128-bit token, readable by
the user only); a client's first line is auth TOKEN. Linux and macOS keep the
Unix socket, and any endpoint path ending in .json picks the TCP transport, so
it is tested on Linux too. control::connect and Stream serve both.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:57:09 +02:00
Ludovic Marie e67ccd5589 Merge pull request #46 from ludovic111/launcher-014
Launcher 0.1.4: reuse prepared resources across versions; clippy and fmt
2026-10-13 21:22:29 +02:00
Ludovic Marie 97245773d1 Merge pull request #45 from ludovic111/readme
README: new banner, current screenshots, what changed in v2026.10.13.1
2026-10-13 21:11:50 +02:00
Ludovic MarieandClaude Opus 5.5 1404dd5a0a Launcher: catch up versions an older launcher installed without preparing them
Launcher 0.1.3 auto-installed v2026.10.13.1 unprepared; after updating to 0.1.4 nothing installs
it again, so install's reuse never ran for it. backend::reuse_prepared_everywhere() applies the
same reuse (same compatibility checks, copied then renamed) to every installed version that is
not prepared, oldest first. It runs when the window starts (on a thread; the page refreshes when
it is done), in the CLI's `versions` and `update`, and in the MCP list_versions and check_updates
tools. The partial folder is now named per copy, and a version prepared meanwhile is left as it is,
since the window's start and an install can copy at the same time.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:11:43 +02:00
Cosmic 870f2b45f7 Merge remote-tracking branch 'origin/main' into fix/vanilla-camera-cracks-clouds 2026-10-13 15:11:33 -04:00
Ludovic MarieandClaude Opus 5.5 8fa3eef809 Launcher 0.1.4: a new version reuses resources another installed version prepared
After installing a version (CLI install and update, the window's automatic install, MCP),
when it is not prepared and another installed version with the same Minecraft version is,
the launcher copies that version's prepared resources. Players who auto-updated to
v2026.10.13.1 no longer prepare again, and can play it without their Minecraft folder.

The prepared output depends on the Horizon version as well as Minecraft's: the manifest
records the hashes of the vanilla exporter sources it was made with, and
prepare_native_client.py writes every file and the manifest's schema. So resources are reused
only when both versions have the same pinned jars in research-lock.json, the same
prepare_native_client.py and the same exporter sources the manifest lists. They are copied
(prepare rewrites files in place, so hard links would tie the versions together), into a
partial folder renamed when complete. install and the MCP tool say when it is prepared already.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:08:06 +02:00
Ludovic MarieandClaude Opus 5.5 22756c28d8 README: retake the launcher's Play page, prepared and ready
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:07:17 +02:00
Ludovic MarieandClaude Opus 5.5 f0be91777f README: a new banner, current screenshots, what changed in v2026.10.13.1
- A banner in the website's design (Instrument Serif wordmark over a dimmed
  sunset, purple accent), rendered from docs/media/banner.html with Playwright.
- Screenshots of Horizon's own menus and graphics settings, the in-game scenes
  as WebP (from the website's media), and the launcher 0.1.3 Play and Patch
  notes pages; the JPEGs the README no longer uses are removed.
- A "What changed" section matching the v2026.10.13.1 release notes.
- Download only through the launcher (playhorizon.dev or launcher-v releases).
- Roadmap: performance optimisation, mod support and agent control.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:07:17 +02:00
Cosmic b797839f77 fix(client): follow block shapes for cracks and terrain particles
The crack overlay and particle emitters assumed a unit cube. Use selected baked model quads and projected decal UVs for cracks, outline bounds for mining crumbs, and per-box density for the destruction burst. Keep translucent overlays after translucent terrain.

Distinguish model offsets from outline offsets and preserve double-precision shape coordinates. Add regression tests and actual-client differential oracles: 2,740 model cases and 2,740 particle cases, each passing three runs after the upstream merge. Particle enqueue positions match exactly; model max error is 1.40395e-7. Offline gate, camera/first-person/cloud comparisons and Vulkan smoke checks pass.
2026-10-13 15:06:46 -04:00
Ludovic MarieandClaude Opus 5.5 3a522af067 Launcher: fix clippy's 7 warnings (unused re-exports, complex markdown types, large Err in send closures)
Behaviour is unchanged: the threads still ignore a closed channel.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:06:39 +02:00
Ludovic MarieandClaude Opus 5.5 c989692bd9 Launcher: cargo fmt (formatting only)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:06:31 +02:00
Ludovic MarieandClaude Opus 5.5 a96580aa2e Tests: the supervise trial-merge test sets its own git identity (CI runners have none)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 21:06:28 +02:00
Ludovic Marie cfdcd7f7eb Merge pull request #44 from ludovic111/website
Website: playhorizon.dev, in the launcher's design language
2026-10-13 21:01:55 +02:00
Cosmic 7f7cdf01c2 Merge remote-tracking branch 'origin/main' into fix/vanilla-camera-cracks-clouds 2026-10-13 14:51:09 -04:00
Ludovic MarieandClaude Opus 5.5 6cd64ddcae Website: let the page fetch its own origin (robots.txt checks) and preconnect to GitHub
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:48:10 +02:00
Ludovic MarieandClaude Opus 5.5 f4719d974d Website: the social card keeps its text clear of the sun and names playhorizon.dev
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:47:03 +02:00
Ludovic MarieandClaude Opus 5.5 4ecb4c85e7 Launcher: use HORIZON_GITHUB_TOKEN for GitHub's API when given; CI passes its own
Shared CI runners hit GitHub's anonymous rate limit in the smoke test (launcher 0.1.2's
macOS build failed twice on it). Players never set the variable, so nothing changes for them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:46:36 +02:00
Ludovic MarieandClaude Opus 5.5 189119a861 Website: a cinematic one-page site in the launcher's design language, on playhorizon.dev
The launcher's palette, violet accent, Instrument Serif and Geist, without its sidebar
and settings rows: a full-viewport hero over Horizon's own sunset (slow drift,
parallax, grain), then sections for what it is (a statement that lights up as it
scrolls), a screenshot mosaic, the parity count and a grid of the 14 subsystems, the
launcher beside Horizon's own menus, the latest patch notes, the roadmap, community
and the footer. Reveals, staggered letters and magnetic buttons stop under
prefers-reduced-motion; a translucent top bar and a full-screen phone menu replace
the sidebar.

playhorizon.dev: canonical, og:url, absolute og/twitter images, sitemap.xml and its
robots.txt line, and a 301 from *.up.railway.app (Railway's healthcheck host is still
served).

The full-page screenshots are no longer committed (about 17 MB): `npm run shots`
writes them to the gitignored shots/. The unused blurred background is gone; LEGAL.md
lists the hero and the settings screenshot.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:46:19 +02:00
Ludovic Marie 3738c876bc Merge pull request #43 from ludovic111/domain
Add the playhorizon.dev website link
2026-10-13 20:40:03 +02:00
Ludovic MarieandClaude Sonnet 5.5 1c0a47e012 Website: playhorizon.dev in the README, docs, PLAY.txt and the launcher (0.1.3)
links.json gains a website key; the launcher shows a quiet Website link under
Join Discord and lists it in the links CLI command and MCP tool.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 20:35:22 +02:00
Ludovic Marie 2518075339 Merge remote-tracking branch 'origin/prepare-fix' into parity-base 2026-10-13 20:20:20 +02:00
Ludovic MarieandClaude Opus 5.5 6d7f11feb2 Prepare: require only this platform's libraries; accept republished 26.3 manifests
lab.prepare imported every client library in the version JSON, ignoring
its OS rules, so a Linux install failed on the macOS-only
java-objc-bridge the official launcher never downloads there. The rule
evaluation moves from runtime.py into lab.py and one selector,
client_library_artifacts, now serves preparation, the runtime and the
model baking harness: OS rules as the launcher applies them, and the
natives for this architecture (classifier suffixes, plain natives being
the x64 build only when an ARM variant is listed). Required libraries
are still checksummed and a missing one still errors.

Mojang republished 26.3.json twice (702fe591, then 11f1aefe, the current
one) with only assetIndex changed: non-English translations, same jars
and libraries. The lock pins the current file and accepts both earlier
ones; preparation takes the launcher's copy so it matches the asset
index installed with it, and an unknown republish errors clearly.
Fixes #41

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:20:17 +02:00
Cosmic 17f0029d08 Fix vertical camera flip, breaking crack blending and cloud face culling 2026-10-13 14:04:01 -04:00
Ludovic MarieandClaude Opus 5.5 f53f198f03 Website: one static page in the launcher's design, for Railway
website/ holds Horizon's site: the horizon-theme tokens and bundled fonts, the
launcher's sidebar, rows, buttons and segmented control, over Horizon's own frozen
landscape. The parity table, harness count and roadmap are generated from the README
at build time; releases, patch notes, the roadmap and links.json are refreshed in the
browser from GitHub, with the build's copy as fallback. The download button picks the
newest launcher-v* asset for the visitor's OS.

Legal: the Minecraft disclaimer in the hero, footer and 404; no Minecraft logo or
wordmark; no game files; the launcher's background (licence unconfirmed) and the
screenshots showing it are left out; LEGAL.md lists every asset and its licence. No
cookies, analytics or third-party assets.

Railway: root directory website, Dockerfile (Node build, Caddy on $PORT with a strict
CSP). Checked with Playwright at 360-1920 px and 1250x700 (docs/widths/); Lighthouse
96/100/96/92 on mobile, 100/100/96/92 on desktop.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 20:03:56 +02:00
Ludovic Marie 383afd81eb Merge remote-tracking branch 'origin/graphics' into parity-base 2026-10-13 18:55:46 +02:00
Ludovic MarieandClaude Opus 5.5 3f3f294c52 Merge origin/main: game-bugs and launcher 0.1.2
Villager POI search: main's per-search state classification replaces this
branch's state table (same sections skipped, same positions in order).
status keeps main's mob and block-entity counts and this branch's pending
uploads.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 18:41:36 +02:00
Ludovic MarieandClaude Opus 5.5 b6ee20d0e8 Graphics benchmark results: baseline against 9006566b on the RTX 4080 and lavapipe
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 17:50:18 +02:00
Ludovic MarieandClaude Sonnet 5.5 85851909d6 launcher CI: the game's Linux build failing its checks is a warning, not a launcher failure
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 17:38:41 +02:00
Ludovic MarieandClaude Sonnet 5.5 929fa4ec5a Launcher 0.1.2: Discord link, auto-install on by default, menu style setting, smoke tests
- links.json on main gives the Discord and sponsor links (built-in fallback offline,
  empty hides the button); 'links' command and MCP tool.
- Install new versions automatically is on unless explicitly turned off (new settings
  key, so 0.1.1's written default does not count as a choice).
- Settings: Horizon / Classic menu style, the horizon.txt menuStyle line the game reads;
  'menu-style' command and MCP tool.
- launcher workflow: install latest into a temp home, check imports (Windows, Linux client)
  and that the client starts, on all three platforms; also runs on launcher-* branches.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 17:27:31 +02:00
Ludovic MarieandClaude Opus 5.5 9006566bbd Graphics docs and screenshots for the Video section of the Horizon options
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 17:21:40 +02:00
Ludovic MarieandClaude Opus 5.5 73ca04b10d Merge origin/main: Horizon menus; graphics settings in the Video section
The Horizon options shell's Video section now holds the graphics settings:
a Simple / Advanced switch (remembered in horizon-graphics.txt), then the
level's rows, each with its frame-time cost and one-line description
(ui_theme::described_row). Horizon settings draw as switches, sliders or
value buttons like vanilla options. The Classic style keeps the Video
Settings buttons to the same screens. Main's menu blur and the world's
resolution-scale pass are separate (post.wgsl, world_post.wgsl).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 17:17:43 +02:00
Ludovic MarieandClaude Opus 5.5 9dc0803a24 Graphics benchmark: games run with HORIZON_NO_AUDIO=1
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 17:12:30 +02:00
Ludovic Marie 87733155b3 Merge remote-tracking branch 'origin/game-bugs' into parity-base 2026-10-13 17:11:28 +02:00
Ludovic MarieandClaude Opus 5.5 7f1e197428 Section arena in pages; graphics docs and benchmark comparison
At render distance 32 the single section arena grew past the 4 GiB buffer
limit and the renderer panicked. Sections now live in pages of at most
256 MiB (or the device's buffer limit); draws keep their order and bind each
page once per run of consecutive draws in it, so translucent sections stay
back to front. docs/graphics.md describes the settings, the benchmark and
what changed; graphics_bench.py --compare prints a before/after table and
keeps each game's log.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 17:10:07 +02:00
Ludovic MarieandClaude Opus 5.5 9bc1425177 Villagers: find POIs without reading every block of a 48-block sphere
AcquirePoi scanned every block within 48 of the villager (about 460,000),
naming each with string matches, every 20 to 40 ticks for each villager missing
a home, job site or meeting point. Villages gain such villagers over time
(babies, more villagers than beds), so the game thread's work grew with play
time: in a village, 18% of samples at the start and 30-42% eight minutes on,
frame rate dropping and staying low.

Block states are classified once per search, and 16^3 sections whose palette
holds no POI block are skipped whole (PoiManager only visits sections with
records). The same positions are visited in the same order, so the result,
ties in the distance sort included, is unchanged. Same session after: 18%
throughout, frames at the vsync cap.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 16:58:33 +02:00
Ludovic MarieandClaude Opus 5.5 ad9cd6c67e Resolution scale, FXAA and mipmap levels
With a resolution scale other than 100% or FXAA on, the world renders into
its own target at the scaled size and one full-screen pass copies it
(bilinear) or anti-aliases it (FXAA 3.11) onto the screen; the hand, screen
effects and HUD stay at full resolution. Off, the world renders straight to
the screen as before. Vanilla's Mipmap Levels option now limits the mip
levels block textures sample (the default 4 is the full chain, as before).
Both are in the Advanced screen.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 16:44:20 +02:00
Ludovic Marie ef4fc67f1b Merge remote-tracking branch 'origin/menus' into parity-base 2026-10-13 16:39:24 +02:00
Ludovic MarieandClaude Opus 5.5 e0283c70db Graphics settings, Simple and Advanced, with a performance overlay
Video Settings opens two Horizon screens (graphics_ui): Simple has the
Performance / Balanced / Quality / Ultra presets with render distance, FOV,
max framerate, VSync and GUI scale; Advanced groups every knob under
Rendering, Quality, Display, Performance and Overlay. Each row shows a
one-line description and its frame-time cost, and applies live. Layout lives
in graphics_ui, every colour, size and widget call in graphics_style, so a
menu theme can restyle them in one place.

Horizon-only knobs (horizon-graphics.txt, never options.txt): preset, cave
culling, chunk updates and upload budget per frame (nearest sections first),
sky, fog, weather, animated textures, present mode, frame pacing, worker
threads and the performance overlay (FPS, frame/CPU/GPU times and a
frame-time graph). Defaults keep vanilla's rendering; vanilla options keep
their options.txt keys.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 16:37:31 +02:00
Ludovic Marie c2c7614a2f Merge remote-tracking branch 'origin/feel' into parity-base 2026-10-13 16:28:56 +02:00
Ludovic MarieandClaude Opus 5.5 ad701d73d9 Fewer stalls: region writes on a writer thread, culled entities, villager POI scans skip empty sections
- Unloaded chunks and entity chunks are encoded and written by a background
  region writer, in order; loads see queued records first, and synchronous
  saves wait for the queue. Deleting entity chunks a region doesn't hold no
  longer rewrites the region file.
- Mobs render within Entity.shouldRenderAtSqrDistance (64 x bounding-box size
  x entity distance) and inside the view frustum (EntityRenderer.shouldRender);
  block entities outside the frustum are skipped, beams and structure blocks
  excepted.
- Minecarts and dropped items tick only in entity-ticking chunks, like mobs.
- Villager POI searches skip sections whose palette has no POI block.
- Streaming bookkeeping uses the Fx hash and checks a column's light
  readiness once per frame instead of once per dirty section.
- HORIZON_SPIKES=MS prints the timed spans of slow frames; frame summaries
  give the phase split of the slowest 1%.

RD 32 village flight on the 4080: 81 -> 230 fps; 1% low 5.8 -> 18.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 16:14:57 +02:00
Ludovic MarieandClaude Opus 5.5 1a9452d408 Memory: drop late chunks whole, bound the decoded sounds, count what stays resident
A column that finished loading or generating after the player moved out of
range was dropped, but its block entities and saved entities were added to the
world first. The entities spawned in a column that never became resident, so
nothing saved or removed them: travelling, mobs piled up (141 to 5,028 in an
8-minute flight), and when the column loaded later its entities spawned again,
so villages near the view edge doubled their villagers. Such a column is now
dropped with everything in it. Mesh results for a column unloaded meanwhile are
discarded too, rather than uploaded with nothing left to remove them.

Decoded static sounds were kept for the whole session: every sound heard, up to
1.4 GiB of samples, and a village plays hundreds. They now stay within 64 MiB,
least recently used out, and are decoded on a thread of their own instead of the
game loop (vanilla's buffers load asynchronously too). Stopping a source that
is still waiting for its sound stops it, as alSourceStop does, so a late decode
cannot start it.

status reports mobs, block entities, resident GPU sections and the sound
engine's tables, for soak tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 16:10:32 +02:00
Ludovic MarieandClaude Opus 5.5 66e41ed573 Satisfy clippy in the hand module
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:40:09 +02:00
Ludovic MarieandClaude Opus 5.5 72542a89e2 Compare sprint-jumping with vanilla in the sprint scene
The --sprint-input scene drives the real LocalPlayer.aiStep sprint and
jump path from keyboard state. Add sprint-jump runs: sprint held or
started by double-tapping forward, jump tapped, held through landings or
pressed first, at five headings, with too little food to sprint, under a
two-block ceiling and up onto a slab. All 293,175 states match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:38:48 +02:00
Ludovic MarieandClaude Opus 5.5 45bd1a7be8 Renderer and tick performance: section arena with indirect multi-draw, dense occlusion graph, entity ticking within the simulation distance, fast chunk-map hashing
- Terrain sections live in one vertex arena (first-fit free list, grown on the
  GPU) and draw with one multi_draw_indexed_indirect per pass instead of a
  buffer bind and draw per section; per-frame scratch vectors are reused.
- The SectionOcclusionGraph search runs over dense arrays around the camera
  instead of hash sets, with per-column visibility.
- Mobs outside the entity-ticking chunks (Chebyshev distance of the
  simulation distance, DistanceManager.inEntityTickingRange) only check
  despawning, as in ServerLevel.tick; before, every loaded mob ticked.
- World chunks use the Fx hash; sky darkening is sampled once per time and
  weather instead of once per mob; creaking-heart scans compare state ids.
- Horizon-only graphics settings (horizon-graphics.txt): frame pacing without
  spinning, present mode, animated textures, worker threads.

RD 32 village flight on the 4080: 3.1 -> 81 fps.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:34:48 +02:00
Ludovic MarieandClaude Opus 5.5 0734daa911 Swing the hand and raise it as vanilla does: SwingState, equip heights, attack clicks
The local player's clicks now go through a port of Minecraft.startAttack,
continueAttack and handleKeybinds' attack part with MultiPlayerGameMode's
block breaking (first_person.rs): attacking the air swings (and sets the
miss time), creative breaking swings every tick through its destroy delay,
survival mining keeps swinging after a block breaks, swords cannot break
blocks in creative, and attacking an entity in creative sets the delay.
The swing is LivingEntity.SwingState (restart rules, durations under haste
and mining fatigue, forward wrap on restart); the equip height follows
FirstPersonHandsAndItems with the item swap ticker, and placing or
starting to use an item drops the hand (itemUsed). Mining fatigue scales
by Math.pow(0.3, amplifier + 1) as in 26.3.

test_first_person_parity drives the real startAttack, continueAttack,
startUseItem, MultiPlayerGameMode breaking, SwingState, the tickers and
FirstPersonHandsAndItems over 4,192 scripted click sequences.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:33:29 +02:00
Ludovic MarieandClaude Opus 5.5 d9351ec054 Menus: Horizon-style options screen, pause polish, screenshots
Options open as the launcher's Settings page: a sidebar with the sliding
selection (Video, Audio, Controls, Accessibility, Language, Chat, Interface)
and rows with a switch, slider or value button per option
(options_horizon.rs; new sections or rows slot into SECTIONS). Key binds,
the language list and resource packs open vanilla's pages. Interface holds
Menu style (Horizon / Classic). The pause menu hides the in-game HUD over the
blurred world. Scripted and frame-limited runs default to Classic, so the
harnesses see vanilla's screens.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:33:15 +02:00
Ludovic MarieandClaude Opus 5.5 eb18bb42af Menus: Horizon style for the title, worlds, create, multiplayer and pause screens
One theme for the launcher and the game: crates/horizon-theme holds the
palette, type scale, spacing, radii, control sizes, motion and the bundled
fonts; launcher/src/theme.rs and the game's ui_theme both read it. ui_theme
ports the launcher's components (button with hover layer and press state,
sidebar list with the sliding selection, segmented control, switch, rows)
and draws Geist and Instrument Serif through the HUD atlas.

The title is laid out like the launcher (sidebar, page header, rows) over a
live backdrop: Horizon generates an ice-spikes landscape for a fixed seed,
orbits a camera over it with falling snow, then blurs and cold-grades the
frame (post.rs). The launcher's opening (wordmark, then the interface) plays
once per session and a click or key skips it. Menu style Horizon / Classic
lives in horizon.txt, never options.txt; Classic keeps vanilla's drawing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:19:14 +02:00
Ludovic MarieandClaude Opus 5.5 f2c7a2d359 Draw the first-person hand with its own projection at hudFov
GameRenderer.render3dHud sets up the hand's projection at Camera's hudFov
(70, changed only by death and fluids), never the FOV option or the
sprint, speed and bow modifier. The hand pass now has its own globals
with that projection (a port of JOML setPerspective, as Projection does).
The camera harness compares the world and hand projection matrices at FOV
options 30, 70, 110 and others with vanilla's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:07:39 +02:00
Ludovic MarieandClaude Opus 5.5 c982fadaf5 Graphics benchmark: scripted flights over four scenes at render distances 8/16/32, with CPU and GPU frame times
horizon-ctl gains 'fly' (a constant-speed camera path that replies with the
frame summary); frame summaries add CPU time per frame (waits for the GPU,
display and limiter excluded), per-phase averages and GPU time from timestamp
queries. --offscreen renders into a texture on the discrete GPU so the 4080
can be measured under the headless compositor. Baselines: lavapipe on vscreen
and the RTX 4080 offscreen, seed 1234.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:04:23 +02:00
Ludovic MarieandClaude Opus 5.5 1a10d4efe8 Windows: launcher without VCRUNTIME140.dll, a clear message without Vulkan, import checks in CI
The Windows launcher was built without crt-static and imported VCRUNTIME140.dll,
which only the Visual C++ redistributable installs: players without it got a
missing-DLL dialog before anything started. The game itself links only system
DLLs (vulkan-1.dll is loaded at run time).

- launcher.yml links the C runtime on Windows.
- tools/check_imports.py reads PE import and delay-import tables (and ELF
  loader, needed libraries and run paths); release.yml and launcher.yml fail
  when a Windows binary imports a non-system DLL.
- release.yml builds Linux on Ubuntu 22.04: the NixOS-made Linux release asked
  for a /nix/store loader, so it ran nowhere but NixOS.
- No adapter: the game says the Vulkan driver is missing and what to install,
  and on Windows keeps the console open until Enter.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:02:15 +02:00
Ludovic MarieandClaude Opus 5.5 59fd98dea4 Sound: play under the launcher's own stream name, open any sample format, say what opened
PipeWire remembers mute per application name. A test run's stream, muted once
in the mixer, left "PipeWire ALSA [horizon-client]" muted for every later game,
the release played from the launcher included: no sound at all, with the device,
the stream and the mixer all working.

- The launcher starts the game as "Horizon" (media.role Game), its own entry.
- The game opens no output on a vscreen, where agents run it (HORIZON_AUDIO=1
  forces it, for a null sink), so nobody needs to mute it again.
- Any device sample format is accepted (the mixer converts from f32): a plain
  ALSA default reporting i16 used to fail.
- Other output devices are tried when the default does not open, and the log
  names the output opened or every reason none did.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 15:02:15 +02:00
Ludovic MarieandClaude Opus 5.5 27a32cc30d README: parity is what the harnesses check, until the final audit
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 14:17:34 +02:00
Ludovic MarieandClaude Opus 5.5 8cdec2c8d9 Tidy the repository now that parity is reached: launcher-first README, docs index, research leftovers removed
Removed (each unreferenced by code, workflows, tests or living docs; no harness
dependency record names any of them, and parity.py --list still finds all 281):
- 22 one-off write-ups of the Java-pack experiments in docs/: adaptive-terrain,
  client-graphics-smoke, compact-headers, core-performance, culling-empty,
  culling-rays, debounce-queue, dispatch-retry, foreground-first,
  graphics-api-comparison, heap-budget, mac-first-test, optimization-plan,
  playable-validation, quad-reuse, server-graphics-context, shader-world-smoke,
  terrain-measurements, terrain-position, terrain-read-wait, tick-membership,
  worker-pacing. Their findings are folded into one paragraph of java-packs.md.
- 24 benchmarks/ observation dumps only those write-ups linked (client graphics,
  culling, queues, heap, Mac Vulkan, shader worlds, software identity, and the
  unlinked rust-core, rust-worldgen-2026-10-05, rust-native-client and
  rust-cuboid-model-decoding runs), plus 12 unlinked files inside kept
  report folders. The scoped-parity reports the living docs cite stay.
- debug/: one server log from a chunk investigation.
- The manual macos-shader-research and macos-vulkan-research workflows.
- tools/logs/latest.log, an empty log committed by accident (now ignored).

Kept: research-lock.json (parity.py, packaging, the launcher and datafix read
it), the Java-pack how-tos (vulkan, collectors, profiling, process-memory,
tick-state) and tools/test_client_graphics.py (ci.yml runs it).

README: leads with what Horizon is and "Download the launcher" (the
launcher-v* releases; the launcher updates itself), then build from source
for developers. Direct game downloads and PLAY.txt steps for players are gone;
the launcher has its own section with two screenshots. The roadmap merges the
known differences, the final checks and the plans after parity, under the
"Roadmap" heading the launcher's What's next page reads. The parity table and
its 100%-of-what-the-harnesses-compare note are unchanged.

docs/README.md indexes what remains: build and run, parity (status and
workflow), world generation, world data and simulation, the old Java track.
Links to the removed pages and README anchors are fixed.

packaging/PLAY.txt now speaks to players who came through the launcher and
points anyone with a bare archive to it, keeping the manual steps short.

The launcher's README link points at main instead of the launcher branch.
.gitignore: tools/logs/ and .DS_Store. No code behaviour changes; the compiler
and clippy flag no unused code and the tree has no stale TODOs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 14:16:55 +02:00
Ludovic MarieandClaude Opus 5.5 2e4c4d1861 Launcher: run the game from the saves folder, never a version folder
The client ran in the version's own folder, so saves and options.txt would have
landed there and been deleted with the version, and the saves in
~/.local/share/horizon (where the release folders' horizon.sh keeps them) were
not seen. It now runs in HORIZON_HOME, else horizon in the platform's data
folder, with --resources pointing at the version.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 14:12:16 +02:00
Ludovic MarieandClaude Opus 5.5 ed05c1970f Launcher: release workflow for launcher-v tags (Linux, macOS, Windows, draft), README for updates, CLI and MCP; quieter CLI progress
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:28:57 +02:00
Ludovic MarieandClaude Opus 5.5 6c51322171 Launcher: opening screen over the prismal background, violet accent from it, opening setting, docs frames and clip
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:27:30 +02:00
Ludovic MarieandClaude Opus 5.5 86e4a05c01 Launcher: CLI subcommands and an MCP server over stdio, both on the shared core
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:20:39 +02:00
Ludovic MarieandClaude Opus 5.5 53583b28d8 Launcher design pass: aurora background, eased page, pill, hover and bar motion, Play hero, Settings page with update state; Geist, Instrument Serif and Geist Mono
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:18:17 +02:00
Ludovic MarieandClaude Opus 5.5 55ecf5a59e Launcher core: update checks for Horizon and the launcher, self-update, install by tag, notes as plain text, tests
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:13:57 +02:00
Ludovic MarieandClaude Opus 5.5 e5e27c24d4 Launcher: backend as a shared library; game and launcher tags kept apart, numeric version order, HORIZON_LAUNCHER_HOME
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:11:00 +02:00
Ludovic MarieandClaude Opus 5.5 5a2602406b Launcher: preview screenshot
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 13:01:46 +02:00
Ludovic MarieandClaude Opus 5.5 a2fe7286c1 Launcher: README and screenshots
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:51:46 +02:00
Ludovic MarieandClaude Opus 5.5 d7bcc04064 Launcher workflow: also run on pushes to the launcher branch
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:50:59 +02:00
Ludovic MarieandClaude Opus 5.5 7ff1b97f80 Launcher: tables in notes, the README roadmap, the server's EULA, and a macOS/Windows build workflow
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:50:49 +02:00
Ludovic MarieandClaude Opus 5.5 57257ae231 Launcher: a GPUI app that installs, prepares and starts Horizon builds
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:45:05 +02:00
Ludovic MarieandClaude Opus 5.5 b279705c8d README: every subsystem matches vanilla in its harnesses (100%), audit and launch checks next
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 07:18:24 +02:00
Ludovic Marie 7d4304a840 Merge branch 'parity/leftovers' into parity-base 2026-10-13 07:07:54 +02:00
Ludovic Marie b7ced27dd1 Merge branch 'parity/server-leftovers' into parity-base 2026-10-13 06:52:25 +02:00
Ludovic Marie c6d0184353 Merge branch 'parity/screens' into parity-base 2026-10-13 06:47:44 +02:00
Ludovic MarieandClaude Opus 5.5 98ec7bc509 Edit word moves with Cmd on macOS, as InputQuirks does
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 06:38:47 +02:00
Ludovic Marie 2aa3cd5afa Merge branch 'parity-base' into parity/screens 2026-10-13 06:29:00 +02:00
Ludovic Marie b0e5fe5591 docs: pack screen session count 2026-10-13 06:28:59 +02:00
Ludovic MarieandClaude Opus 5.5 8a13322143 README: the resource pack screen and the chat input match vanilla
Assets and Menus score 1; Java parity is 93%.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 06:28:53 +02:00
Ludovic MarieandClaude Opus 5.5 436d71eba2 Compare the chat screen's input and command suggestions with vanilla
horizon_client::chat::ChatScreen is now a port of vanilla's ChatScreen,
EditBox and CommandSuggestions: the input's scrolling, cursor, selection,
word moves and select all, history up and down, argument colouring, usage
lines and parse errors, the suggestion list (sorting, hover, Tab and
Shift+Tab cycling, clicks, wheel) and its tooltips, drawn as GUI calls the
game paints. tools/test_chat_screen_parity.py drives a real ChatScreen on
vanilla's client command tree (custom suggestions answered by the server
dispatcher): 3000/3000 cases match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 06:27:55 +02:00
Ludovic MarieandClaude Sonnet 5.5 e70c9fdd69 Document the recipe book search, ghost recipe and hotbar harnesses; more old options.txt bodies
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 06:22:53 +02:00
Ludovic Marie 08eeb06eff Merge branch 'parity-base' into parity/leftovers 2026-10-13 06:22:05 +02:00
Ludovic MarieandClaude Sonnet 5.5 35f0b5ec30 Read creative toolbars (hotbar.nbt) through the HOTBAR data fixers, compared with HotbarManager
EmptyItemInHotbarFix was missing from the data fixers. horizon_client::hotbar loads the nine rows of nine stacks of an older file as vanilla does: lenient counts, unregistered items empty, stray entries dropped from their row, a row that is no list ending the reading, short rows lost and long ones cut.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 06:21:56 +02:00
Ludovic MarieandClaude Opus 5.5 639237afcc Show the ported pack screen in the game
The options' Packs page is horizon_client::pack_screen: vanilla's layout,
lists, focus and selection, search box typing, the mouse wheel per list and
the confirmation of an incompatible pack (Escape answers no). Packs carry
their raw description, compatibility (too old, too new, unknown) and icon.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 06:10:23 +02:00
Ludovic MarieandClaude Opus 5.5 a7606c4ad4 Compare the resource pack screen's drawing with vanilla
horizon_client::pack_screen ports PackSelectionScreen, its two
TransferableSelectionLists and the ConfirmScreen of an incompatible pack as
vanilla's state machine (clicks, wheel, search typing, focus, selection,
scroll) and gives its GUI calls; screen_draw holds the widgets (StringWidget,
MultiLineTextWidget, Button, a font-aware EditBox port) and StringSplitter's
line splitting with legacy codes. Pack components keep their legacy codes and
style fields. tools/test_pack_screen_parity.py runs a real
PackSelectionScreen through the same actions: 1500/1500 cases match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 06:07:04 +02:00
Ludovic Marie 2c34e0753d Merge branch 'parity/menus-golem' into parity-base 2026-10-13 05:59:38 +02:00
Ludovic Marie 27d18063a8 Merge branch 'parity/save-roundtrip' into parity-base 2026-10-13 05:49:27 +02:00
Ludovic MarieandClaude Opus 5.5 7c8afc8a34 Merge branch 'parity-base' into parity/server-leftovers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 05:44:19 +02:00
Ludovic MarieandClaude Opus 5.5 0a2601c33a Send recipes, advancements and command replies to players as vanilla does
- ClientboundUpdateRecipesPacket at join: the recipe property sets and the
  stonecutter's recipes, from the data pack (lan/recipes.rs).
- On a player's first tick the minecraft:tick criteria are met: the recipes
  their advancements grant go out in ClientboundRecipeBookAddPacket, then
  ClientboundUpdateAdvancementsPacket with what the player may see
  (lan/advancements.rs).
- Command replies reach remote players as the components vanilla sends:
  Text keeps the Component it was built from (literal, translatable,
  siblings, style), sendFailure wraps the message as vanilla does, and the
  NBT wraps the elements of mixed lists.

The dedicated-server harness drops its known gaps: it compares these
packets (sorted where vanilla's hash maps order them per run) and the
replies to three failing commands, keeps only the first set_time among the
joining packets and turns random ticks off in the generated world.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 05:43:51 +02:00
Ludovic MarieandClaude Sonnet 5.5 b28fcec7f0 Compare the ghost recipe of a recipe book click with the vanilla client's
Book::ghost is the one place that places a recipe's ingredients into the grid or furnace slots; the harness runs fillGhostRecipe against the real menus. Fixes found: the result and the dyed, potion and map demo ingredients cycle through every stack (not the first), a furnace's fuels follow the registry's component lookup, and items keep their registry order.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 05:43:31 +02:00
Ludovic Marie d6fd90a347 Merge branch 'parity-base' into parity/menus-golem 2026-10-13 05:36:44 +02:00
Ludovic MarieandClaude Sonnet 5.5 23d7ebdfaa Search the recipe book as vanilla's FullTextSearchTree does, over the full tooltip lines of every result
The recipe book view harness now searches: names, parts of names, ids with a colon, odd texts.
Horizon's recipe tooltips lacked attribute modifiers, smithing template, potion, dyed, pot, rocket and disc lines, and the results a display cycles through (map copies, tipped arrows, dyed armour).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 05:35:49 +02:00
Ludovic Marie 6b6506a65a Merge branch 'parity/platform-maths' into parity-base 2026-10-13 05:22:43 +02:00
Ludovic Marie 765f53b2ba Merge branch 'parity-base' into parity/platform-maths 2026-10-13 05:15:09 +02:00
Ludovic MarieandClaude Opus 5.5 e70c38e578 Send the command tree in vanilla's registration order
The LAN and dedicated servers built the tree from the data generator's
commands report, which sorts each node's children. lan/command_order.rs,
generated from vanilla's Commands(CommandSelection.ALL) by
tools/generate_lan_command_order.py, gives the registration order, and the
dedicated-server harness now compares the tree in order (the game rules,
registered in an identity-hashed order, aside).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:59:34 +02:00
Ludovic Marie 41c4f2247e Merge branch 'parity-base' into parity/menus-golem 2026-10-13 04:48:24 +02:00
Ludovic MarieandClaude Opus 5.5 8976bd37d4 Select resource packs as vanilla's PackSelectionModel does, compared with vanilla
horizon_client::packs::SelectionModel ports PackRepository's selection and
PackSelectionModel (default positions, fixed and required packs, moving up
and down, commit), and the pack screen uses it. The new pack_selection
harness drives vanilla's model and Horizon's through 4,000 random action
sequences; every state matches.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:47:36 +02:00
Ludovic Marie 708a162090 Merge branch 'parity-base' into parity/save-roundtrip 2026-10-13 04:40:01 +02:00
Ludovic MarieandClaude Opus 5.5 66114adfd9 save_roundtrip: promote only the fields a full chunk saves differently
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:40:01 +02:00
Ludovic Marie 2756b55b5b Merge branch 'parity/old-saves' into parity-base 2026-10-13 04:37:51 +02:00
Ludovic MarieandClaude Opus 5.5 b1a560264d jmath: rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:33:20 +02:00
Ludovic MarieandClaude Opus 5.5 4ce4e983e7 jmath: rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:33:03 +02:00
Ludovic MarieandClaude Opus 5.5 7826a221c5 jmath: satisfy clippy (fdlibm's constants and NaN idiom, verbatim)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:32:48 +02:00
Ludovic MarieandClaude Opus 5.5 ed1ea50c8e Merge parity-base into parity/platform-maths
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:31:39 +02:00
Ludovic MarieandClaude Opus 5.5 b15db4749f Net harness client: wait for each chat reply instead of 1.5 s
On a busy machine the /list reply sometimes came after the client had
left. Each step now waits for a new chat line, up to 15 s.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 04:04:17 +02:00
Ludovic MarieandClaude Opus 5.5 85242053e2 save_roundtrip: accept the promotion of vanilla's border proto chunks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:59:11 +02:00
Ludovic Marie 8e26af99a1 Merge remote-tracking branch 'origin/parity/spawn-gear' into parity/save-roundtrip 2026-10-13 03:54:23 +02:00
Ludovic MarieandClaude Opus 5.5 4078118c71 Generate superflat worlds with their layers (FlatLevelSource)
Horizon generated noise terrain in minecraft:flat worlds. Since chunk
streaming finishes the corners of the spawn neighbourhood, save_roundtrip's
flat test world got four noise chunks where vanilla had saved flat proto
chunks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:54:23 +02:00
Ludovic MarieandClaude Opus 5.5 7322bba2b5 dedicated_server: read the game time as the console prints it
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:51:40 +02:00
Ludovic Marie df18d60d14 Merge branch 'parity/warden-sculk' into parity-base 2026-10-13 03:45:25 +02:00
Ludovic Marie ab0d708f87 Merge branch 'parity-base' into parity/menus-golem 2026-10-13 03:43:32 +02:00
Ludovic MarieandClaude Opus 5.5 4093112bb6 Update the README for player skins, the focused chat and copper golem sorting
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:43:32 +02:00
Ludovic MarieandClaude Opus 5.5 75336660bb Compare the focused chat with vanilla
The HUD harness's chat cases now also draw the chat as the open chat
screen does: foreground, at the focused height, scrolled, with the scroll
bar.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:42:57 +02:00
Ludovic MarieandClaude Opus 5.5 71e677ed6a dedicated_server: settle the generated world in game ticks, without random ticks
The world was saved 20 wall-clock seconds after force-loading the area, so
on a busy machine chunks were still generating or their fluids flowing,
and random ticks changed blocks while the client was being sent its
chunks: which chunks differed varied from run to run. Wait until every
force-loaded chunk is loaded and 600 game ticks have passed, with
random_tick_speed 0.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:40:50 +02:00
Ludovic MarieandClaude Opus 5.5 a9fa46fd0a Run the copper golem on CopperGolemAi's brain and compare its chest sorting
The golem's goals are replaced by vanilla's brain (core and idle activities,
the transport cooldown, look-at-player-sometimes, stroll or wait), and
TransportItemsBetweenContainers moves into the library: nearest wanted
chest in chunk and block entity map order, queueing behind golems with a
chest open, the 60-tick interaction with its states, sounds and opener
counts, picking up and putting down (with vanilla's overcounting), visited
and unreachable positions. Weathering draws from the level random after the
living tick; the spin sound is client-local. mob_ai gains seven copper golem
scenarios that print each golem's state, hand and opened chest and every
chest's contents and openers; all match vanilla.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:40:13 +02:00
Ludovic Marie 9ac6d665fb Merge branch 'parity/rendering-gaps' into parity-base 2026-10-13 03:32:19 +02:00
Ludovic Marie 9b1c29463b Test: worlds from 1.12.2 and 1.16.5 are upgraded on opening 2026-10-13 03:29:13 +02:00
Ludovic Marie 2db50eeca1 Merge branch 'parity-base' into parity/old-saves 2026-10-13 03:27:26 +02:00
Ludovic Marie 3d20af9a9c Datafix: every server fix ported; saves without a DataVersion upgrade from -1 2026-10-13 03:27:20 +02:00
Ludovic Marie 1ded8799fc Merge branch 'parity/spawn-gear' into parity-base 2026-10-13 03:18:39 +02:00
Ludovic MarieandClaude Sonnet 5.5 8c818c6f84 1.8.9 world: real maps by right click, objectives its scoreboard knows
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 03:17:12 +02:00
Ludovic MarieandClaude Opus 5.5 585a41acfa Satisfy clippy in the SHA-1 helper
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:17:04 +02:00
Ludovic MarieandClaude Opus 5.5 19d4146f04 Draw player list heads from players' skins as vanilla does
Profiles' textures properties are unpacked as authlib does and looked up
as SkinManager does (signatures, the local player, allowed texture URLs,
downloads), skins are fetched and processed as SkinTextureDownloader does
and shown from atlas slots. The tab_list harness now runs a real
SkinManager and compares processLegacySkin over 400 PNGs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:16:04 +02:00
Ludovic Marie 991df3d23c Merge remote-tracking branch 'origin/parity/old-saves' into parity/old-saves-flat 2026-10-13 03:13:32 +02:00
Ludovic MarieandClaude Sonnet 5.5 19802a4a65 Keep what the schema of the data did not know untyped, read the legacy data again at 1.14
DataFixerUpper reads the data once with its own schema: an entity tree of an id that
schema lacks stays untyped for good, and a list of trees is typed only if all of them
are. Spawner potentials follow that, the spawner wrapping skips untyped data, and a stack
without a string id is an empty equipment slot. The raw maps entities remember are taken
again where the fixes of before 1.14 end.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 03:13:32 +02:00
Ludovic MarieandClaude Opus 5.5 6aa875c6c2 Compute the breeze's long-jump vector with jmath; run every harness on the Mac
The Mac mini no longer excludes options, chunk_generation,
world_border_render and mob_ai: their float maths now matches vanilla's
on Apple silicon.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:13:05 +02:00
Ludovic MarieandClaude Opus 5.5 ab9109c787 Route world generation's and mob AI's Math calls through jmath
Beardifier, density pow/log, Marsaglia's Gaussian, dripstone, ores, fancy
trunks, icebergs, end spikes, strongholds, note pitches, sculk charge
particles, the warden's and brains' weighted shuffles.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:06:48 +02:00
Ludovic MarieandClaude Opus 5.5 558d140fca Compute Math.sin/cos/pow/log10 as HotSpot does on the host architecture
Rust's float functions use the platform libm, and vanilla's own Math
results differ between x86-64 (Intel stubs, close to glibc) and AArch64
(fdlibm, with sin/cos evaluated using fused multiply-adds). jmath picks
the same implementation HotSpot uses on the machine, so options, the
world border's alpha and RandomPos match vanilla on an Apple silicon Mac
as well as on Linux.

The vanilla protocol client no longer records the game-time sync sent
every 20 ticks: whether one arrives before the first chunk batch depends
on when the client joined.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:05:34 +02:00
Ludovic MarieandClaude Opus 5.5 811e4ff6de Merge parity-base into parity/warden-sculk
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:03:24 +02:00
Ludovic Marie 085cca6aa4 Merge branch 'parity/rendering-gaps' into parity-base 2026-10-13 03:02:44 +02:00
Ludovic Marie 9c3e98403d Merge branch 'parity/spawn-gear' into parity-base 2026-10-13 03:02:44 +02:00
Ludovic MarieandClaude Opus 5.5 8dc1859369 Merge branch 'parity-base' into parity/spawn-gear
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:02:28 +02:00
Ludovic Marie b8ee0b27b3 Datafix harness: pre-1.17 worlds in worlds-pre-1.17, which other worktrees' harnesses do not read 2026-10-13 02:54:04 +02:00
Ludovic Marie 1705653912 Datafix harness: worlds saved before 1.17 stay in the branch's own .local until integrated 2026-10-13 02:53:54 +02:00
Ludovic Marie 360ddcbdba Merge branch 'parity/villager-social' into parity-base 2026-10-13 02:53:42 +02:00
Ludovic Marie e4f4f57e9b Merge branch 'parity/render-distance' into parity-base 2026-10-13 02:53:42 +02:00
Ludovic MarieandClaude Sonnet 5.5 b7aa3b0d07 1.10.2 world: no thrown potions or 1.8 zombie villagers (vanilla fixes cannot handle them)
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 02:44:39 +02:00
Ludovic MarieandClaude Sonnet 5.5 c46ac98b1a Port the fixes of 1.9 to 1.12 (keys 100 to 820) and read names and arrays like DataFixerUpper
Entity, block entity and item schemas below 1.11 (CamelCase ids, Equipment, Riding,
numeric item ids), their read hooks, and the fixes: equipment, item ids, potions, spawn
eggs, spawners, minecarts, UUIDs, health, saddles, paintings, riding, signs and books,
the 1.10 splits, id namespacing, banners, shulkers, totems. 1.11.2 passes the bands
1343 and 1631.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 02:33:59 +02:00
Ludovic MarieandClaude Sonnet 5.5 43155d7822 Sample world for 1.11.2, and 1.8.9 to 1.10.2 in the version list
datafix_scene_12.py builds one scene for 1.8 to 1.12 from per-era tables (blocks, entity ids and merged types, riding, equipment, potions, items probed on the server, achievements by command instead of advancements).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 02:32:43 +02:00
Ludovic MarieandClaude Opus 5.5 5e48972bff README and docs: the recipe book's drawing, the loom's banner preview and End gateway beams match vanilla
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 02:26:40 +02:00
Ludovic MarieandClaude Opus 5.5 eec52f9055 The recipe book draws as vanilla's widgets do; test_recipe_book_render_parity
horizon_client::recipe_book_screen lays out RecipeBookComponent's drawing
(background, search EditBox, tab buttons, the filter CycleButton, the page
of RecipeButtons with its number and arrows, the alternatives overlay,
tooltips) and GhostSlots as vanilla's GUI calls with their poses, and the
game paints them. The new harness builds vanilla's widgets for 600 random
states (VanillaRecipeBookScreenOracle) and compares every call: 600/600.

Ingredients keep their HolderSet order (tags in TagLoader order), which is
how the overlay and ghost slots cycle; the book centres over the menu on
narrow screens as widthTooNarrow does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 02:22:55 +02:00
Ludovic MarieandClaude Sonnet 5.5 ba20b8eb29 Port the fixes of 1.11.2 to 1.12 (keys 1022 and 1125): shoulder entities, bed block entities, bed item colour
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 02:05:39 +02:00
Ludovic MarieandClaude Opus 5.5 d9054baf44 The loom's result preview draws vanilla's banner flag picture in picture
GuiBannerResultRenderer's flag model and pattern layers, lit with
Lighting.Entry.ITEMS_FLAT and clipped to the 20x40 rectangle, through the
GUI item pipeline. The block entity render harness gains loom result cases
(the oracle submits vanilla's renderToTexture under the PiP pose): 407/407.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 02:03:08 +02:00
Ludovic MarieandClaude Sonnet 5.5 1efc825a75 Merge parity/old-saves into parity/old-saves-flat
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 02:00:29 +02:00
Ludovic MarieandClaude Sonnet 5.5 39cacbdf83 Rich 1.12.2 sample world and a flat one for the DataFixer harness
tools/datafix_scene_12.py builds it in 1.12 command syntax: the whole block id/data space, block entities, items, entities, player, scoreboard, advancements, maps and statistics (real ones from a bot, plus a few hand-written fixtures).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 01:59:37 +02:00
Ludovic MarieandClaude Opus 5.5 acdbb3d27a End gateways tick their beam in game: client beamAnimationTick beside the server copy's portalTick
The anim harness now runs vanilla's TheEndGatewayBlockEntity on a client and
a server stand-in (triggerCooldown every 2400 ticks and on entry, block event
1) and compares the beam render state; 40 cases match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:55:46 +02:00
Ludovic MarieandClaude Opus 5.5 2b1981acbb Drop a stale warden memory test and collapse the fixture's seeding ifs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:45:07 +02:00
Ludovic Marie 7011c5cddd Merge branch 'parity/dedicated-server' into parity-base 2026-10-13 01:44:30 +02:00
Ludovic MarieandClaude Sonnet 5.5 955f2be4ae Flattening fixes: numeric block names normalised by the chunk rewrite, unknown entities stay untyped, spawn egg default; band harness also upgrades the old saved data
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 01:26:43 +02:00
Ludovic MarieandClaude Opus 5.5 5565cc3a41 Give player-less mob AI scenarios the oracle's far-away player
The oracle's player stays 5000 blocks east between scenarios, and
Mob.checkDespawn draws for it once a mob idles past 600 ticks
(warden_alone).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:26:25 +02:00
Ludovic MarieandClaude Opus 5.5 7b55319171 lan_bot: the status description is a bare string, as vanilla writes it
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:16:23 +02:00
Ludovic MarieandClaude Opus 5.5 8c784eaaa6 Ignore mob step game events in the game, whose sculk layer tracks steps
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:15:26 +02:00
Ludovic MarieandClaude Opus 5.5 42cdea74be LAN discovery as vanilla's list keeps it; test_lan_parity against LanServerPinger and LanServerDetection
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:11:55 +02:00
Ludovic MarieandClaude Opus 5.5 de3a285cb3 Headless Horizon client joining a vanilla dedicated server, checked by the harness
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:07:19 +02:00
Ludovic MarieandClaude Opus 5.5 7fdbdcb3cb Warden footsteps and hearing, kills in the probe, and the ghastling's fly stroll
- Warden.nextStep: a step every 0.55 walked; mob steps raise a step
  game event, which the mob AI probe delivers to wardens through the
  listener the game uses (warden::listen).
- Warden.tick runs the vibration ticker before super.tick.
- The probe applies melee hits on mobs, reads a warden's target from its
  brain, and plays the player's death sound for a lethal hit; warden_player
  and warden_cow stop before the killing blow.
- getViewVector(0) uses the head's previous yaw, and AirAndWaterRandomPos
  the float quarter turn: tempted ghastlings stroll as vanilla's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:06:33 +02:00
Ludovic MarieandClaude Opus 5.5 6f84b9ae94 Harness names differing chunks; spawner update tags without keepPacked
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 01:02:14 +02:00
Ludovic MarieandClaude Opus 5.5 5f5b6119d2 Spawner update tags in chunk packets; harness lists recipes and advancements as known gaps
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:57:10 +02:00
Ludovic Marie 67caf1d2ab Datafix scene: boss bar, scoreboard, team and a trip to the nether and the end for worlds before 1.17 2026-10-13 00:54:43 +02:00
Ludovic MarieandClaude Opus 5.5 4d62899a10 Harness: force-load the spawn area so both servers serve full chunks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:52:35 +02:00
Ludovic MarieandClaude Opus 5.5 3f4c39b057 Satisfy clippy
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:52:12 +02:00
Ludovic MarieandClaude Opus 5.5 5ce4b9585d Satisfy clippy
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:51:30 +02:00
Ludovic MarieandClaude Opus 5.5 0425843aa8 Note finalizeSpawn's parity in the README
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:50:50 +02:00
Ludovic MarieandClaude Opus 5.5 389d2f9549 Adopt only villagers and creakings born during a mob_ai scenario
Animal babies and dropped items stay out of the comparison, as before the
merge: the probe does not model them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:50:18 +02:00
Ludovic Marie c8370d8e29 Merge branch 'parity/old-saves-flat' (1.12.2 to 1.13.2 fixes) 2026-10-13 00:48:14 +02:00
Ludovic MarieandClaude Opus 5.5 1ea26de544 Match finalizeSpawn for every case of the harness
A zombie villager's profession comes from its constructor's random, not
the one finalizeSpawn draws from. Allays and withers are no longer marked
persistent to escape despawning: they are kept as removeWhenFarAway and the
wither's checkDespawn keep them, and canPickUpLoot follows the allay's and
the sulfur cube's overrides. A sulfur cube's size sets its attribute
bases, and strength and speed effects count in attribute values. The
oracle's stand-in level gets the sound seed random Level.playSound draws
from.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:47:25 +02:00
Ludovic Marie 951b43daac Datafix worlds: world type variants for the level.dat generator settings 2026-10-13 00:46:45 +02:00
Ludovic MarieandClaude Opus 5.5 89d5b27b4c Dedicated server: chunk centre in placeNewPlayer, first-tick entity data; harness normalises vanilla's run-to-run orders
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:44:18 +02:00
Ludovic MarieandClaude Opus 5.5 85e43462ac Block entity order as vanilla's chunk map iterates; chunk comparison without light values
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:37:51 +02:00
Ludovic MarieandClaude Opus 5.5 7878013342 Merge parity-base into parity/spawn-gear
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:37:27 +02:00
Ludovic Marie 26462a168b Datafix worlds: 1.15.2 and 1.16.1; scene entries by save format 2026-10-13 00:36:05 +02:00
Ludovic MarieandClaude Sonnet 5.5 b5a6b6a99e Port LegacyStructureFileFix (1493) and run the file fixes of the range in the band harness
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 00:35:54 +02:00
Ludovic MarieandClaude Opus 5.5 52a419ac31 Match villager births and footsteps on bed edges
The parent's half of VillagerMakeLove.tryToGiveBirth (eating, the child's
bed and type, resting) runs in its own tick, before it ages; the partner's
follows as an event. A baby's NearestBedSensor keeps its bed when the
reused path heads elsewhere, as vanilla checks for a POI there. Footsteps
come from the block under the feet (Entity.mainSupportingBlockPos), not
the column below the centre. The oracle faces newborns' heads with their
bodies (LivingEntity draws the head yaw from Math.random), and the breeding
scenarios leave one free bed per section (PoiManager hands them out in hash
order).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:35:40 +02:00
Ludovic MarieandClaude Opus 5.5 7ede56b596 Dedicated server: vanilla console lines, player chat, /list, legacy ping, chunk tracking, heightmaps and light layers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:32:29 +02:00
Ludovic Marie 0e2fc82f4e Datafix: thrown potion item field; legacy scene additions for 1.13.2 to 1.15 2026-10-13 00:32:00 +02:00
Ludovic MarieandClaude Sonnet 5.5 748a80fedd Port the DataFixers of 1.12.2 to 1.13.2 (keys 1450 to 1624): the flattening, renames, stats, leaves
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-13 00:31:05 +02:00
Ludovic MarieandClaude Opus 5.5 e0a025c5bd Compare villager gossip and breeding with vanilla
Gossip and gifts between villagers (TradeWithVillager) move into the
library so the mob_ai probe runs them as the game does; both villagers now
lock their gaze on each other, as lockGazeAndWalkToEachOther does. The
probe reads the oracle's villager flags, prints villager data (food,
inventory, gossip, reputation) and adds babies as they are born. The
oracle seeds TriggerGate's shuffles too, which were left to the clock.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:27:35 +02:00
Ludovic Marie 8498688341 Datafix: 1.13 to 1.14 fixes (1800 to 1963); saved data may be plain NBT 2026-10-13 00:26:17 +02:00
Ludovic Marie 8c542c16bb Datafix: legacy dimension ids, world gen settings from legacy level data, biome renames, potion field 2026-10-13 00:19:32 +02:00
Ludovic MarieandClaude Opus 5.5 8d16a937c5 Dedicated server: load the spawn area; vanilla-codec client harness
VanillaProtocolClient joins a server with vanilla's own codecs;
test_dedicated_server_parity.py compares a vanilla and a Horizon dedicated
server serving the same world.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:18:01 +02:00
Ludovic MarieandClaude Opus 5.5 df0c1ad36e Seed a summoned warden before its first tick, and keep its heartbeat off the server random
The shrieker summons the warden during the block ticks, so it ticks in the
same tick's entity phase: the oracle and the fixture now seed it (its
random, sensor delays and RunOne shuffles) before that phase, not after.
The heartbeat is a client sound: its pitch no longer draws from the
level random, and the fixture leaves it out as vanilla's server never
sends it. sculk: 435/435.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:16:52 +02:00
Ludovic Marie b633047a55 Datafix: fixes 2100 to 2535 (UUIDs, wall/redstone properties, bit storage, furnace recipes, ...) 2026-10-13 00:14:19 +02:00
Ludovic MarieandClaude Opus 5.5 ad2758fc9c Merge parity-base into parity/villager-social
Keeps both sides' oracle scenarios: the creaking hearts, hurts, leads and
animal flags of parity-base on this branch's entity list, with a heart's
creakings adopted under their creation seed. Restores the villager meeting,
birth and golem-check events the unfinished WIP had begun to replace.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:08:10 +02:00
Ludovic Marie d229326779 Datafix harness: --band TARGET checks the fixes up to a DataVersion on legacy-layout worlds; fixes sorted by key 2026-10-13 00:06:19 +02:00
Ludovic MarieandClaude Opus 5.5 6a8c7daca6 Format the render distance fix
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:06:03 +02:00
Ludovic MarieandClaude Opus 5.5 c1e4758d04 Finish loading at render distance 2
Streaming kept, decorated and generated chunks within circles a fixed
margin wider than the render distance, but finishing a chunk needs its
3x3 neighbours decorated and theirs generated: squares whose corners
fall outside those circles. At render distance 2 the corner chunks around
the player never finished, so their neighbours never lit and the player
was never placed. Each step now also keeps what a finished chunk's
neighbourhood needs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 00:03:47 +02:00
Ludovic Marie 93ac585c74 Datafix worlds: list 1.12.2, 1.13.2 and 1.14.4 2026-10-13 00:02:25 +02:00
Ludovic Marie 19896fb6f1 Support saves from 1.16.5 (DataVersion 2571 on): replaceitem for pre-1.17 scenes 2026-10-12 23:59:20 +02:00
Ludovic MarieandClaude Opus 5.5 3319f92c0e Merge parity-base into parity/dedicated-server; track player idle time
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 23:55:53 +02:00
Ludovic MarieandClaude Opus 5.5 af7ad70438 Merge parity-base into parity/warden-sculk
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 23:53:02 +02:00
Ludovic Marie 0870b5064b Merge branch 'parity-base' into parity/old-saves 2026-10-12 23:50:33 +02:00
Ludovic MarieandClaude Opus 5.5 4b93509137 Note the render distance 2 loading hang, and run harnesses here by default
The Mac mini and ThinkPad no longer keep the shared vanilla data, so the
other machines are opt-in again.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 19:50:58 +02:00
Ludovic MarieandClaude Opus 5.5 6909dbfc5b Mention the optional sounds step in PLAY.txt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 19:44:37 +02:00
Ludovic MarieandClaude Opus 5.5 002bd18170 Link the C runtime statically into the Windows build
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 19:31:00 +02:00
Ludovic Marie 6fab5eb279 Merge branch 'main' into parity-base
# Conflicts:
#	README.md
#	crates/horizon-client/src/game.rs
2026-10-12 19:02:09 +02:00
Ludovic MarieandClaude Opus 5.5 2f0ff87295 Describe what is new and the 88% parity audit in the README
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 19:00:32 +02:00
Ludovic MarieandClaude Opus 5.5 222345b5d1 Build Horizon on Windows and package playable folders
The control socket reports itself unavailable on Windows, which has no
Unix domain sockets, and horizon-ctl uses the same stream type. A release
workflow builds the Windows client by hand; packaging/package.sh assembles
the binary, the resource preparation tool and PLAY.txt, without any of
Minecraft's files.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 18:58:25 +02:00
Ludovic MarieandClaude Opus 5.5 c51bfda80c Run the server files harness and platform-sensitive harnesses where they agree
Number the server files cases, whose folders eula-true and eula-TRUE collide
on case-insensitive macOS file systems; keep world_border_render and mob_ai
off the Mac, where platform float math changes their results; give the local
executor the dead flag the flake check reads.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 18:57:30 +02:00
Ludovic MarieandClaude Opus 5.5 f88b1da965 Refuse only worlds older than 1.17 in the save upgrade test
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:58:34 +02:00
Ludovic MarieandClaude Opus 5.5 6402d44ce7 Pass clippy and rustfmt after merging the parity branches
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:57:27 +02:00
Ludovic Marie fc7420f74b Merge branch 'parity/old-saves' (before its WIP commit) into parity-base 2026-10-12 17:55:17 +02:00
Ludovic Marie 5731a9406f Merge branch 'parity/dedicated-server' (before its WIP commit) into parity-base 2026-10-12 17:55:17 +02:00
Ludovic Marie 404072d5e5 Merge branch 'parity/warden-sculk' (before its WIP commit) into parity-base
# Conflicts:
#	crates/horizon-client/examples/entity_anim_fixture.rs
#	crates/horizon-client/src/game.rs
#	crates/horizon-client/src/game/creatures.rs
#	tools/test_entity_model_parity.py
2026-10-12 17:55:17 +02:00
Ludovic Marie 2e3063d821 Merge branch 'parity/mobs-b' into parity-base
# Conflicts:
#	crates/horizon-client/examples/entity_anim_fixture.rs
#	crates/horizon-client/examples/mob_ai_probe.rs
#	crates/horizon-client/src/game/creatures.rs
#	crates/horizon-client/src/mobs.rs
#	crates/horizon-client/src/mobs/ai.rs
#	mods/horizon/src/test/java/dev/horizonlab/parity/VanillaMobAiOracle.java
#	tools/test_mob_ai_parity.py
2026-10-12 17:54:20 +02:00
Ludovic Marie f02c47d289 Merge branch 'parity/mobs-a' into parity-base 2026-10-12 17:50:53 +02:00
Ludovic Marie 14bff2518f Merge branch 'parity/raids' into parity-base
# Conflicts:
#	README.md
#	docs/rust-parity.md
2026-10-12 17:50:53 +02:00
Ludovic Marie c195cd3239 Merge branch 'parity/tablist-border' into parity-base
# Conflicts:
#	README.md
#	crates/horizon-client/src/lib.rs
#	docs/rust-parity.md
2026-10-12 17:50:31 +02:00
Ludovic Marie 69b191b1f4 Merge branch 'parity/loom-crafter' into parity-base
# Conflicts:
#	README.md
#	crates/horizon-client/src/game/dispense_fixture.rs
#	docs/rust-parity.md
#	mods/horizon/src/test/java/dev/horizonlab/parity/VanillaDispenserOracle.java
2026-10-12 17:48:44 +02:00
Ludovic Marie b6fa612bee Merge branches 'parity/tooling', 'parity/score-subtitles' and 'parity/block-followups' into parity-base 2026-10-12 17:47:58 +02:00
Ludovic MarieandClaude Opus 5.5 9c465af186 WIP: unfinished spawn-gear parity work, stopped by Ludovic
Uncommitted changes the agent had in progress when it was stopped on
2026-10-12; may not build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:46:50 +02:00
Ludovic MarieandClaude Opus 5.5 5ea641a7c2 WIP: unfinished villager-social parity work, stopped by Ludovic
Uncommitted changes the agent had in progress when it was stopped on
2026-10-12; may not build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:46:50 +02:00
Ludovic MarieandClaude Opus 5.5 613a0dd3f1 WIP: unfinished dedicated-server parity work, stopped by Ludovic
Uncommitted changes the agent had in progress when it was stopped on
2026-10-12; may not build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:46:50 +02:00
Ludovic MarieandClaude Opus 5.5 edd598cc68 WIP: unfinished warden-sculk parity work, stopped by Ludovic
Uncommitted changes the agent had in progress when it was stopped on
2026-10-12; may not build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:46:50 +02:00
Ludovic MarieandClaude Opus 5.5 54b939e717 WIP: unfinished old-saves parity work, stopped by Ludovic
Uncommitted changes the agent had in progress when it was stopped on
2026-10-12; may not build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:46:50 +02:00
Ludovic MarieandClaude Opus 5.5 c90cd5f072 Match vanilla llama caravans, trader llamas, breeding and wolves
A lead gives its mob a home at the holder (PathfinderMob.whenLeashedTo)
and every random position helper honours homes (generateRandomPos-
TowardDirection's lean back and GoalUtils.isRestricted), as the happy
ghast's float area now does too. LlamaFollowCaravanGoal keeps 2.1F, a
llama's baby and the breeding experience are drawn from the parent's
random, wolves run from llamas by strength (WolfAvoidEntityGoal), a
growing mob refits its box (fudgePositionAfterSizeChange) and a happy
ghast's new controls want nothing. Scenarios can lead mobs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:45:09 +02:00
Ludovic MarieandClaude Opus 5.5 ca1bc52a49 Stop the jukebox's song and the beacon as their block entities go
LevelChunk.removeBlockEntity calls setRemoved: a jukebox reports its song
stopping (the jukebox_stop_play game event and level event 1011) and a
beacon plays its deactivation, whatever the flags. A record popped from a
replaced jukebox stops a playing song first and updates the neighbours as
JukeboxBlockEntity.onSongChanged does (a redstone wire beside it can pop).
The block update oracle removes block entities the same way.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:44:54 +02:00
Ludovic MarieandClaude Opus 5.5 b0ce83dd2d Port the 1.17 to 1.18 chunk height, biome and tick fixes (2825 to 2846)
ChunkHeightAndBiomeFix, ChunkProtoTickListFix, ChunkRenamesFix,
OverreachingTickFix, SpawnerDataFix, the world generation settings fixes
and the Caves & Cliffs biome and advancement renames, with the chunk's
Level tag and UNTAGGED_SPAWNER in the schema walker. A 1.17.1 sample
world upgrades as vanilla's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:42:59 +02:00
Ludovic MarieandClaude Opus 5.5 63f628762f Tick creaking hearts as vanilla and compare them with the oracle
mobs::creaking_heart is CreakingHeartBlockEntity: the ticker drawn from
the level random, the state following the night and the logs, the
protector spawned with SpawnUtil.trySpawnMob (five tries within 16
blocks, on top of a collider, then EntityType.create's yaw and
Mob.finalizeSpawn's follow range bonus), its sounds, letting it go by
day, beyond 34 blocks or with a player stuck in it, and when a player
hurts it the trails and the resin spread over the logs. The game ticks
its hearts through it, and its level random now carries on between
ticks.

The mob AI harness gains hearts: the oracle places them when a scenario
starts, ticks block entities after the mobs, seeds the creakings the
level creates and adds them to the scenario, prints each heart's state
and block entity, and lets the player hit a mob (hurt T I). Five heart
scenarios (night, day, uprooted, no player near, hit twice) match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:40:47 +02:00
Ludovic MarieandClaude Opus 5.5 e5dc127ab2 Document scoreboards, teams and subtitles and their harnesses
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:39:55 +02:00
Ludovic MarieandClaude Opus 5.5 05228e0fe2 Document the loom, crafter and recipe book harnesses
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:39:45 +02:00
Ludovic MarieandClaude Opus 5.5 b5c0bf7859 Draw the loom and crafter screens as the vanilla client does
LoomScreen.extractBackground (slot icons, scroller, pattern buttons
with their swatches and tooltip, the result banner or the six-layer
error) and CrafterScreen's background, disabled slots and redstone
arrow become screen_layout calls the game paints. A new harness runs
vanilla's screens on stand-in menus and compares 1,600 call lists.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:38:25 +02:00
Ludovic MarieandClaude Opus 5.5 4b776a45d8 Tick blocks before entities, as ServerLevel.tick does
The scheduled and random block ticks now run after the player's digging
and before any entity, so items a dispenser shoots or a block pops get
their first tick on the tick they appear, as vanilla's do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:36:33 +02:00
Ludovic MarieandClaude Opus 5.5 225c12f4cc Move subtitles into the HUD overlays and save scoreboards end to end
The subtitle overlay now lays out GuiDraw calls in hud_overlays and the
game paints them like the other overlays. Hover events that show an entity
save its UUID as an int array, as UUIDUtil.CODEC does. The save round trip
builds a vanilla scoreboard with every saved field (objectives, number
formats, display slots, locked and displayed scores, teams with every
option) and requires Horizon to save scoreboard.dat as vanilla did.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:35:05 +02:00
Ludovic MarieandClaude Opus 5.5 01db93a987 Port server.properties, eula.txt and the server user lists
DedicatedServerProperties with every key, default, parser and serializer,
java.util.Properties load/store, Eula and the four StoredUserList files,
checked against the pinned server JAR by test_server_files_parity.py.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:34:57 +02:00
Ludovic MarieandClaude Opus 5.5 8f80f8decf Document block entity removal, immediate drops and copper golems
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:33:49 +02:00
Ludovic MarieandClaude Opus 5.5 13102892c4 Render, save and gift copper golems as vanilla does
The copper golem takes its weathering's texture and glowing eyes, saves
and loads next_weather_age and weather_state, starts with its weathering
unset instead of weathering on its first tick, and throws what it carries
to the player as BehaviorUtils.throwItem does. Iron golems offer their
poppy to copper golems too (#candidate_for_iron_golem_gift) and put it on
an empty antenna when the offer runs out beside one.

The entity model harness now poses the copper golem with its idle and
chest interaction animations (44 cases), and the entity death loot harness
includes it (1,595 cases over 88 types); both match vanilla.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:31:52 +02:00
Ludovic MarieandClaude Opus 5.5 82eda1d8bf Port the 1.18 structure fixes (2967, 2970) and add a 1.18.1 sample world
Old server jars run on Mojang's own Java runtimes, pinned in
research-lock.json and installed beside the shared vanilla data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:30:48 +02:00
Ludovic MarieandClaude Opus 5.5 515d15d36f Merge the integration branch into parity/tablist-border
Keep the integration branch's StringSplitter port and HUD overlays: the tab
list now emits hud_layout::GuiDraw calls and wraps with its split_lines, and
the vignette's border warning comes from WorldBorder::warning_strength
through hud_overlays::border_warning.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:25:13 +02:00
Ludovic MarieandClaude Opus 5.5 a425de4c1c Merge the integration branch: villager brain, mob AI fixes and HUD overlays
The raid bars now draw through hud_overlays. Villagers' raid field is
what getRaidAt finds where they stand, with lost raids and the wave flag
kept apart, so the brain's SetRaidStatus, ResetRaidStatus (which resets on
a lost raid), ReactToBell and raid packages read vanilla's conditions.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:23:59 +02:00
Ludovic MarieandClaude Opus 5.5 81e97617af WIP: share the creaking heart's block entity tick
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:22:02 +02:00
Ludovic MarieandClaude Opus 5.5 e664d2f7c4 Merge origin/t3/achieve-full-parity into parity/block-followups
Explosion drops keep their random sequences and the pot's dynamic drops;
/setblock destroy and /fill destroy run Level.destroyBlock through the
behaviour library, so the block entity spills as vanilla's does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:19:39 +02:00
Ludovic MarieandClaude Opus 5.5 e723c8ad6c Merge origin/t3/achieve-full-parity into parity/score-subtitles
Mobs push through the new pushEntities with the teams' collision rules;
lang keeps the integration branch's deprecated.json handling; the
scoreboard keeps this branch's vanilla hash orders.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:19:13 +02:00
Ludovic MarieandClaude Opus 5.5 2edae5746a Merge origin/t3/achieve-full-parity into parity/mobs-b
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:18:39 +02:00
Ludovic Marie 5dd2840cee Merge remote-tracking branch 'origin/t3/achieve-full-parity' into parity/warden-sculk
# Conflicts:
#	crates/horizon-client/src/game.rs
#	crates/horizon-client/src/game/creatures.rs
2026-10-12 17:18:11 +02:00
Ludovic Marie a5eb241c32 Merge remote-tracking branch 'origin/t3/achieve-full-parity' into parity/loom-crafter
# Conflicts:
#	crates/horizon-client/src/game/commands/world_cmds.rs
2026-10-12 17:15:59 +02:00
Ludovic MarieandClaude Opus 5.5 8393b8de0f Match vanilla breeding sniffers and tempted happy ghasts
Mobs set each other's brain memories within the tick (the breed target
and lockGazeAndWalkToEachOther), the partner rests and forgets at the
birth, and an animal in love draws its heart particle randoms. The adult
happy ghast's TemptGoal.ForNonPathfinders ticks every other tick and
follows creative players. The mob AI scenarios can give the player an
item and a mob love, taming, an age or a llama strength.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:15:34 +02:00
Ludovic MarieandClaude Opus 5.5 233dadf29f Run harnesses on the ThinkPad too, two at a time at nice 19
A sample of 27 harnesses (the 20 quickest, options, datafix's six shards)
passed there; it builds against the same ALSA headers as the desktop.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:15:18 +02:00
Ludovic MarieandClaude Opus 5.5 b56b4c3cea Bring the copper golem into the game and build it and shear it as vanilla does
The copper golem code (its goals, chest transport, weathering, statues and
interactions) was in the tree but not compiled; it is now a species with
its model, keyframe animations, sounds and game hooks. Its antenna flower
sits in the saddle slot as vanilla's EQUIPMENT_SLOT_ANTENNA, sheared by
players and dispensers with the unequip event and the 1.5-up drop, and
dropped with the carried stack as preserved equipment. A pumpkin on a
copper block builds it after the snow and iron golem patterns: both blocks
clear, the block becomes the matching copper chest (CopperChestBlock
getFromCopperBlock with the least oxidized of connected chests), and the
golem takes the block's weathering and plays its spawn sound. Weathering
draws from the level random, the statue pose from the golem's own.

The dispenser harness now builds copper golems and shears and equips them:
6000/6000 cases match.

Block.popResource of tall flowers and flower beds and the composter's
bone meal pop when the behaviour asks, as vanilla does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:14:20 +02:00
Ludovic MarieandClaude Opus 5.5 8ba728287f Order the recipe book's buttons as the vanilla client does
ClientRecipeBook keeps the displays it was sent in a HashMap of display
ids, whose iteration order (buckets, then arrival) orders the
collections; the game now keeps such a client book (on the verified
Java HashMap port) synced with the server book, with display ids
numbered as RecipeManager does. A new harness runs the client's
ClientRecipeBook, RecipeCollection selection and the tab and page logic
of RecipeBookComponent over 1,200 cases.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:14:14 +02:00
Ludovic MarieandClaude Opus 5.5 59a966a9e3 Compare breezes and creakings with vanilla in the mob AI harness
Eight scenarios: a breeze alone and fighting a player near, inside and
beyond its jump circle; a creaking alone, watched, unwatched, and woken
then hunting once the player turns away (a new player turn= option).
The oracle now faces the player +z with its head too (it kept a random
head yaw from its creation, which the breeze's jump target reads).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:14:07 +02:00
Ludovic MarieandClaude Opus 5.5 245ceb5428 Port the breeze and creaking brains
monster_brain runs BreezeAi and CreakingAi as vanilla's Brain does:
the sensors with their random first delays, memories that expire, the
core, idle and fight activities, and each behaviour (Shoot, LongJump,
ShootWhenStuck, Slide, SlideToTargetSink, StartAttacking, MeleeAttack,
RunOne...) started and ticked in vanilla's order, with durations drawn
from the level random. It reuses the villager brain's memory slots.

Breeze.tick draws its particle count and whirl clock before the entity
tick; its whirl and idle sounds are local (client) sounds; it is immune
to fall damage and plays its landing sound. Entity.lookAt and the long
jump's atan2 (an fdlibm port) are bit-exact. A frozen creaking keeps
thinking while its navigation and controls wait, stopInPlace zeroes its
motion, and its attack sound follows the hit. Mobs update their ground
flag on every move, as a server's authoritative entities do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:14:02 +02:00
Ludovic MarieandClaude Opus 5.5 839ea6d04c Give the level random back to the level after the mobs' ticks
Brain behaviours draw from the level random (DoNothing, POI scans): the
game lends it to the mobs and keeps what they drew.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:13:57 +02:00
Ludovic Marie b98c67b04f Merge remote-tracking branch 'origin/t3/achieve-full-parity' into parity/mobs-a 2026-10-12 17:13:55 +02:00
Ludovic MarieandClaude Opus 5.5 d98576a1a4 Document remote hosts, shards, Rust scopes, flake checks and trial merges
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:11:09 +02:00
Ludovic MarieandClaude Opus 5.5 a4355c7c9b Catch flaky harnesses: --repeat, and three runs in the gate
parity.py --repeat N runs each harness N times; its runs must agree, else it
is reported FLAKY and recorded as failing. Later rounds run on the machine
that ran the first, reusing its oracle results, and never two at once there.
With --flake-check REF (passed by gate.py, merge base with parity-base; by
supervise.py integrate, the integration branch before the merge), harnesses
whose script, oracle or probe is new or changed must pass three runs in a
row; a pass records its rounds so it is not repeated again. gate.py matches
shards of a known failure by the harness's name.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:10:08 +02:00
Ludovic MarieandClaude Opus 5.5 bbae62fc4b Render subtitles exactly as vanilla's SubtitleOverlay
The overlay listens to the sound engine from the frame that renders it with
Show Subtitles on until one renders with it off (keeping its captions),
forgets plays as it renders, picks the latest play in range (the first of
full ties), fades in float arithmetic, lays the boxes out in integers under
the pose translation and takes its background from the text background
opacity options. Translations now apply the game's deprecated.json renames,
as ClientLanguage does ("Chick hurts"). tools/test_subtitle_parity.py runs
vanilla's SubtitleOverlay on 1500 scripted cases.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:07:47 +02:00
Ludovic MarieandClaude Opus 5.5 000e676b57 Compare the warden's animations and emissive layers with vanilla
The entity model harness now sets the warden's render state (tendril and
heart animation, the roar, sniff, emerge, dig, attack and sonic boom
animation states) and bakes its four emissive layers (tendrils, heart,
bioluminescent skin, pulsating spots) over WardenModel: 430 cases match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:06:36 +02:00
Ludovic MarieandClaude Opus 5.5 621fca874c Keep the player's recipe book as vanilla's ServerRecipeBook does
The known and highlighted recipes, the book settings and the saved
recipeBook compound now live in one place (recipe_book::Settings with
a RecipeIndex of learnability and display counts): advancement rewards,
/recipe give and take (counting displays, never special recipes) and
crafting a recipe award through it, and loading drops unknown recipes
instead of rebuilding the set from done advancements. A new harness
compares 1,500 operation sequences with vanilla's ServerRecipeBook and
its codec.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:02:53 +02:00
Ludovic MarieandClaude Opus 5.5 2f232d955c Charge sculk catalysts when the killing blow lands
Mobs die (LivingEntity.die: the death event, catalysts, loot and
experience) when they are killed, not when their death animation ends.
Catalysts take a death in the dispatcher's order (nearest by exact
distance, then visiting order); experience orbs draw their merge id from
the level random and their motion from their own. The sculk harness
gains catalyst scenarios: kills by the player near catalysts over
random terrain, with blooms, charge cursors and the sculk they spread.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:01:59 +02:00
Ludovic MarieandClaude Opus 5.5 4a2d801d2b Apply teams in gameplay: targeting, explosions, pushing, names, deaths
Mobs on the player's team never target the player; a creeper's blast
spares its team mates when its team has no friendly fire; mobs push each
other only as their collision rules allow; name tags follow the team's
name tag visibility, show the team's prefix, suffix and colour and the
score of the objective displayed below names; the player's own death
message stays out of chat when the team hides death messages. The
criteria that follow the player compare health as a float, round armor
down and give auto-updated displays the player's team-formatted name.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:52:15 +02:00
Ludovic MarieandClaude Opus 5.5 acf4df3a90 Place recipe book recipes as vanilla's ServerPlaceRecipe does
ServerPlaceRecipe and StackedContents' RecipePicker run on the menu
engine (horizon_client::menu::place) for the inventory, crafting table
and furnaces: testClearGrid, clearGrid with placeItemBackInInventory,
the biggest craftable stack, clamping to stack sizes and moveItemToGrid.
A new harness compares 6,000 placements with vanilla; vanilla's item
order follows identity hash codes, so the oracle hands its order to the
Rust side. The game's recipe book now places through the engine, and
its craftable filter uses the same counts and placement ingredients.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:51:38 +02:00
Ludovic MarieandClaude Opus 5.5 09a0a0e261 Match vanilla happy ghasts and ghastlings
The adult's careful GhastMoveControl (the blocks around the destination
and swept on the way, #happy_ghast_avoids, fluids), HappyGhastLookControl,
HappyGhastFloatGoal, the still timeout of a player standing on top, and
getSuitableFlyToPosition returning its first good point. The ghastling
flies by its brain with getWalkTargetValue's preference for air just
above the ground. Flying travel drags by 0.91F and 0.8F as floats, and a
happy ghast swims as fast as it flies.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:51:36 +02:00
Ludovic MarieandClaude Opus 5.5 4490ff75fc Spill block entity contents when their block is replaced, as vanilla does
LevelChunk.setBlockState now runs BlockEntity.preRemoveSideEffects and
removes the block entity when a block with one is replaced by another
block (copper chests and copper golem statues keep theirs across
weathering; UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS skips the side effects).
Containers spill every slot through Containers.dropItemStack (spot and
pieces of 10 to 30 with triangular motions from the level random, empty
slots still drawing their spot), jukeboxes pop their record, lecterns
their book; shulker boxes keep their contents for the dropped box.
Campfires, decorated pots, chiseled bookshelves and shelves, which Horizon
keeps as loaded, spill too.

Block.dropResources now draws its loot and pop spots when the behaviour
calls it, not after it returns, and spawnAfterBreak awards ore, sculk and
spawner experience. Item entities and orbs the behaviour makes are added
before it returns to the game, in the same tick. Player mining follows
ServerPlayerGameMode.destroyBlock's order (removal and spill, tool wear,
then the drops); explosions let the removal spill the contents.
ExperienceOrb.award draws the merge id from the level random and moves
the orb with its own random. Decorated pots copy their decorations and
drop their sherds when cracked (loot tables' dynamic entries).

The block update oracle replays preRemoveSideEffects too, and the new
block removal harness (tools/test_block_removal_parity.py) compares
setBlock/destroyBlock/removeBlock on every block entity holder with
contents against vanilla: 2000/2000 cases match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:49:20 +02:00
Ludovic MarieandClaude Opus 5.5 cdd05f8e8b Trial-merge branches before integrating them
supervise.py check trial-merges every candidate branch into the integration
branch with git merge-tree, without touching a worktree: each alone, every
pair, then the largest set that merges cleanly together, in about a second.
integrate starts from that set (or every parity/* branch with new commits,
with --ready), gates it once, and if the gate fails tries each half, so the
branches that pass still land.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:43:58 +02:00
Ludovic Marie e6aa9f71b0 Merge branch 'parity/rendering-be' into parity-base 2026-10-12 16:43:52 +02:00
Ludovic Marie 93c3de5d61 Merge branch 'parity/hud' into parity-base 2026-10-12 16:43:50 +02:00
Ludovic Marie 095991b946 Merge branch 'parity/rendering-hud' into parity-base 2026-10-12 16:43:49 +02:00
Ludovic Marie cfb19e238f Merge branch 'parity/rendering-anim' into parity-base 2026-10-12 16:43:49 +02:00
Ludovic Marie ec6c2c596f Merge branch 'parity/entity-ai' into parity-base 2026-10-12 16:43:48 +02:00
Ludovic Marie 577e68fd12 Merge branch 'parity/tooling' into parity-base 2026-10-12 16:43:47 +02:00
Ludovic MarieandClaude Opus 5.5 70992eb815 Document the patrol and raid harness and its scope
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:43:32 +02:00
Ludovic MarieandClaude Opus 5.5 cb0244ce4a Fill the mob effect registry so /effect finds its effects
The command registries never received the effect ids, so every /effect
and mob_effect argument failed to resolve.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:43:32 +02:00
Ludovic MarieandClaude Opus 5.5 a05f9b7b8c Run harnesses on the Mac mini by default
Every harness gave the same result on the Mac mini as on Linux, except
options and chunk_generation, where Rust's float functions use the platform
libm and round differently on macOS: those stay off the Mac. gate.py and
supervise.py no longer force 8 local harnesses, so parity.py keeps the
desktop to 3. The ThinkPad is listed (2 harnesses, nice 19) but not used by
default. Oracle runs get a 15-minute hang guard instead of 5, since one oracle
on a fully loaded machine can take more than 5 minutes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:42:07 +02:00
Ludovic MarieandClaude Opus 5.5 cb19f5e7d6 Make the datafix harness take 40 seconds instead of 25 minutes
The oracle spent 58 of every world's 62 seconds waiting for the idle
threads of the game's IO pool to time out; it now exits once its outputs are
written (same outputs on all 22 worlds). The harness runs in 6 shards, keeps
the vanilla outputs so the oracle's results are reused, and declares its Rust
scope (datafix, NBT, region files, compression and horizon-core positions):
other horizon-world changes no longer rerun it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:41:51 +02:00
Ludovic MarieandClaude Opus 5.5 f5ab40d415 Shard harnesses, narrow their Rust sources, keep the desktop light
parity.py:
- A harness declaring PARITY_SHARDS = N runs as N entries, NAME#1..NAME#N,
  each told its share through PARITY_SHARD; NAME selects them all.
- PARITY_RUST_SCOPE lists the Rust sources a harness's probes can reach.
  It applies only if closed (nothing in it names a module, crate-root
  re-export or macro outside it, and nothing outside implements anything for
  its types); crate roots then count without their other module declarations.
- Bytecode caches no longer count as dependencies.
- With other hosts, this machine runs 3 harnesses at once and only those
  under 800 MB, admitted against the memory free at each start; hosts can
  exclude harnesses and run at a nice level.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:41:51 +02:00
Ludovic MarieandClaude Opus 5.5 5352b59358 Tick the sniffer's and the ghastling's brains
The level random is passed down to the mob AI step as the integration
branch does, the brain runs in customServerAiStep's place, and the mob AI
probe builds the brain after seeding the mob and prints its activities and
memories. The oracle seeds every GateBehavior's shuffle with the mob's seed
(the same change the entity-ai branch makes) so RunOne picks are
reproducible.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:36:44 +02:00
Ludovic MarieandClaude Opus 5.5 1515c5e46c Add vanilla's team rules and compare them with vanilla
Friendly fire (doTeamsAllowDamage), alliances, collision rules
(EntitySelector.pushableBy), seeing invisible team mates (isInvisibleTo),
name tag visibility (LivingEntityRenderer.shouldShowName) and who sees a
player's own death message. tools/test_team_rules_parity.py runs vanilla's
methods on stand-in entities and a stand-in client over 6000 cases.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:36:04 +02:00
Ludovic MarieandClaude Opus 5.5 89c3a155c5 Play the sniffer's digging and searching sounds on the client side
The searching sound and the digging block hit sound are the client's
(playSearchingSound, emitDiggingParticles), the digging sound starts with
the dig (SnifferSoundInstance), and the egg plop and the breeding
experience come from the parent's random in its brain.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:31:58 +02:00
Ludovic MarieandClaude Opus 5.5 eb9bee05bd Run the loom and the crafter menu on the verified menu engine
LoomMenu (selectable patterns, clickMenuButton, the six-layer limit,
quick moves, the result's onTake) and the server's CrafterMenu over the
block entity (the result following the grid, slot state packets, filled
disabled slots enabling) join the menu click harness, now 8,000 click
sequences over 19 menus with pattern button and slot state ops. Slot
clicks end with setChanged and container slots are limited to their
stack size as SimpleContainer does. The game's loom and crafter screens
now click through Game::menu_session on the same engine.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:31:00 +02:00
Ludovic MarieandClaude Opus 5.5 4e871bf22e Match vanilla llamas: the horse tail draw and mobs seeing earlier mobs' moves
AbstractHorse.aiStep draws a tail swish every tick before the goals run.
Mobs now see the mobs ticked before them as they are after their tick
(ServerLevel ticks entities one after another), in the game and in the
mob AI probe; a baby llama following its parent depended on it. The
llama's strength is read raw, as getStrength does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:29:00 +02:00
Ludovic MarieandClaude Opus 5.5 b8711a7c64 Add a sculk vibration harness against a vanilla server level
VanillaSculkOracle runs sensor, calibrated sensor and shrieker scenarios
(scripted game events and block changes, the player's warning level) in
a real headless level ticked in ServerLevel.tick's order; the game runs
the same scenarios through its own sculk code (HORIZON_SCULK_FIXTURE).

Fixes found on the way: sculk block entities tick in the order they were
added, the entity phase of sculk runs before the block entities, client
side effects of level events draw from the client random, scheduled
ticks run one at a time so a shrieker summons inline, wardens are
summoned as SpawnUtil does (obstruction by entities, the yaw and
finalizeSpawn draws, agitated sounds of discarded attempts), and an
empty level no longer draws the level random every tick.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:25:06 +02:00
Ludovic MarieandClaude Opus 5.5 68520308d0 Keep the scoreboard in vanilla's hash orders and save it as its codec does
The objectives, holders and teams now iterate as vanilla's fastutil maps and
each team's members as its HashSet; criteria resolve to their canonical
names as ObjectiveCriteria.byName does; scoreboard.dat leaves out the
fields equal to the codec defaults and writes components as
ComponentSerialization does. tools/test_scoreboard_parity.py runs vanilla's
own Scoreboard against the model on 500 scripted cases.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:23:34 +02:00
Ludovic MarieandClaude Opus 5.5 81783a5125 Port PatrolSpawner, Raid and Raids exactly, and run the game on them
The patrol spawner, the raid tick (countdown, spawn positions, wave
composition, bonus wave, leaders, riders, boss bar, horn seed, raiders
leaving, victory, loss, celebration) and the raids.dat codec with
DataFixerUpper's partial results and fastutil's map order now follow
vanilla line by line. tools/test_raid_parity.py runs vanilla's own
PatrolSpawner, Raids and Raids.CODEC on a stand-in level: 1,900 cases
match.

In game, raiders join, are loaded, hurt and killed through addWaveMob,
updateBossbar and removeFromRaid as vanilla calls them, the wave leader
map lives in the raid, recruits take the raid's current wave, raid and
patrol mobs keep their spawn rotation, and each dimension keeps its own
raids.dat. Bad Omen and Raid Omen act from inside the effect tick, with
the ConcurrentModificationException vanilla swallows when Raid Omen is
first added, and the omen position is saved with the player.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:22:29 +02:00
Ludovic MarieandClaude Opus 5.5 0e076c7153 Port the sniffer's and the ghastling's brains
SnifferAi and HappyGhastAi as vanilla's Brain runs them: the sensors and
their scan rates, the activities and their requirements, and every
behaviour (AnimalPanic, MoveToTargetSink, FollowTemptation, AnimalMakeLove,
LookAtTargetSink, RunOne and the sniffer's scenting, sniffing, searching,
digging, rising and happy states) in availableBehaviorsByPriority order.
Adds AirAndWaterRandomPos and the mob AI scenarios for llamas, sniffers
and happy ghasts. The brain is not ticked yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:17:44 +02:00
Ludovic MarieandClaude Opus 5.5 95c7e7ad2a Document the player list and world border parity harnesses
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:08:40 +02:00
Ludovic MarieandClaude Opus 5.5 e4bb8463b9 Show the player list and the world border wall in the game
Holding the player-list key draws tab_list's layout: in single player the
local player with the list objective (vanilla shows nothing otherwise), on
a server the listed players from PlayerInfoUpdate (game mode, latency,
display name, list order, hat), the tab list header and footer, online
mode for heads and the server's objectives, scores, display slots and
teams, which now also feed the sidebar. The renderer draws the border wall
with RenderPipelines.WORLD_BORDER's overlay blend and the forcefield
texture, from border_render's buffer and transforms; the client border
follows the server's border packets and ticks between them. The vignette
reddens near the border.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:07:47 +02:00
Ludovic MarieandClaude Opus 5.5 16227901fc Check the crafter against vanilla with a crafting harness
CrafterBlock.dispenseFrom and CrafterBlockEntity.serverTick over 4,000
cases: recipes from the datapack with remainders and specials, disabled
slots, containers and other crafters in front. The crafter now reports
its level events (1049, 1050, white smoke 2010) through the client
random, hoppers merge stacks only with equal components, brewing stands
take items as a WorldlyContainer, and empty written book pages are not
written.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 16:05:18 +02:00
Ludovic MarieandClaude Opus 5.5 1c9c9486f6 Run vanilla harnesses on other machines with parity.py --hosts
A worker started over ssh (parity.py --worker) runs harnesses on a mirror of
the worktree on another machine, here the Mac mini. One longest-first queue
feeds every machine, remote ones first; passes come back with the content
hash of each dependency, so they are keyed on exactly what ran. Harnesses
that need this machine are listed in tools/parity_hosts.json.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:54:35 +02:00
Ludovic MarieandClaude Opus 5.5 95015b7828 Compare sniffer animation states, happy ghast layers and the llama decor model
The entity model harness now drives the sniffer's five keyframe animation
states and its search walk, the happy ghast body item, riding and leash
holder on its body, harness and ropes layers, and LlamaDecorLayer's model.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:51:58 +02:00
Ludovic MarieandClaude Opus 5.5 cba3f5bb6a Compare the breeze's animations and its wind and eyes layers with vanilla
The entity model harness now poses the breeze's six animation states and
bakes BreezeWindLayer's and BreezeEyesLayer's models and the creaking's
emissive eyes model (141 and 64 cases, no differences).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:51:57 +02:00
Ludovic MarieandClaude Opus 5.5 8a32850f95 Lay out the player list exactly as vanilla PlayerTabOverlay does
tab_list ports PlayerTabOverlay: the comparator (list order, spectators,
team, name ignoring case), the 80-player limit and 20-row columns, heads
with the default skin by UUID and upside-down names, team and spectator
name styling, ping bars, the list objective as integer scores in their
number format or hearts with their change blink and the hp text fallback,
and the wrapped header and footer. Font::split_lines now follows
StringSplitter.splitLines and Text::resolve_legacy applies legacy codes
inside components. test_tab_list_parity runs vanilla's overlay against
examples/tab_list_fixture: 1,000 cases, 3,476 frames, 844,758 calls match.

The protocol gains the scoreboard, team and world border packets.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:47:55 +02:00
Ludovic MarieandClaude Opus 5.5 a086bd83ba Merge parity/entity-ai, parity/rendering-anim and parity/rendering-hud into parity/hud
Keep the nbt contents hook and stack_display_name from parity/hud with
rendering-hud's object_style and first-component sibling style.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:40:44 +02:00
Ludovic Marie 94508b4528 Merge remote-tracking branch 'origin/parity/rendering-anim' into parity/hud 2026-10-12 15:39:07 +02:00
Ludovic Marie 136b74011c Merge remote-tracking branch 'origin/parity/entity-ai' into parity/hud 2026-10-12 15:39:06 +02:00
Ludovic MarieandClaude Opus 5.5 3467380074 Render the world border wall and its vignette exactly as vanilla does
The client border now wraps horizon-core's vanilla-checked BorderGeometry
(previous size for partial ticks, status, lerp speed, absolute limit) and
border_render ports WorldBorderRenderer: extract's fade and tint, the cached
wall buffer, the scrolling texture transform and which walls draw. The
vignette takes vanilla's int colour and the warning strength from the
border. test_world_border_render_parity runs vanilla's renderer against
examples/world_border_render_fixture: 1,500 cases, 16,859 frames match.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:29:53 +02:00
Ludovic MarieandClaude Opus 5.5 f94aa2a3d6 Assemble /place jigsaw pieces from the generation context's random
JigsawPlacement.generateJigsaw builds the pieces with the GenerationContext's
WorldgenRandom (large feature seed from the level seed and the position's
chunk) and only places them with the level random. Horizon assembled them from
the level random, so the village layout, and the plants /fill later broke
around it, changed from run to run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 14:28:40 +02:00
Ludovic Marie 42c2e96082 Merge remote-tracking branch 'origin/t3/achieve-full-parity' into parity/hud 2026-10-12 14:07:23 +02:00
Ludovic MarieandClaude Opus 5.5 e2b3f7b4e9 Keep unsimulated entities' UUIDs across saves and save player equipment as vanilla
save_entities forgot the UUID and compound of entities Horizon keeps but
does not simulate, so the save on quit gave them new UUIDs. The player's
equipment is written as LivingEntity does: omitted when empty, where
PlayerEquipment.isEmpty also counts the selected hotbar item.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 13:26:18 +02:00
Ludovic MarieandClaude Opus 5.5 b3b6194a91 Add the plans for after the rewrite to the README roadmap
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 02:49:42 +02:00
Ludovic MarieandClaude Opus 5.5 6fdd7f3bd7 Add the Horizon logo, banner and in-game screenshots to the README
An original logo (a sun setting behind a blocky horizon), a banner and a social
preview card, and six screenshots captured in the Rust client. The README opens
with badges, a short pitch and a gallery; a test keeps the parity badge in step
with the subsystem table. Packaged builds use the logo as their menu icon.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 02:47:52 +02:00
Ludovic MarieandClaude Opus 5.5 312d5fc7d2 Hide the whole HUD and the hand with F1, as vanilla does
F1 only hid the chat. Hud.extractRenderState hides the camera overlays,
crosshair, hotbar, effects, bars, sidebar, action bar, titles and chat, and
GameRenderer.renderItemInHand skips the hand; the sleep overlay, debug screen
and open screens still draw.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 02:47:37 +02:00
Ludovic Marie fae208deb6 Merge pull request #39 from ludovic111/docs/professional
Docs: professional README and no personal details
2026-10-12 02:18:57 +02:00
Ludovic MarieandClaude Opus 5.5 83bcfb15af Docs: professional README and no personal details
Restructure the README around what Horizon is, its status, how to build it
from your own copy of the game, and its parity table. The Java performance
pack material and the research lab notes move to docs/java-packs.md and
docs/research-lab.md. The target platform is stated generically instead of
naming a machine, the stale list of missing mobs is dropped in favour of the
audited table, and the legal notice follows Mojang's usage wording.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 02:14:10 +02:00
Ludovic MarieandClaude Opus 5.5 6c90e42675 Install ALSA headers for the CI lint and test job
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 02:02:37 +02:00
Ludovic MarieandClaude Opus 5.5 37898e856b Build from the user's own copy of the game instead of downloading it
Horizon no longer fetches anything of Minecraft from Mojang's servers. The
client jar, version JSON, libraries and assets come from the user's official
launcher install, and the server jar is one they downloaded themselves
(--server-jar or HORIZON_SERVER_JAR). Every file is checked against checksums
pinned in research-lock.json, and the prepared .local/ layout is byte-identical
to the old downloads, so the harnesses and the native client are unchanged.

CI keeps the offline checks on GitHub's runners; the vanilla comparisons and
the mod build need the game, so they move to a manual job on a self-hosted
runner that holds the maintainer's own copy.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 02:00:18 +02:00
Ludovic MarieandClaude Opus 5.5 feb043fda6 Merge parity/blocks into parity/hud
Block loot keeps one random-sequence path: the blocks side's block_loot
with the generic loot evaluator, and /loot uses the shared loot_sequence.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 19:02:13 +02:00
Ludovic MarieandClaude Opus 5.5 7d35a25906 Format and lint the command parity changes
Clippy and rustfmt clean, and the scoreboard test now expects vanilla's
removeObjective, which keeps holders tracked without scores.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 18:00:32 +02:00
Ludovic Marie 2e775aff2f Merge parity-base into parity/hud 2026-10-11 17:51:39 +02:00
Ludovic MarieandClaude Opus 5.5 a919e44050 Run /locate biome and poi and /place feature, jigsaw and structure as vanilla
/locate biome samples the biome source like BiomeSource.findClosestBiome3d,
/locate poi scans loaded chunks for PoiTypes block states within 256 blocks,
/place feature places the configured feature with the level random,
/place jigsaw assembles pieces with JigsawPlacement.addPieces and places
them into the level, and unknown structures or pools report vanilla's
errors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 17:35:55 +02:00
Ludovic MarieandClaude Opus 5.5 d46fa60400 Run /compute as vanilla's ComputeCommand
Context int and float providers (inline or registered) evaluate with
Java's arithmetic, exceptions and rounding, in the default, block or
entity loot context; their codecs report missing fields as
DataFixerUpper does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 17:24:18 +02:00
Ludovic MarieandClaude Opus 5.5 17b1bcf2ce Destroy blocks for /setblock and /fill destroy as Level.destroyBlock does
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 17:11:05 +02:00
Ludovic MarieandClaude Opus 5.5 debc6e124c Award tick, inventory and recipe advancements and draw block drops as vanilla
PlayerTrigger.TICK fires every tick and InventoryChangeTrigger as the
inventory changes; /recipe counts recipe book displays and fires
RecipeUnlockedTrigger; block drops draw from their loot table's random
sequence.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 17:02:09 +02:00
Ludovic MarieandClaude Opus 5.5 753b5654b1 Keep errors inside forked execute chains silent, as vanilla
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 16:51:07 +02:00
Ludovic MarieandClaude Opus 5.5 00371a7f35 Run /test as vanilla does in a world without test instances
Model TestCommand's release tree (ResourceSelectorArgument patterns
included) and its finder, locate, pos, stop and clear outcomes when no
test instance block exists. Compare /help's gamerule alternatives as a
set: GameRuleCommand registers them in identity-hash order.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 16:47:42 +02:00
Ludovic Marie 38059ab9f9 Merge branch 'parity-base' into parity/hud 2026-10-11 16:43:21 +02:00
Ludovic MarieandClaude Opus 5.5 d7e4a5a275 List command usages in vanilla's registration order and run the release tree
Brigadier keeps children in registration order and /help prints them
that way; tools/generate_command_order.py records vanilla's order where
Horizon's tree differs. The game now runs the release integrated
server's tree; HORIZON_DEV_COMMANDS restores the development commands.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 16:41:43 +02:00
Ludovic MarieandClaude Opus 5.5 8490e19ec0 Resolve nbt text components, other dimensions and vanilla's own data as vanilla
/tellraw resolves nbt components; execute in another dimension sees its
chunks unloaded; the built-in pack's predicates load; holders stay
tracked after their objective is removed; new worlds use the offline
profile id of the player.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 16:34:17 +02:00
Ludovic MarieandClaude Opus 5.5 2faf5520b3 Match vanilla /spreadplayers, /datapack, /reload, function tags and dialog codecs
/spreadplayers follows SpreadPlayersCommand (safe positions, failure
distance, float centre); /datapack models the built-in, feature and
world packs with their chat links; unknown function tags are empty.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 16:22:06 +02:00
Ludovic MarieandClaude Opus 5.5 b5d84b138d Match vanilla /clear predicates, /particle results, block entity NBT and /fillbiome checks
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 16:06:17 +02:00
Ludovic MarieandClaude Opus 5.5 c80edcdbf4 Draw /loot from each table's random sequence, as vanilla
LootTable.getRandomItems uses the table's random_sequence, so /loot
results are deterministic per world seed; inline loot tables and tool
components now work too. The oracle ticks its player like the network
listener does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 15:59:56 +02:00
Ludovic MarieandClaude Opus 5.5 2ea1c273dd Run /item modify, /summon stacks and generic attributes as vanilla
Inline and registered item modifiers now apply (26.3's type-dispatched
functions, set_lore, set_custom_data, set_components, toggle_tooltips,
filtered), counting every set slot like CountingModifier. Item stacks
keep components Horizon does not model, display names follow
ItemStack.getDisplayName, /data prints compounds in CompoundTag's
HashMap order, summoned passengers snap to the position, and living
entities other than the player get vanilla attribute maps (waypoint
transmit range included, tracked as ServerWaypointManager does).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 15:52:59 +02:00
Ludovic Marie c2b7dad0e4 Merge branch 'parity-base' into parity/hud 2026-10-11 15:43:47 +02:00
Ludovic MarieandClaude Opus 5.5 01f492c939 Select, tag and summon entities Horizon does not simulate, as vanilla
Markers, displays and other unsimulated entity types are now kept as
their saved data at a position, so selectors, /tag, /kill, /tp and
/data reach them. Widen the command execution corpus to every command
the integrated server registers, and keep the oracle's terrain tickets
out of /forceload's view.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 15:31:12 +02:00
Ludovic Marie 89b712b5a8 Merge branch 'parity-base' into parity/hud 2026-10-11 15:26:52 +02:00
Ludovic MarieandClaude Opus 5.5 e3a1cdce51 WIP: hud parity work, paused while the harness tooling is sped up
Uncommitted changes the agent had in progress when it was stopped; may
not build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 14:26:47 +02:00
Ludovic Marie 4becbd860b Merge branch 'parity-base' into parity/hud 2026-10-11 14:12:44 +02:00
Ludovic MarieandClaude Opus 5.5 0410a222ea WIP: unfinished hud parity work, stopped for the night
Uncommitted changes the agent had in progress when it was stopped; may not
build or pass its harnesses yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 22:24:03 +02:00
1027 changed files with 202896 additions and 31552 deletions

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
# Docker builds (the relay) need the Rust sources only.
target/
.local/
**/node_modules/
website/
benchmarks/
packs/
mods/
+3
View File
@@ -0,0 +1,3 @@
self-hosted-runner:
# The Mac mini's runner (ludovics-mac-mini), which holds the maintainer's own Minecraft files.
labels: [horizon-game, ludovics-mac-mini]
+19
View File
@@ -0,0 +1,19 @@
## What and why
<!-- What this changes, and why. Link the issue it fixes ("Fixes #123"). -->
## Vanilla reference
<!-- The vanilla classes and methods this follows (tools/rea_vanilla.py), and the harness that checks it.
"Horizon-only" for a feature vanilla doesn't have; "none" for tooling or docs. -->
## Self-check
<!-- Paste the block `python3 tools/pr_ready.py` prints (`--base upstream/main` from a fork). -->
## Screenshots
<!-- For anything players see: before and after. Delete this section otherwise. -->
<!-- Please tick "Allow edits by maintainers": we push small fixups ourselves instead of a round trip.
See CONTRIBUTING.md. -->
+72 -15
View File
@@ -1,19 +1,25 @@
name: checks
# verify: every pull request and every push to main, on GitHub's runners (the repository is public).
# parity: the vanilla harnesses a pull request's changes can affect, on the Mac mini's runner, which holds the
# maintainer's own Minecraft files (Horizon never downloads the game). A fork's pull request runs it only when
# a maintainer adds the run-parity label, once per label. See docs/release-flow.md.
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, labeled]
workflow_dispatch:
permissions:
contents: read
concurrency:
# A new push to a pull request replaces its running checks; main's runs all finish (releases follow them).
group: checks-${{ github.event.pull_request.number || github.sha }}-${{ github.event.action == 'labeled' && 'label' || 'run' }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
verify:
strategy:
fail-fast: false
matrix:
# Linux only. macOS only when started by hand: gh workflow run checks --ref <branch>.
os: ${{ fromJSON(github.event_name == 'workflow_dispatch' && '["ubuntu-latest", "macos-26"]' || '["ubuntu-latest"]') }}
runs-on: ${{ matrix.os }}
if: github.event.action != 'labeled'
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
@@ -27,14 +33,68 @@ jobs:
python tools/check_public_tree.py --history
- name: Test offline research tooling
run: python -m unittest discover -s tests -v
- name: Install Rust toolchain
run: rustup toolchain install stable --profile minimal --component rustfmt --component clippy
- name: Install Rust toolchain and the ALSA and udev headers the client links against
run: |
sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
rustup toolchain install stable --profile minimal --component rustfmt --component clippy
# Dependencies and the workspace's own build, saved from main's runs (pull requests read main's cache).
- uses: Swatinem/rust-cache@v2
with:
shared-key: verify
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Check formatting and lint
run: |
cargo +stable fmt --all -- --check
cargo +stable clippy --workspace --all-targets -- -D warnings
- name: Test Rust core and voxel kernel correctness
run: cargo +stable test --workspace
parity:
if: >-
github.event_name == 'pull_request' && (
(github.event.pull_request.head.repo.full_name == github.repository && github.event.action != 'labeled') ||
(github.event.action == 'labeled' && github.event.label.name == 'run-parity'))
runs-on: [self-hosted, horizon-game]
timeout-minutes: 120 # a change to core crates reruns ~300 harnesses: ~60-90 min on the Mac mini
steps:
- uses: actions/checkout@v4
with:
# The commit the event names: a fork's later pushes need another run-parity label.
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
# Keeps .local/ (parity state, probe builds, oracle results) and target/ between runs.
clean: false
- uses: dtolnay/rust-toolchain@stable
- name: Tools from the runner
run: bash tools/ci/runner-env.sh
- name: Vanilla data, and resources prepared by this preparer
run: bash tools/ci/vanilla-data.sh
- name: The harnesses this change can affect
env:
PARITY_HOSTS: ''
run: python3 tools/parity.py --changed ${{ github.event.pull_request.base.sha }} --timeout 1500
- name: Logs of the failed harnesses
if: failure()
uses: actions/upload-artifact@v4
with:
name: parity-logs
path: .local/parity-runner/logs/
if-no-files-found: ignore
retention-days: 3
# Horizon never downloads the game. These jobs need a self-hosted Linux runner
# (label horizon-game) holding the maintainer's own copy: the official launcher's
# game directory in HORIZON_MINECRAFT_DIR and the pinned server jar in
# HORIZON_SERVER_JAR. Start them by hand: gh workflow run checks --ref <branch>.
vanilla-parity:
if: github.event_name == 'workflow_dispatch'
runs-on: [self-hosted, linux, horizon-game]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Rust toolchain
run: rustup toolchain install stable --profile minimal
- uses: actions/setup-java@v4
with:
distribution: temurin
@@ -374,12 +434,8 @@ jobs:
RUSTUP_TOOLCHAIN: stable
run: python tools/test_float_log_parity.py
portable-mod:
strategy:
fail-fast: false
matrix:
# Linux only. macOS only when started by hand: gh workflow run checks --ref <branch>.
os: ${{ fromJSON(github.event_name == 'workflow_dispatch' && '["ubuntu-latest", "macos-26"]' || '["ubuntu-latest"]') }}
runs-on: ${{ matrix.os }}
if: github.event_name == 'workflow_dispatch'
runs-on: [self-hosted, linux, horizon-game]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -466,7 +522,7 @@ jobs:
- name: Upload original mod and pack manifests only
uses: actions/upload-artifact@v4
with:
name: horizon-${{ matrix.os }}
name: horizon-linux
path: |
dist/*.mrpack
dist/horizon-*.jar
@@ -486,3 +542,4 @@ jobs:
dist/client-graphics-smoke.json
dist/client-graphics-macos-title.json
dist/client-graphics-macos-world.json
retention-days: 3
+253
View File
@@ -0,0 +1,253 @@
name: launcher
# Builds the launcher on Linux, macOS and Windows, and releases it by itself (docs/release-flow.md): after a
# push to main that changes the launcher or what it builds in (crates/horizon-prepare, crates/horizon-theme),
# every 10 minutes (a release waiting for merges to settle goes out) and by hand, tools/release_train.py decides as
# for the game.
# A release is launcher-vX.Y.Z: the patch after the last launcher tag, or the next minor when a merged pull
# request is labelled feature. The version is given to the build (HORIZON_LAUNCHER_VERSION): no bump commits.
# Never marked latest. Pushes to launcher branches only build. RELEASES_PAUSED=1 stops releases.
# gh workflow run launcher --ref <branch> # dry run: builds everything, publishes nothing
# gh workflow run launcher --ref main -f dry_run=false -f force=true
on:
push:
branches: [main, launcher, 'launcher-*']
paths:
- 'launcher/**'
- 'crates/horizon-prepare/**'
- 'crates/horizon-theme/**'
- '.github/workflows/launcher.yml'
schedule:
- cron: '7-59/10 * * * *'
workflow_dispatch:
inputs:
dry_run:
description: Build everything and write the notes, but publish nothing
type: boolean
default: true
force:
description: Release even without launcher changes, before merges settle or while paused
type: boolean
default: false
permissions:
contents: read
concurrency:
group: launcher-${{ github.ref == 'refs/heads/main' && 'release' || github.ref }}
cancel-in-progress: false
jobs:
decide:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
release: ${{ steps.decide.outputs.release }}
tag: ${{ steps.decide.outputs.tag }}
head: ${{ steps.decide.outputs.head }}
version: ${{ steps.decide.outputs.version }}
dry_run: ${{ steps.mode.outputs.dry_run }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: mode
# Off main every run is a dry run (a launcher branch's push only builds).
run: echo "dry_run=${{ github.ref != 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && inputs.dry_run) }}" >> "$GITHUB_OUTPUT"
- id: decide
env:
GH_TOKEN: ${{ github.token }}
RELEASES_PAUSED: ${{ vars.RELEASES_PAUSED }}
# A push or a run off main builds its own commit; otherwise main's newest commit with green checks.
HEAD_SHA: ${{ (github.event_name == 'push' || steps.mode.outputs.dry_run == 'true') && github.sha || '' }}
FORCE: ${{ inputs.force && 'yes' || '' }}
run: |
python3 tools/release_train.py decide --kind launcher ${HEAD_SHA:+--head "$HEAD_SHA"} ${FORCE:+--force} | tee decision.json
echo "### $(jq -r '.reason' decision.json)" >> "$GITHUB_STEP_SUMMARY"
tag=$(jq -r '.tag' decision.json)
echo "version=${tag#launcher-v}" >> "$GITHUB_OUTPUT"
# A dry run (and a launcher branch's push) builds whatever the decision.
if [[ "${{ steps.mode.outputs.dry_run }}" == true ]]; then
echo "release=true" >> "$GITHUB_OUTPUT"
echo "head=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
fi
build:
needs: decide
if: needs.decide.outputs.release == 'true'
name: build ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: linux
os: ubuntu-22.04
asset: horizon-launcher-linux-x86_64.tar.gz
binary: horizon-launcher
- name: macos
mac: true
asset: horizon-launcher-macos-arm64.zip
binary: horizon-launcher
- name: windows
os: windows-latest
asset: horizon-launcher-windows-x64.zip
binary: horizon-launcher.exe
# The C runtime linked in: without it the launcher asks for VCRUNTIME140.dll,
# which only the Visual C++ redistributable installs.
rustflags: -C target-feature=+crt-static
runs-on: ${{ matrix.mac && (vars.MAC_RUNNER || 'ludovics-mac-mini') || matrix.os }}
timeout-minutes: 40
env:
RUSTFLAGS: ${{ matrix.rustflags }}
# Horizon's Azure app for Microsoft sign-in (docs/microsoft-account.md): a repository
# variable, not a secret. Unset, the launcher says sign-in is not configured.
HORIZON_MSA_CLIENT_ID: ${{ vars.HORIZON_MSA_CLIENT_ID }}
# The release's version, built in (launcher/src/backend.rs VERSION); a launcher branch's build keeps
# Cargo.toml's.
HORIZON_LAUNCHER_VERSION: ${{ (github.event_name != 'push' || github.ref == 'refs/heads/main') && needs.decide.outputs.version || '' }}
defaults:
run:
working-directory: launcher
shell: bash
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.decide.outputs.head }}
persist-credentials: false
# The Mac mini's runner keeps its target/ between runs.
clean: ${{ runner.environment == 'github-hosted' }}
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
if: runner.environment == 'github-hosted'
with:
workspaces: launcher
shared-key: launcher-${{ matrix.name }}
- name: Linux libraries GPUI links to
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libxkbcommon-x11-dev libwayland-dev libx11-xcb-dev libfontconfig-dev libvulkan-dev libasound2-dev
- name: Metal shaders compiled now, or at run time without the Metal toolchain
# GPUI compiles its Metal shaders when it builds; the Mac mini has Xcode without the Metal toolchain
# (xcodebuild -downloadComponent MetalToolchain), so there they are compiled when the launcher starts.
if: runner.os == 'macOS'
run: |
if ! xcrun metal --version > /dev/null 2>&1; then
echo "::notice::No Metal toolchain on this runner: GPUI compiles its shaders at run time"
echo "LAUNCHER_FEATURES=gpui/runtime_shaders" >> "$GITHUB_ENV"
fi
- run: cargo test --release --locked --lib ${LAUNCHER_FEATURES:+--features "$LAUNCHER_FEATURES"}
- run: cargo build --release --locked ${LAUNCHER_FEATURES:+--features "$LAUNCHER_FEATURES"}
- name: The version is the release's
run: |
out=$(target/release/${{ matrix.binary }} --version)
echo "$out"
expected="${HORIZON_LAUNCHER_VERSION:-$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)}"
[[ "$out" == "horizon-launcher $expected" ]] || { echo "::error::expected horizon-launcher $expected"; exit 1; }
- name: Only system libraries
run: |
file=target/release/${{ matrix.binary }}
case "$RUNNER_OS" in
Windows) python ../tools/check_imports.py "$file" ;;
macOS) others=$(otool -L "$file" | tail -n +2 | awk '{print $1}' | grep -v -E '^(/usr/lib/|/System/Library/)' || true)
[[ -z "$others" ]] || { echo "::error::links $others"; exit 1; } ;;
esac
- name: Smoke test
env:
HORIZON_LAUNCHER_NO_SELF_UPDATE: '1'
HORIZON_GITHUB_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
export HORIZON_LAUNCHER_HOME="${RUNNER_TEMP//\\//}/horizon-launcher-smoke"
export HORIZON_HOME="$HORIZON_LAUNCHER_HOME/game"
rm -rf "$HORIZON_LAUNCHER_HOME"
launcher="$PWD/target/release/${{ matrix.binary }}"
# GitHub's API rate-limits shared runner addresses now and then: try a few times.
retry() { for i in 1 2 3 4; do "$@" && return 0; sleep $((i * 15)); done; return 1; }
retry "$launcher" versions
retry "$launcher" install latest
"$launcher" versions --installed
"$launcher" links --json
"$launcher" menu-style classic
grep -qx 'menuStyle:classic' "$HORIZON_HOME/horizon.txt"
"$launcher" menu-style horizon
clients=("$HORIZON_LAUNCHER_HOME"/versions/v*/horizon-client*)
client="${clients[0]}"
echo "installed client: $client"
# The game's Linux build is the game's to keep portable (release.yml checks it): a
# release linked to a Nix store is a warning here, not a broken launcher.
soft() { if [[ "$RUNNER_OS" == "Linux" ]]; then "$@" || echo "::warning::$* failed"; else "$@"; fi; }
if [[ "$RUNNER_OS" == "Windows" ]]; then
python ../tools/check_imports.py "$client"
elif [[ "$RUNNER_OS" == "Linux" ]]; then
soft python3 ../tools/check_imports.py "$client"
fi
# The client starts: --help prints before any window or GPU is needed.
help() { "$client" --help > "$RUNNER_TEMP/help.txt" 2>&1 && head -3 "$RUNNER_TEMP/help.txt" && grep -q -- '--resources' "$RUNNER_TEMP/help.txt"; }
soft help
rm -rf "$HORIZON_LAUNCHER_HOME"
- name: Package
run: |
rm -rf dist out && mkdir -p out
if [[ "$RUNNER_OS" == "macOS" ]]; then
# Horizon.app, zipped (self-update) and in a .dmg (installer): packaging/macos.
python3 -m venv "$RUNNER_TEMP/dmg" && "$RUNNER_TEMP/dmg/bin/pip" install --quiet dmgbuild==1.6.5
version=${HORIZON_LAUNCHER_VERSION:-$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)}
DMGBUILD="$RUNNER_TEMP/dmg/bin/dmgbuild" ../packaging/macos/package.sh target/release/${{ matrix.binary }} "$version" out
rm -rf out/Horizon.app
else
mkdir -p dist
cp target/release/${{ matrix.binary }} dist/
if [[ "${{ matrix.asset }}" == *.tar.gz ]]; then
(cd dist && tar czf ../out/${{ matrix.asset }} ${{ matrix.binary }})
else
(cd dist && 7z a ../out/${{ matrix.asset }} ${{ matrix.binary }})
fi
fi
ls -l out
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset }}
path: launcher/out/*
retention-days: 3
release:
needs: [decide, build]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Notes
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 tools/release_train.py notes --kind launcher --tag "${{ needs.decide.outputs.tag }}" \
--head "${{ needs.decide.outputs.head }}" --out notes > /dev/null
{ echo "## $(cat notes/title.txt)"; echo; cat notes/body.md; } >> "$GITHUB_STEP_SUMMARY"
- uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
# Never marked latest: Horizon's own releases stay the repository's latest.
- name: Publish ${{ needs.decide.outputs.tag }}
if: needs.decide.outputs.dry_run != 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.decide.outputs.tag }}
run: |
gh release create "$TAG" --target "${{ needs.decide.outputs.head }}" --title "$(cat notes/title.txt)" \
--notes-file notes/body.md --latest=false dist/horizon-launcher-*
- name: Dry run, the release that would be published
if: needs.decide.outputs.dry_run == 'true'
run: |
echo "Would publish ${{ needs.decide.outputs.tag }} at ${{ needs.decide.outputs.head }}: $(cat notes/title.txt)"
ls -l dist
- uses: actions/upload-artifact@v4
with:
name: launcher-release-notes
path: notes/
retention-days: 3
@@ -1,46 +0,0 @@
name: macOS shader research
on:
workflow_dispatch:
permissions:
contents: read
jobs:
shader-worlds:
runs-on: macos-26
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '25'
- name: Build original mod and private probe dependencies
run: python tools/build_mod.py
- name: Verify required cinematic shaders in OpenGL and Vulkan worlds
run: |
python - <<'PY'
import json, subprocess, sys
from pathlib import Path
observations = []
for backend in ['opengl', 'vulkan']:
case = ['--profile', 'cinematic', '--backend', backend, '--world', '--shaders']
result = subprocess.run([sys.executable, 'tools/test_client_graphics.py', '--native-display', *case], capture_output=True, text=True)
print(result.stdout, end='', flush=True)
print(result.stderr, end='', flush=True)
observation = {'case': case, 'exit_code': result.returncode}
if result.returncode:
marker = 'HORIZON_FIXTURE_FAILURE '
observation['failure'] = [json.loads(line.split(marker, 1)[1]) for line in result.stdout.splitlines() if marker in line]
else:
observation['report'] = json.loads(Path('dist/client-graphics-smoke.json').read_text())
observations.append(observation)
Path('dist/client-graphics-shader-research.json').write_text(json.dumps(observations, indent=2) + '\n')
sys.exit(int(any(item['exit_code'] for item in observations)))
PY
- name: Retain selected observations including failed cases
if: always()
uses: actions/upload-artifact@v4
with:
name: macos-shader-observations
path: dist/client-graphics-shader-research.json
@@ -1,59 +0,0 @@
name: macOS Vulkan research
on:
workflow_dispatch:
inputs:
world:
description: Create or open disposable demo worlds instead of title probes
type: boolean
default: false
permissions:
contents: read
jobs:
native-probes:
runs-on: macos-26
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '25'
- name: Build original mod and private probe dependencies
run: python tools/build_mod.py
- name: Probe vanilla, core and distant-terrain Vulkan cases
env:
HORIZON_GRAPHICS_WORLD: ${{ inputs.world }}
run: |
python - <<'PY'
import json, os, subprocess, sys
from pathlib import Path
cases = [
['--profile', 'baseline', '--backend', 'vulkan'],
['--profile', 'core-performance', '--backend', 'vulkan'],
['--profile', 'vulkan'],
]
if os.environ.get('HORIZON_GRAPHICS_WORLD') == 'true':
cases = [case + ['--world'] for case in cases]
observations = []
for case in cases:
result = subprocess.run([sys.executable, 'tools/test_client_graphics.py', '--native-display', *case], capture_output=True, text=True)
print(result.stdout, end='', flush=True)
print(result.stderr, end='', flush=True)
observation = {'case': case, 'exit_code': result.returncode}
if result.returncode:
marker = 'HORIZON_FIXTURE_FAILURE '
observation['failure'] = [json.loads(line.split(marker, 1)[1]) for line in result.stdout.splitlines() if marker in line]
else:
observation['report'] = json.loads(Path('dist/client-graphics-smoke.json').read_text())
observations.append(observation)
Path('dist/client-graphics-vulkan-research.json').write_text(json.dumps(observations, indent=2) + '\n')
sys.exit(int(any(item['exit_code'] for item in observations)))
PY
- name: Retain selected observations including failed cases
if: always()
uses: actions/upload-artifact@v4
with:
name: macos-vulkan-observations
path: dist/client-graphics-vulkan-research.json
+79
View File
@@ -0,0 +1,79 @@
name: nightly audit
# Every vanilla harness, from scratch, on main, at 03:00 Paris time on the Mac mini's runner (it holds the
# maintainer's own Minecraft files). The resources are prepared again first when the preparer or its exporters
# changed (tools/ci/vanilla-data.sh). A harness that passed in the previous audit and fails now gets an issue
# labelled parity-regression (one per harness); its issue closes when it passes again
# (tools/ci/parity_issues.py). The bugs session picks those up. See docs/release-flow.md.
# gh workflow run "nightly audit" # now
# gh workflow run "nightly audit" -f dry_run=true # the audit, without touching issues
on:
schedule:
# GitHub's schedules are in UTC: both, and the first step keeps the one that is 03:00 in Paris.
- cron: '7 1 * * *'
- cron: '7 2 * * *'
workflow_dispatch:
inputs:
dry_run:
description: Run the audit, but only print what it would do with issues
type: boolean
default: false
permissions:
contents: read
issues: write
concurrency:
group: nightly-audit
cancel-in-progress: false
jobs:
audit:
runs-on: [self-hosted, horizon-game]
timeout-minutes: 150
steps:
- name: 03:00 in Paris
id: when
run: |
hour=$(TZ=Europe/Paris date +%H)
if [[ "${{ github.event_name }}" == schedule && "$hour" != 03 ]]; then
echo "It is ${hour}:00 in Paris: the other schedule runs the audit."
echo "run=false" >> "$GITHUB_OUTPUT"
else
echo "run=true" >> "$GITHUB_OUTPUT"
fi
- uses: actions/checkout@v4
if: steps.when.outputs.run == 'true'
with:
fetch-depth: 0
persist-credentials: false
# Keeps .local/ (parity state, probe builds, the previous audit) and target/.
clean: false
- uses: dtolnay/rust-toolchain@stable
if: steps.when.outputs.run == 'true'
- name: Tools from the runner
if: steps.when.outputs.run == 'true'
run: bash tools/ci/runner-env.sh
- name: Vanilla data, prepared again if the preparer changed
if: steps.when.outputs.run == 'true'
run: bash tools/ci/vanilla-data.sh
- name: Every harness
id: audit
if: steps.when.outputs.run == 'true'
env:
PARITY_HOSTS: ''
run: |
echo "since=$(date +%Y-%m-%dT%H:%M:%S)" >> "$GITHUB_OUTPUT"
set +e
python3 tools/parity.py --all --timeout 1800 2>&1 | tee "$RUNNER_TEMP/audit.log"
echo "exit=${PIPESTATUS[0]}" >> "$GITHUB_OUTPUT"
{ echo '```'; tail -40 "$RUNNER_TEMP/audit.log"; echo '```'; } >> "$GITHUB_STEP_SUMMARY"
- name: Issues for the harnesses that regressed
if: steps.when.outputs.run == 'true' && always() && steps.audit.outputs.since
env:
GH_TOKEN: ${{ github.token }}
run: python3 tools/ci/parity_issues.py --since "${{ steps.audit.outputs.since }}" ${{ inputs.dry_run && '--dry-run' || '' }} | tee -a "$GITHUB_STEP_SUMMARY"
- name: Logs of the failed harnesses
if: steps.when.outputs.run == 'true' && steps.audit.outputs.exit != '0'
uses: actions/upload-artifact@v4
with:
name: nightly-parity-logs
path: .local/parity-runner/logs/
if-no-files-found: ignore
retention-days: 7
+225
View File
@@ -0,0 +1,225 @@
name: release
# Automatic game releases (docs/release-flow.md). After every green `checks` run on main, every 10 minutes (so a
# release waiting for merges to settle goes out without another merge) and by hand, tools/release_train.py decides:
# a release when pull requests merged since the last one changed what players run and the newest merged 15 minutes
# ago (the oldest an hour ago, if merges never pause), or at once for a pull request labelled release-now.
# RELEASES_PAUSED=1 (repository variable) stops them.
# Builds Linux (an older Ubuntu, so the binary runs on any recent distribution and on NixOS through nix-ld) and
# Windows on GitHub, macOS on the Mac mini's runner (MAC_RUNNER=macos-latest sends it to GitHub), then
# publishes vYYYY.MM.DD[.N] with notes from the merged pull requests.
# gh workflow run release --ref <branch> # dry run: builds and notes, publishes nothing
# gh workflow run release -f dry_run=false -f force=true # on main: release now, whatever the rules say
on:
workflow_run:
workflows: [checks]
types: [completed]
branches: [main]
schedule:
- cron: '2-59/10 * * * *'
workflow_dispatch:
inputs:
dry_run:
description: Build everything and write the notes, but publish nothing
type: boolean
default: true
force:
description: Release even without player-facing changes, before merges settle or while paused
type: boolean
default: false
permissions:
contents: read
concurrency:
group: game-release
cancel-in-progress: false
jobs:
decide:
if: >-
github.event_name != 'workflow_run' ||
(github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push')
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
release: ${{ steps.decide.outputs.release }}
tag: ${{ steps.decide.outputs.tag }}
head: ${{ steps.decide.outputs.head }}
dry_run: ${{ steps.mode.outputs.dry_run }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: mode
# A dry run never publishes; a hand-started run off main is always one.
run: echo "dry_run=${{ github.event_name == 'workflow_dispatch' && (inputs.dry_run || github.ref != 'refs/heads/main') }}" >> "$GITHUB_OUTPUT"
- id: decide
env:
GH_TOKEN: ${{ github.token }}
RELEASES_PAUSED: ${{ vars.RELEASES_PAUSED }}
# The commit whose checks just passed; a dry run builds the branch it was started on; otherwise
# main's newest commit with green checks.
HEAD_SHA: ${{ github.event.workflow_run.head_sha || (steps.mode.outputs.dry_run == 'true' && github.sha) || '' }}
FORCE: ${{ inputs.force && 'yes' || '' }}
run: |
python3 tools/release_train.py decide --kind game ${HEAD_SHA:+--head "$HEAD_SHA"} ${FORCE:+--force} | tee decision.json
echo "### $(jq -r '.reason' decision.json)" >> "$GITHUB_STEP_SUMMARY"
# A dry run builds whatever the decision, to test the builds.
if [[ "${{ steps.mode.outputs.dry_run }}" == true ]]; then echo "release=true" >> "$GITHUB_OUTPUT"; fi
build:
needs: decide
if: needs.decide.outputs.release == 'true'
name: build ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: linux
os: ubuntu-22.04
dir: horizon-linux-x86_64
asset: horizon-linux-x86_64.tar.gz
- name: windows
os: windows-latest
dir: horizon-windows-x64
asset: horizon-windows-x64.zip
exe: .exe
# The C runtime linked in, so the game runs without the Visual C++ redistributable.
rustflags: -C target-feature=+crt-static
- name: macos
mac: true
dir: horizon-macos-arm64
asset: horizon-macos-arm64.zip
runs-on: ${{ matrix.mac && (vars.MAC_RUNNER || 'ludovics-mac-mini') || matrix.os }}
timeout-minutes: 40
env:
RUSTFLAGS: ${{ matrix.rustflags }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.decide.outputs.head }}
persist-credentials: false
# On the Mac mini's runner, keep target/ (incremental) and .local/ (the prepared resources).
clean: ${{ runner.environment == 'github-hosted' }}
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
if: runner.environment == 'github-hosted'
with:
shared-key: release-${{ matrix.name }}
- name: ALSA and udev headers
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
- name: Build the client, horizon-ctl and horizon-prepare
run: cargo build --release --locked -p horizon-client --bin horizon-client --bin horizon-ctl -p horizon-prepare --bin horizon-prepare
- name: Every program the release folder takes was built
run: |
for binary in horizon-client horizon-ctl horizon-prepare; do
test -f "target/release/$binary${{ matrix.exe }}" || { echo "::error::target/release/$binary${{ matrix.exe }} is missing"; exit 1; }
done
- name: Only system libraries
# Windows: no non-system DLL (a "DLL not found" dialog on some players' machines). Linux: the standard
# loader and libraries every desktop distribution has. macOS: only the system's own libraries.
run: |
for binary in horizon-client horizon-ctl horizon-prepare; do
file="target/release/$binary${{ matrix.exe }}"
if [[ "$RUNNER_OS" == macOS ]]; then
others=$(otool -L "$file" | tail -n +2 | awk '{print $1}' | grep -v -E '^(/usr/lib/|/System/Library/)' || true)
[[ -z "$others" ]] || { echo "::error::$binary links $others"; exit 1; }
else
${{ runner.os == 'Windows' && 'python' || 'python3' }} tools/check_imports.py "$file"
fi
done
- name: Every program starts
run: |
set -euo pipefail
bin=target/release
"$bin/horizon-client${{ matrix.exe }}" --help | grep -q -- '--resources'
"$bin/horizon-ctl${{ matrix.exe }}" --help > /dev/null
"$bin/horizon-prepare${{ matrix.exe }}" --version
"$bin/horizon-prepare${{ matrix.exe }}" --help | grep -q -- '--minecraft-dir'
- name: Tools from the runner
if: runner.environment == 'self-hosted'
run: bash tools/ci/runner-env.sh
- name: Resources prepared from the runner's own Minecraft
if: runner.environment == 'self-hosted'
run: bash tools/ci/vanilla-data.sh
- name: The game runs (offscreen, a new world, 1500 frames)
if: runner.environment == 'self-hosted'
run: |
set -euo pipefail
# From a scratch folder: the game keeps its saves and options in the folder it starts in.
home="$RUNNER_TEMP/horizon-smoke"
rm -rf "$home" && mkdir -p "$home"
version=$(sed -n 's/.*"version": *"\([^"]*\)".*/\1/p' research-lock.json | head -1)
client="$PWD/target/release/horizon-client"
resources="$PWD/.local/horizon-client/$version"
(cd "$home" && HORIZON_HOME="$home" HORIZON_NO_AUDIO=1 "$client" --resources "$resources" --offscreen \
--world smoke --seed 1 --render-distance 4 --frames 1500 --timeout-seconds 180 \
--smoke-report "$home/smoke.json" > "$home/client.log" 2>&1) || { tail -40 "$home/client.log"; exit 1; }
python3 - "$home/smoke.json" <<'EOF'
import json, sys
report = json.load(open(sys.argv[1]))
print(json.dumps(report))
if report.get("error") is not None or report.get("frames", 0) < 1500 or not report.get("chunks") \
or not report.get("meshed_sections") or not report.get("player"):
sys.exit("the smoke run did not draw a world")
EOF
- name: Package
run: |
set -euo pipefail
cargo run --locked -p xtask -- package "target/release/horizon-client${{ matrix.exe }}" "dist/${{ matrix.dir }}"
cd dist
rm -f "${{ matrix.asset }}"
case "${{ matrix.asset }}" in
*.tar.gz) tar czf "${{ matrix.asset }}" "${{ matrix.dir }}" ;;
*) if [[ "$RUNNER_OS" == Windows ]]; then 7z a -tzip "${{ matrix.asset }}" "${{ matrix.dir }}" > /dev/null
else ditto -c -k --keepParent "${{ matrix.dir }}" "${{ matrix.asset }}"; fi ;;
esac
ls -l "${{ matrix.asset }}"
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset }}
path: dist/${{ matrix.asset }}
if-no-files-found: error
retention-days: 3
publish:
needs: [decide, build]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Notes
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 tools/release_train.py notes --kind game --tag "${{ needs.decide.outputs.tag }}" \
--head "${{ needs.decide.outputs.head }}" --out notes > /dev/null
{ echo "## $(cat notes/title.txt)"; echo; cat notes/body.md; } >> "$GITHUB_STEP_SUMMARY"
- uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: Publish ${{ needs.decide.outputs.tag }}
if: needs.decide.outputs.dry_run != 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.decide.outputs.tag }}
run: |
gh release create "$TAG" --target "${{ needs.decide.outputs.head }}" --title "$(cat notes/title.txt)" \
--notes-file notes/body.md --latest dist/horizon-linux-x86_64.tar.gz dist/horizon-windows-x64.zip \
dist/horizon-macos-arm64.zip
- name: Dry run, the release that would be published
if: needs.decide.outputs.dry_run == 'true'
run: |
echo "Would publish ${{ needs.decide.outputs.tag }} at ${{ needs.decide.outputs.head }}: $(cat notes/title.txt)"
ls -l dist
- uses: actions/upload-artifact@v4
with:
name: release-notes
path: notes/
retention-days: 3
+34
View File
@@ -0,0 +1,34 @@
name: telemetry-server
# The ingest server is its own workspace (crates/horizon-telemetry-server), so the checks job doesn't build
# it: this one does, when it or the crate it shares with the launcher and the game changes.
on:
push:
branches: [main]
paths:
- 'crates/horizon-telemetry/**'
- 'crates/horizon-telemetry-server/**'
- '.github/workflows/telemetry-server.yml'
pull_request:
paths:
- 'crates/horizon-telemetry/**'
- 'crates/horizon-telemetry-server/**'
- '.github/workflows/telemetry-server.yml'
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
working-directory: crates/horizon-telemetry-server
steps:
- uses: actions/checkout@v4
- run: rustup toolchain install stable --profile minimal --component rustfmt --component clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: crates/horizon-telemetry-server
save-if: ${{ github.ref == 'refs/heads/main' }}
- run: cargo +stable fmt --check
- run: cargo +stable clippy --all-targets --locked -- -D warnings
- run: cargo +stable test --locked
+12
View File
@@ -16,3 +16,15 @@
/dist/
/mods/horizon/build/
/saves/
/backups/
/tools/logs/
.DS_Store
# What the client writes to its working directory when run from the repo root.
/options.txt
/horizon.txt
/horizon-graphics.txt
/horizon-controller.txt
/servers.dat
/screenshots/
/crash-reports/
/debug/
+77
View File
@@ -0,0 +1,77 @@
# Contributing to Horizon
Thanks for helping. Horizon is Minecraft: Java Edition 26.3 rewritten in Rust, and the one rule that shapes
everything is that **it plays exactly like vanilla**. This page is the short version of how we work; questions are
welcome on [Discord](https://discord.gg/HcTeMZxe5E).
## Build it
You need Rust (stable), Python 3.10+, JDK 25, and on Linux the ALSA and udev headers (`libasound2-dev libudev-dev`).
Horizon never downloads the game: it prepares its resources from your own copy of Minecraft 26.3, as described in
[Build from source](README.md#build-from-source).
```sh
cargo run --release -p horizon-prepare -- --prepare --server-jar ~/Downloads/server.jar
cargo run --release -p horizon-client
```
The launcher is its own Cargo workspace in `launcher/` (`cd launcher && cargo run`; on NixOS, `nix-shell` first).
## Vanilla first
Wherever vanilla has a feature, vanilla is the specification, down to the order of random calls. "Parity" here
means Horizon gives the same results as the pinned 26.3 client and server for the same inputs, checked by a
**harness**: a `tools/test_*_parity.py` script that runs a small Java oracle against the real game and a Rust
probe against Horizon, and compares their outputs. There are about 290 of them.
- **Read the vanilla code before writing Horizon's.** `tools/rea_vanilla.py` queries the pinned game bytecode:
`python3 tools/rea_vanilla.py method net.minecraft.world.level.block.DispenserBlock dispenseFrom`.
Say in your pull request which vanilla classes and methods you followed.
- **Gameplay changes come with a harness**, new or extended, so the next change can't silently break them.
[The parity workflow](docs/parity-workflow.md) shows how harnesses run; copy a nearby one.
- **Horizon's own features** (the launcher, the new menus) follow [the design system](docs/design-system.md) and are
off by default wherever they would change the vanilla look.
- **Everything players run is Rust.** Python and Java are fine for dev tools and harness drivers in `tools/`, never
for player-facing code.
Never commit game files, decompiled source or prepared resources (`.local/`): `tools/check_public_tree.py` rejects
them (`git config core.hooksPath .githooks` runs it before every commit).
## Before asking for review
Run the self-check and paste the block it prints into your pull request:
```sh
python3 tools/pr_ready.py --base upstream/main # or origin/main if you work on the main repository
```
It looks at what your branch changes and runs what matters: rustfmt, clippy with warnings denied, the tests of the
crates you touched (and the launcher's), generated files, `Cargo.lock`, the Python tests, and the vanilla harnesses
your change can affect. Without the vanilla data on your machine it lists those harnesses instead; CI runs them.
`--quick` skips the harnesses. It exits non-zero when something fails.
## Pull requests
- **Small.** One change per pull request, under about 500 lines of code where you can; split bigger work into
pieces that each make sense alone. Small pull requests get reviewed and merged the same day.
- **Fill in the template**: what and why, the vanilla reference, the pr_ready block, screenshots for anything you
can see.
- **Tick "Allow edits by maintainers".** When something small is left (a lint, a rebase, a nit) we push the fixup
ourselves instead of sending it back to you; only design questions come back.
- **Labels** (we set them if you can't): `feature` when players get something new (it appears under "New" in the
release notes), `skip-release` when players see no change (tooling, docs, tests), nothing for a fix.
`release-now` is for crash fixes that shouldn't wait. pr_ready suggests one.
Every merge to main is released automatically ([release flow](docs/release-flow.md)), so main always stays playable.
## Parity checks on forks
The `verify` check (formatting, lints, tests) runs on every pull request. The `parity` check runs the affected
harnesses on a maintainer's machine, which holds the game files, so it never runs a fork's code on its own: a
maintainer reads your change, then adds the `run-parity` label, which runs it once on your current commit. After
new pushes, we add it again.
## Talk to us
[Discord](https://discord.gg/HcTeMZxe5E) for questions and ideas, [issues](https://github.com/ludovic111/horizon/issues)
for bugs. If you want to take something on, say so in its issue so nobody else starts the same work.
Generated
+1142 -4
View File
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -1,5 +1,6 @@
[workspace]
members = ["crates/horizon-core", "crates/horizon-world", "crates/voxel-kernels", "crates/horizon-client", "crates/horizon-assets", "crates/horizon-protocol"]
exclude = ["launcher", "crates/horizon-telemetry-server"]
members = ["crates/horizon-core", "crates/horizon-world", "crates/voxel-kernels", "crates/horizon-client", "crates/horizon-assets", "crates/horizon-protocol", "crates/horizon-theme", "crates/horizon-prepare", "crates/horizon-telemetry", "crates/horizon-bench", "crates/horizon-friends", "crates/horizon-relay", "xtask"]
resolver = "2"
[workspace.package]
+171 -304
View File
@@ -1,337 +1,204 @@
<p align="center">
<img src="docs/media/banner.webp" alt="Horizon: Minecraft: Java Edition 26.3, rewritten in Rust and checked against vanilla by 281 differential harnesses" width="100%">
</p>
<p align="center">
<a href="https://github.com/ludovic111/horizon/actions/workflows/ci.yml"><img src="https://github.com/ludovic111/horizon/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
<img src="https://img.shields.io/badge/Minecraft-Java%2026.3-5D9C3F" alt="Minecraft Java 26.3">
<img src="https://img.shields.io/badge/Rust-stable-B7410E?logo=rust&logoColor=white" alt="Rust">
<img src="https://img.shields.io/badge/vanilla%20parity-100%25-F0795A" alt="Vanilla parity 100%">
<img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-2A2470" alt="Linux, macOS and Windows">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-3B2F7E" alt="MIT license"></a>
</p>
<p align="center">
<a href="https://playhorizon.dev"><b>Website</b></a> ·
<a href="#download"><b>Download</b></a> ·
<a href="#what-changed-in-v202610131"><b>What changed</b></a> ·
<a href="#screenshots"><b>Screenshots</b></a> ·
<a href="#project-status"><b>Parity status</b></a> ·
<a href="docs/README.md"><b>Documentation</b></a>
</p>
# Horizon
Horizon is a Rust rewrite of Minecraft Java **26.3** targeting one-to-one vanilla gameplay parity, alongside client performance research. Not affiliated with Mojang or Microsoft.
A Rust rewrite of Minecraft: Java Edition 26.3 built for one-to-one vanilla parity, checked against the game itself with differential tests.
Every subsystem matches vanilla in all 281 parity harnesses, on Linux and macOS: 100% of what the harnesses compare (see [Project status](#project-status)). The native client is playable on Linux, macOS (Apple Silicon) and Windows.
> Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft. Horizon contains no Minecraft code, assets or data: you need your own legally obtained copy of Minecraft: Java Edition 26.3.
## What changed in v2026.10.13.1
The latest release ([notes](https://github.com/ludovic111/horizon/releases/tag/v2026.10.13.1)):
- **Horizon's own menus:** a new title screen, world list, options and pause menu in the launcher's style, over a live frozen landscape. The vanilla look is still available: Options → Interface → Menu style → Classic.
- **Graphics settings, Simple and Advanced:** presets (Performance, Balanced, Quality, Ultra), or every rendering, quality, display and performance setting, each with a short description and its cost, plus a performance overlay.
- **Much faster rendering:** for example, at render distance 8 over a village, 363 → 2,409 FPS on an RTX 4080. Render distance 32 still stutters in places.
- **Fixed:** no sound on Linux; Linux builds that only ran on the machine they were built on; a missing DLL on Windows (the launcher no longer needs the Visual C++ runtime); memory growing and the frame rate dropping near villages (mobs were duplicated when chunks reloaded); resource preparation failing on Linux with "Missing … java-objc-bridge" ([#41](https://github.com/ludovic111/horizon/issues/41)); the hand and held item at high FOV; missing swing animations.
## Download
Horizon is downloaded only through **the Horizon launcher**: get it from [playhorizon.dev](https://playhorizon.dev) or from [the launcher's releases](https://github.com/ludovic111/horizon/releases?q=launcher-v&expanded=true) (the newest `launcher-v*` release, currently [launcher-v0.1.3](https://github.com/ludovic111/horizon/releases/tag/launcher-v0.1.3)), for Linux x86-64, macOS Apple Silicon or Windows x64. The launcher installs and updates the game, prepares its resources from your own copy of Minecraft, starts the client or a dedicated server, and updates itself.
**You need** Minecraft: Java Edition installed with the official launcher, with 26.3 played once; Python 3.10 or newer and Java 25 (a JDK, e.g. Eclipse Temurin 25) for the one-time resource preparation; and a GPU with Vulkan on Linux and Windows, or any Apple Silicon Mac.
### The launcher
<table>
<tr>
<td width="50%"><img src="docs/media/launcher-play.webp" alt="The launcher's Play page: v2026.10.14.1 ready to play, its summary, Client and Server, the version picker and Play, the resources and the Minecraft folder as a numbered list"></td>
<td width="50%"><img src="docs/media/launcher-patch-notes.webp" alt="The launcher's Patch notes page, showing the notes of Horizon 2026.10.14.1"></td>
</tr>
</table>
It lists Horizon's releases and installs the build for your platform, shows each release's patch notes, updates Horizon and itself, and doubles as a command-line tool and an MCP server. See [the launcher's README](launcher/README.md).
## Screenshots
Captured in the Rust client itself, with vanilla assets and no mods or shaders.
### Menus and settings
<table>
<tr>
<td colspan="2"><img src="docs/media/menu-title.webp" alt="Horizon's title screen: the mark and the pages on the left, the Horizon title, Singleplayer and Multiplayer, and the last world played and the faint wordmark, over a veiled snowy landscape"></td>
</tr>
<tr>
<td width="50%"><img src="docs/media/menu-worlds.webp" alt="The Singleplayer page: three worlds with their dates and game modes, and Create world and Play buttons"></td>
<td width="50%"><img src="docs/media/settings.webp" alt="The Video settings in their Simple view: a preset, render distance, field of view, framerate, VSync and GUI scale, each with what it costs"></td>
</tr>
</table>
The vanilla menus are one setting away: Options → Interface → Menu style → Classic. See [Graphics settings](docs/graphics.md).
### In game
<table>
<tr>
<td colspan="2"><img src="docs/media/sunset.webp" alt="Sunset over a savanna river valley and a plains village"></td>
</tr>
<tr>
<td width="50%"><img src="docs/media/village.webp" alt="A plains village with farms, an iron golem and animals"></td>
<td width="50%"><img src="docs/media/survival.webp" alt="Survival at dusk: a zombie attacks near the village"></td>
</tr>
<tr>
<td width="50%"><img src="docs/media/nether.webp" alt="A crimson forest in the Nether with a zombified piglin"></td>
<td width="50%"><img src="docs/media/night.webp" alt="Moonrise over a torch-lit village and river"></td>
</tr>
<tr>
<td width="50%"><img src="docs/media/underwater.webp" alt="Salmon swimming in a river"></td>
<td width="50%" valign="middle">
Vanilla world generation ported to Rust (terrain, aquifers, carvers, features, villages and the Nether), every block model with smooth lighting and biome tints, the vanilla sky and fog, mobs, the HUD, chat and advancements: everything in these frames is drawn by Horizon.
</td>
</tr>
</table>
## What it does
Horizon reimplements the Minecraft Java client and its game logic in Rust, one subsystem at a time, and compares each piece with the vanilla game. Each `tools/test_*_parity.py` harness drives the same inputs through Horizon and through the vanilla client and server bytecode from your own copy of the game, then checks that the outputs are identical. It is for players and developers interested in game reimplementation, and for anyone who wants to see how far a behaviour-exact native rewrite can go.
The [native client](docs/native-client.md) opens on a vanilla-style title screen with world creation and selection, and generates worlds with the Rust port of the vanilla generators: noise terrain, aquifers, surface rules, carvers and placed features, all checked against vanilla. It streams and lights chunks on worker threads and renders every vanilla block model with smooth lighting, biome tints, the vanilla sky, sun, moon, stars and clouds. Gameplay includes:
**The Rust game is now playable.** The [native client](docs/native-client.md) opens on a vanilla-style title screen with world creation and selection, and generates worlds with the Rust port of the vanilla overworld generator: noise terrain, aquifers, surface rules, carvers, and the placed features ported so far, all checked against vanilla. It streams and lights chunks on worker threads and renders every vanilla block model with smooth lighting, biome tints, the vanilla sky, sun, moon, stars and clouds. Gameplay so far:
- validated player physics, health and hunger;
- mining with vanilla tool rules and loot tables;
- placing, crafting, chests and furnaces;
- dropped items and particles;
- sounds;
- passive and hostile mobs with combat, including guardians, shulkers, illagers, ravagers, the wither and the ender dragon fight;
- villagers that take jobs, trade, restock, meet at the bell and sleep in beds;
- dropped items, particles and sounds;
- passive and hostile mobs with combat and vanilla AI, including guardians, shulkers, illagers, ravagers, the wither, the ender dragon fight, the breeze, the creaking, the sniffer, the happy ghast, llamas and the copper golem;
- villagers that take jobs, trade, restock, meet at the bell and sleep in beds, on a port of vanilla's brain;
- raids and pillager patrols;
- dispensers, crafters, the loom and the recipe book;
- every command, scoreboards and teams, the player list, subtitles and the HUD overlays;
- boats, minecarts, item frames, paintings and armor stands;
- shields, maps, books, fireworks, beacons, advancements and statistics;
- Anvil saves.
- Anvil saves, joining vanilla servers, and opening a world to LAN.
Parity is **not** complete. Still missing: the warden and the sculk family, the breeze, sniffer, creaking, happy ghast, llamas and a few other mobs, raids and pillager patrols, villager breeding and gossip, the loom, crafter and recipe book, scoreboards, subtitles, and spawned mob gear enchantments. Multiplayer joins vanilla servers but Horizon cannot host one. See [Rust rewrite status](docs/rust-parity.md).
## Agent control
### Java parity: 84%
AI agents and scripts can play Horizon. `horizon-ctl`, shipped beside the game in every release folder, is a command line that reads the game as JSON and acts like a player; `horizon-ctl mcp` serves the same commands as an MCP server (one tool per command, screenshots returned as images).
```sh
horizon-ctl launch --world Survival --seed 5 --wait # finds the version the launcher installed
horizon-ctl state # position, health, food, target, screen...
horizon-ctl find-block birch_log # the nearest logs
horizon-ctl goto -0.5 65 -2.5 --near 2.5 # walks there along a path
horizon-ctl break -1 65 -3 # mines it; replies with the drops
horizon-ctl open-inventory && horizon-ctl click-slot 0 # menus: slots, buttons by label, text fields
```
Commands block until the action is done and reply with what happened; errors are JSON with distinct exit codes, `horizon-ctl help` lists every command and `horizon-ctl COMMAND --help` explains one with examples. It talks to the game over a Unix socket on Linux and macOS and over a token-protected localhost port on Windows. See [Agent control in the native client guide](docs/native-client.md#agent-control-horizon-ctl-and-mcp).
## Build from source
For developers. Requirements: Rust 1.90 or newer, Python 3.10 or newer, JDK 25, and on Linux the ALSA and udev development headers (`libasound2-dev libudev-dev` on Debian and Ubuntu). Development and the vanilla harnesses run on Linux.
Horizon contains no game files and never downloads them. It builds its resources from **your own copy** of Minecraft: Java Edition 26.3, verified against the checksums in `research-lock.json`:
1. **Client:** install Java Edition with the official launcher and play 26.3 once. Horizon reads `versions/26.3/`, `libraries/` and `assets/` from the launcher's game directory (`~/.minecraft` on Linux). If yours lives elsewhere, pass `--minecraft-dir` or set `HORIZON_MINECRAFT_DIR`.
2. **Server jar:** the 26.3 server jar, from the `downloads.server.url` in your launcher's `versions/26.3/26.3.json` (or [minecraft.net/download/server](https://www.minecraft.net/en-us/download/server) while 26.3 is the current release). Pass it with `--server-jar` or set `HORIZON_SERVER_JAR`. It is only needed the first time.
```sh
git clone https://github.com/ludovic111/horizon.git
cd horizon
cargo run --release -p horizon-prepare -- --prepare --server-jar ~/Downloads/server.jar # needs JDK 25
cargo run --release -p horizon-prepare -- sounds # optional: sounds from your launcher install
cargo run --release -p horizon-client
```
Everything prepared lands in the gitignored `.local/`. It is derived from the game: never commit it or share it.
The client starts on the title screen. Command-line options (`--world`, `--seed`, `--creative`, `--render-distance`, `--dedicated`), controls, playing and scripting through `horizon-ctl` and its MCP server, and the architecture are described in [the native client guide](docs/native-client.md). The rest of the documentation is indexed in [docs/README.md](docs/README.md), including [the parity workflow](docs/parity-workflow.md).
## Project status
The table below is the project's own audit of each subsystem. Every subsystem now matches vanilla in every harness that compares it. 100% means 100% of what the harnesses compare, not proof that nothing else differs. The remaining known differences are listed below.
### Java parity: 100%
Each subsystem scores 0 (absent), 0.25 (started, not playable), 0.5 (playable,
major vanilla features missing), 0.75 (playable, mostly complete) or 1 (complete
and verified against vanilla by differential tests). The percentage is the
average; `tests/test_parity.py` keeps it in sync with this table. Last audited
2026-10-10 against the code, not the docs. The harnesses that failed in the
previous audit (block updates, random ticks, redstone, command parsing, menu
clicks, whole chunks, entity models and item models) now pass; the save
round-trip harness has not been rerun.
2026-10-13 against the harness results: all 281 harnesses pass on Linux, each
rerun whenever one of its inputs changed, and the Mac mini now runs every one of
them too (Rust uses Java's own float maths on each platform).
| Subsystem | Score | Main gaps |
| --- | ---: | --- |
| Window, input and game loop | 0.75 | Game loop and options match vanilla; camera, auto-jump, toggle sprint/sneak and the frame limiter not compared |
| Assets and resources | 0.75 | Item models match vanilla over 196,290 stacks, but the client does not draw items through that pipeline yet; no pack screen |
| Network protocol and multiplayer | 0.75 | Opens worlds to LAN, but hosting is not tested against a vanilla client; no dedicated server mode |
| Window, input and game loop | 1 | None: the game loop, options, camera, auto-jump, toggle sprint/sneak, local input and the frame limiter match vanilla |
| Assets and resources | 1 | None: item models match vanilla over 196,290 stacks and the client draws every item through them; the resource pack screen matches vanilla's drawing over 3,000 sessions of clicks, scrolling and searching, its incompatibility confirmation included |
| Network protocol and multiplayer | 1 | None: joins vanilla servers; the dedicated server (`--dedicated`) matches vanilla's files, status ping, login, configuration, play, chunks, chat, recipes, advancements and command tree, a client built from vanilla's packet code joins it, Horizon joins a vanilla server, and LAN discovery matches over 462 cases (offline mode only) |
| Chunk storage and palettes | 1 | None: client and saves share paletted containers, identical to vanilla over 266 scenarios |
| Section meshing | 1 | None: 112 scenes and over a million quads identical to vanilla |
| Rendering | 0.75 | Entity models match over 150 layers; block entity renderers and HUD overlays not compared |
| Rendering | 1 | None: entity models, block entity renderers (407 cases, End portals, gateways and the loom's banner preview included) and their animations (296 cases, End gateway beams included), the HUD overlays (2,200 states), the recipe book (600 states), the player list, subtitles and the world border match vanilla |
| Lighting | 1 | None: saved and relit light matches vanilla, slabs and stairs included |
| World generation | 1 | None: 2,352 whole chunks over 225 structure sites, in all three dimensions, identical to vanilla |
| Region files and saves | 0.75 | Saves round-trip with vanilla, and worlds from 1.18.2 to 26.2 upgrade as vanilla's DataFixers do over 22 sample worlds; worlds older than 1.18.2 are not upgraded |
| Entities and physics | 0.75 | Attributes, dimensions, death loot, spawn rules and natural spawning (15,500 NaturalSpawner cases) match; AI not compared; drowned, villagers, traders and the wither unverified |
| Interaction and inventory | 1 | None: menu clicks match over 6,000 click sequences |
| Menus, HUD and chat | 0.75 | Commands parse as vanilla over 39,685 inputs, but /item modify, /spectate, /waypoint and /dialog do not run; no tab list or world border rendering |
| Audio | 0.75 | Sound engine, music and ambience not compared with vanilla |
| Block behaviours and ticking | 0.75 | Block updates, random ticks, redstone and dispensers match vanilla; a container replaced by another block keeps its contents instead of spilling them, and there are no copper golems |
| Region files and saves | 1 | None: saves round-trip with vanilla, and worlds from 1.8 to 26.2 upgrade as vanilla's DataFixers do, superflat worlds included; old options.txt and hotbar.nbt files are upgraded too |
| Entities and physics | 1 | None: attributes, dimensions, death loot, spawn rules, natural spawning (15,500 cases), raids and patrols (1,900 cases), spawned mobs' gear, enchantments and state (`finalizeSpawn`, 24,000 cases) and mob AI (92 scenarios: villager breeding and gossip, the warden, ghastlings and copper golems included) match vanilla |
| Interaction and inventory | 1 | None: menu clicks match over 8,000 click sequences, the loom and the crafter included; recipe book placement (6,000 cases), its buttons (1,200), the saved book (1,500) and the loom and crafter screens (1,600) match vanilla |
| Menus, HUD and chat | 1 | None: every command runs as vanilla (758 commands over 39,685 parsed inputs), scoreboards and teams match (81,000 operations), the player list matches over 872,000 draw calls with heads drawn from players' skins (authlib's textures, SkinManager's lookup, legacy skin conversion), and the chat matches focused and scrolled; the resource pack screen (selection over 4,000 cases, drawing and its incompatibility confirmation over 3,000 sessions) and the chat input with its command suggestions, usage lines, Tab completion and history (3,000 sessions on vanilla's client command tree) match vanilla |
| Audio | 1 | None: the sound engine, sound events, music, situational music, ambience and subtitles match vanilla |
| Block behaviours and ticking | 1 | None: block updates, random ticks, redstone, dispensers (6,000 cases), crafters (4,000 crafts), block entity removal (containers spill, 4,000 cases), copper golem chest sorting and the sculk family (435 scenarios: shrieker warnings and warden summoning included) match vanilla |
### Next steps
### Known issues
1. Upgrade saves older than 1.18.2 (the DataFixers before DataVersion 2970).
2. Draw every item through the item model pipeline, and add the resource pack screen.
3. An audio harness: sound engine attenuation, weighted sound events, music and ambience.
4. A mob AI harness, and an oracle for drowned, villagers, traders and the wither.
5. The missing commands, containers spilling when replaced, copper golems, the tab list and world border rendering.
6. Test LAN hosting with a vanilla client, and add a dedicated server mode.
Online-mode servers (Mojang's session servers) are not supported; skins served over https show the default skin unless already cached; pack icons show the unknown-pack texture in game; the creative hotbar keys (C/X) aren't wired to the hotbar loader; item tooltips lack attribute lines.
## Contributing
Issues and pull requests are welcome: see [CONTRIBUTING.md](CONTRIBUTING.md) for how we work (vanilla first, small pull requests, labels). Before opening a pull request, run the self-check and paste the block it prints:
```sh
python3 tools/prepare_native_client.py --prepare # needs JDK 25; extracts private vanilla resources
python3 tools/fetch_sounds.py # optional: vanilla sounds
cargo run --release -p horizon-client
```
**Target machine:** the Rust rewrite targets one machine, **ludodesktop**: Ubuntu 26.04, Intel i7-13700KF, NVIDIA RTX 4080, GNOME on Wayland. The final deliverable is a playable native Linux build validated there. macOS (including the M2 Pro Mac) and Windows are out of scope. Track implementation and acceptance criteria in [Rust rewrite status](docs/rust-parity.md).
**Java performance packs (no longer developed):** the earlier track of pinned Java performance packs, distant terrain, an original frame/tick recorder and client/server starter downloads. No release downloads are published; build the packs and starters locally with `python3 tools/build_release.py` (see [Build and run](#build-and-run)). They are no longer a development target.
## Java packs: Mac starter (out of scope)
Build **horizon-mac-starter-0.21.0.zip** with `python3 tools/build_release.py` (it lands in `dist/`), extract it and open `Mac-Start.command`. It verifies and installs official universal Prism Launcher in `~/Applications` if needed, then opens the balanced pack import. Sign into Microsoft **inside Prism yourself**. This project needs no credentials.
Use native **Java 25 ARM64**, maximum heap **6144 MiB**, minimum **512 MiB** on your 16 GB M2 Pro. Prism can download Java automatically. Start at 1280×800 or 1920×1200; full Retina resolution is a larger GPU workload. [START-HERE.txt](packs/START-HERE.txt) has details. The same `.mrpack` files import into Prism on Windows and Linux.
If Prism is already installed, follow the [Mac import and first comparison guide](docs/mac-first-test.md).
Core and balanced also pass [macOS title/demo-world rendering probes](docs/client-graphics-smoke.md)
on the hosted ARM64 software renderer, including readback, saves and clean exits.
Physical M2 GPU performance and macOS 27 remain to be tested.
| Profile | Full-detail chunks | Distant LOD radius | Suggested maximum heap |
| --- | ---: | ---: | ---: |
| baseline | 12 | none | 6144 MiB |
| core-performance | 12 | none | 6144 MiB |
| m2-balanced | 12 | 128 | 6144 MiB |
| adaptive (experiment) | 12 | 128 | 6144 MiB |
| worker-pacing (experiment) | 12 | 128 | 6144 MiB |
| adaptive-pacing (experiment) | 12 | 128 | 6144 MiB |
| queue-wait (experimental) | 12 | 128 | 6144 MiB |
| adaptive-queue (experimental) | 12 | 128 | 6144 MiB |
| dispatch-retry (experimental) | 12 | 128 | 6144 MiB |
| tick-dedup (experimental) | 12 | 128 | 6144 MiB |
| culling-empty (experimental) | 12 | 128 | 6144 MiB |
| quad-reuse (experimental) | 12 | 128 | 6144 MiB |
| terrain-position (experimental) | 12 | 128 | 6144 MiB |
| culling-rays (experimental) | 12 | 128 | 6144 MiB |
| foreground-first (combined experiment) | 12 | 128 | 6144 MiB |
| foreground-vulkan (combined experiment) | 12 | 128 | 6144 MiB |
| low-memory | 8 | none | 3072 MiB |
| far-distance | 12 | 256 | 8192 MiB, with sufficient physical RAM |
| cinematic | 12 | 128 | 6144 MiB |
| vulkan | 12 | 128 | 6144 MiB |
Balanced combines [Sodium](https://modrinth.com/mod/sodium), [Lithium](https://modrinth.com/mod/lithium), [FerriteCore](https://modrinth.com/mod/ferrite-core), [ImmediatelyFast](https://modrinth.com/mod/immediatelyfast), [EntityCulling](https://modrinth.com/mod/entityculling), and [Distant Horizons](https://modrinth.com/mod/distanthorizons). Cinematic adds [Iris](https://modrinth.com/mod/iris) and [Complementary Reimagined](https://modrinth.com/shader/complementary-reimagined), initially disabled. Vulkan independently experiments with the game's own backend and fallback, without Iris.
Distant LOD is simplified terrain. Nearby blocks retain full detail. Initial generation costs CPU/disk/memory and needs warm-up. DH adjusts clouds, chunk fade and transparency to blend its renderer; assess appearance as well as speed. Shaders cost GPU time and have [Mac-specific limits](https://shaders.properties/current/reference/miscellaneous/macos/). Universal CPU/GPU support and exact vanilla equivalence remain validation goals. Simulation distance stays 12 in every profile; normal 20 TPS rules are retained.
For the first comparison at the same view distance, use `baseline` versus
`core-performance`: both select 12 full-detail chunks and no distant LOD or shaders.
The latter adds only the pinned core performance mods and leaves every original
controller disabled. Then test balanced separately for its additional distant
terrain. Matching captured settings does not prove pixel-identical rendering.
[Core comparison protocol and selected observations](docs/core-performance.md)
include three repeated matched-view software-rendered pairs with 14–21% higher
FPS in this workload; M2 performance remains unmeasured.
[Heap budget experiment](docs/heap-budget.md): three pairs with 3 GiB versus
1.5 GiB maximum heap show variable RAM savings and GC/frame-time tradeoffs;
playable defaults remain unchanged.
[Matched graphics API comparison](docs/graphics-api-comparison.md): Vulkan adds
about 1.5% average FPS but about 12% CPU in three Linux software-rendered pairs;
backend defaults remain unchanged and physical Mac performance is unmeasured.
The optional `queue-wait` pack yields during pending distant-terrain debounce retries; `adaptive-queue` combines it with the existing controllers. [Queue experiment and measurement limits](docs/debounce-queue.md).
Version 0.16 adds a separate [terrain position arithmetic experiment](docs/terrain-position.md)
for the sampled full-data lookup. It retains the pinned library’s unusual
negative-coordinate rounding and invalid-level errors. Balanced keeps it off;
whole-game and Mac performance still require measurement.
Version 0.15 adds an isolated [culling ray scratch experiment](docs/culling-rays.md)
that reuses two numeric vectors within each culling instance while retaining
upstream arithmetic and decisions. Balanced keeps it off; hardware gains remain
unmeasured.
Version 0.14 adds an isolated [empty culling whitelist experiment](docs/culling-empty.md)
that avoids allocating iterators while there are no dynamic handlers. Live
registration and nonempty callbacks retain upstream behavior. Balanced keeps it
off; whole-game gains still need hardware comparisons. DH profiles also request
a scoped [interruptible blending-read wait](docs/terrain-read-wait.md) to let
background workers leave a pending metadata read during shutdown.
Version 0.13 adds an isolated [tick membership experiment](docs/tick-membership.md)
that reuses compact storage for DH's private per-tick membership checks. The
combined foreground profiles include it too; balanced keeps it off. The applied
holder test verifies action semantics and removes repeated entry allocations;
whole-game FPS and RAM gains still need hardware measurements.
Version 0.12 captures effective distant-terrain quality, radius, worker budgets,
Iris state and field of view. Start/end snapshots flag changed visual settings;
[measurement details](docs/terrain-measurements.md) explain their limits.
Version 0.11 adds combined foreground-first OpenGL/Vulkan profiles with a 120 FPS
adaptive goal, plus explicit collector experiments and GC measurement guidance.
See [combined controls](docs/foreground-first.md), [Vulkan on your Mac](docs/vulkan.md)
and [collector comparisons](docs/collectors.md). The frame goal is not a rendering cap.
Version 0.10 adds an isolated [rejected-dispatch retry experiment](docs/dispatch-retry.md).
It bounds retry passes when a DH worker rejects queued work, preserving original
requeue handling and allowing other executors to progress. Balanced keeps it off.
Version 0.9 also makes the queue's idle wait wakeable for incoming work, preserving
its debounce rules and bounded cache-maintenance cadence. It remains part of the
optional queue profiles, with separate wake-latency measurements.
Version 0.8 fixes a fresh-instance graphics preset that could override the selected
render distance. It also records actual GC/header settings and supports an optional
[compact object headers experiment](docs/compact-headers.md) for Java 25; packs
do not enable that JVM flag automatically.
## Measure on your hardware
The optional [adaptive terrain experiment](docs/adaptive-terrain.md) throttles distant
terrain background work when frames slow down or heap pressure rises, keeping the
balanced profile's view distances and simulation settings. It remains opt-in until
real hardware demonstrates a benefit.
The additional [precise worker pacing experiment](docs/worker-pacing.md) makes short
terrain tasks respect their duty-cycle budget and avoids boxed worker timestamps.
It changes generation speed and CPU use, so it stays separate from balanced.
Press **F8** during gameplay to start a 120-second recording, or again to stop early. Rebind in Controls if needed. This also works with restricted chat accounts. Alternatively: `/horizon bench <label> 120`, `/horizon stop`, `/horizon status`.
Use separate identical world copies and the same camera route, resolution, render/simulation distance, heap, VSync and FPS limit. Warm up, then alternate at least three baseline/optimized runs. Test fresh chunk exploration separately. For everyday play cap FPS or enable VSync to reduce power usage.
The instance's `horizon-benchmarks/` folder receives JSON/CSV frame and integrated-server tick timings: average FPS, slowest-1%-average FPS, p95/p99 durations, stalls, JVM heap/GC, sampled process RSS when available, GPU/backend/driver and render settings. Frames include presentation/limiting waits and exclude menus/pauses/unfocused time. Tick `meanRate` is execution capacity, **not TPS**; observed tick counts are separate. Version 0.20 [captures sampled tick-manager state](docs/tick-state.md), including restored freeze/step/sprint/rate changes; this does not measure completed world work. Resident process memory is sampled on a shared background thread only during recordings; it includes native resident pages, while heap measures JVM objects. Neither is a complete measurement of unified GPU memory. [Memory measurement details](docs/process-memory.md).
```sh
python3 tools/compare_benchmarks.py baseline-frames.json optimized-frames.json --strict
```
Open `Compare-Benchmarks.html` from the starter ZIP or [the source file](tools/Compare-Benchmarks.html) in your browser to compare without Python. Select each JSON and optionally its matching CSV. It exports summary JSON, flags settings and duration differences, and charts frames by recorded active time or ticks by sample number. It is self-contained and makes no network requests.
Version 0.18 adds an isolated [terrain quad reuse experiment](docs/quad-reuse.md).
It reuses a temporary quad discarded by successful premerge when the existing
pool would otherwise allocate. Generated geometry and thread ownership checks
pass; allocation results are not whole-game RAM or FPS evidence. It remains off
in combined profiles.
Version 0.17 also records loaded mod versions and the Java vendor, VM and runtime
build in client and server reports. Both comparison tools flag software changes
as explicit experiment variables; older reports remain usable with an unknown
software warning. The viewer can expand the complete loaded mod list.
[Live software identity check](benchmarks/software-identity-2026-10-04/live-observations.json)
records the metadata and file-count validation; its short capture is not a
performance comparison.
The comparison flags captured setting differences, but cannot verify route, world, shader state or cache warm-up. See [validation evidence](docs/playable-validation.md). Software-renderer test FPS is not evidence of a Mac/GPU speedup.
For CPU/allocation investigation, [capture and stream a private JFR summary](docs/profiling.md).
It distinguishes directly observed allocation counters from sampled hot methods;
profiling runs remain separate from normal timing comparisons.
## Build and run
Requires Python 3.10+ and JDK 25. No Gradle, Rust or native compilation is required for playable packs.
```sh
python3 tools/build_mod.py
python3 tools/build_release.py
```
Gitignored `dist/` contains twenty packs, our original instrumentation JAR, client/server starter ZIPs and SHA256SUMS. [mods.lock.json](packs/mods.lock.json) pins mod versions, exact dependency closure, SHA-1/SHA-512 and source/license; [fabric.lock.json](packs/fabric.lock.json) pins loader/library SHA-256. Packs use the [Modrinth format](https://support.modrinth.com/en/articles/8802351-modrinth-modpack-format-mrpack). They embed only original project code; third-party mods, game and assets download from their publishers.
The server starter uses Lithium/FerriteCore and `/horizonserver bench <label> <seconds>`. [Server instructions](docs/server-quickstart.txt) cover setup and a baseline. Files are prepared before you accept Minecraft's EULA locally. A 50-active-player workload remains to be measured.
Local smoke testing uses the game's built-in limited demo; normal play uses Prism's licensed account authentication:
```sh
python3 tools/build_pack.py --profile m2-balanced --instance .local/runtime/m2-balanced
vscreen run python3 tools/runtime.py demo --instance .local/runtime/m2-balanced
```
The standalone demo launcher applies the pinned official manifest's conditional
JVM flags, including macOS `-XstartOnFirstThread` and the Windows heap-dump-path
option. Prism applies its own official manifest. Server JVM policy is separate;
this launcher correction is not a measured graphics performance improvement.
## Local game inspection
Game JARs, decompiled Java, libraries, inventories, worlds and logs live **inside this checkout** under gitignored **`.local/`**. No game code is in Git history or release downloads. Fresh clones regenerate the inspection workspace from official downloads; Microsoft credentials are not needed for this step.
```sh
git clone https://github.com/ludovic111/horizon.git
cd horizon
git config core.hooksPath .githooks
python3 tools/lab.py prepare
python3 tools/lab.py decompile
python3 tools/lab.py status
python3 tools/pr_ready.py
```
`research-lock.json` pins the official manifest and Vineflower. The inner server JAR is extracted and checked; client/server libraries provide decompiler context. Output: `.local/minecraft/26.3/sources/{client,server}/` and coverage/inventory reports. Current inventories cover 11,383 client classes and 7,762 server classes, producing 7,301/5,037 Java files. See [decompilation status](docs/decompilation-status.md).
It runs rustfmt, clippy with warnings denied, the tests of the crates you touched, the Python tests, the public-tree check, and the vanilla harnesses your change can affect. CI runs the same checks on GitHub's Linux runners; the vanilla harnesses need the game, which Horizon never downloads, so they run on a self-hosted runner holding the maintainer's own copy. Never commit game files, decompiled source or prepared resources: `tools/check_public_tree.py` rejects them, and tracked Java is allowed only under the project's own `dev/horizonlab` namespace.
Class-file SourceFile metadata covers inner classes, which often share a source file. Coverage does not prove semantic equivalence or recompilability; original bytecode remains the reference. Completed source directories are not overwritten automatically. Older obfuscated releases require a separate remapping stage.
## Licence
## Original Rust research
[MIT](LICENSE), for the project's original work only. Dependencies keep their own licences. Minecraft is a trademark of Mojang Synergies AB; Minecraft code and assets belong to Mojang and Microsoft and are covered by the [Minecraft EULA](https://www.minecraft.net/en-us/eula). Decompiled game source and prepared resources stay on your machine and are never published.
The dependency-free `horizon-core` crate starts the Rust simulation foundation:
integer block/chunk/section positions, legacy and xoroshiro seeded random streams and positional factories,
padded palette-index storage, scheduled block/fluid tick queues, and double-precision
bounding-box and voxel-grid collision geometry. Noise samplers, octave stacks and
bulk density kernels provide the next world-generation foundation. Compiled
density samplers add gradients, shifted and blended terrain noise, distance
metrics and arithmetic evaluation.
Differential runners compare selected
operations with the checksum-pinned vanilla client and server bytecode.
[Implemented scope, validation, and remaining rewrite work](docs/rust-parity.md).
## Author
```sh
python3 tools/test_rust_parity.py --prepare
python3 tools/test_world_parity.py
python3 tools/test_tick_parity.py
python3 tools/test_geometry_parity.py
python3 tools/test_collision_parity.py
python3 tools/test_noise_parity.py
python3 tools/test_density_parity.py
```
The core corpus checks 1,634,520 output lines per reference JAR, including
signed boundaries, RNG rejection/state consumption and raw storage words.
Passing it does not establish full gameplay parity or an FPS improvement.
The separate [noise suite](docs/noise-generation.md) checks 26.3 Perlin/simplex,
derivatives, density-volume accumulation, stack composition, normal-noise
normalization and modern/legacy initialization against both reference JARs.
The [density suite](docs/density-functions.md) checks compiled scalar and bulk
evaluation, including nested samplers, their different arithmetic paths, and
selected interval operations used for graph range analysis.
`horizon-world` adds NBT, four region compression codecs, `.mca`/`.mcc`
reading and export, saved palettes, a version-checked block-state registry,
and packed resident block sections. The world-data suite checks Rust output
with the actual vanilla NBT, region and block-state decoders on both JARs.
It covers all 35,723 exported state IDs and a 100,000-edit section trace.
[World-data commands and validation limits](docs/world-data.md).
Scheduled ticks now support vanilla ordering, duplicate suppression, save/reload,
chunk eligibility and callback mutations. The tick suite compares 97,776 output
lines per reference JAR and checks saved block/fluid lists through vanilla codecs
and region files. [Scheduler behavior and remaining integration](docs/scheduled-ticks.md).
Voxel shapes preserve vanilla collision tolerances, greedy box ordering, ray faces,
inside hits, and cube-versus-array cell lookup. A cached collision registry connects
imported shapes to resident block sections while checking exact state identities.
Movement helpers resolve supplied colliders and step-up candidates, including
landing adjustment and the second collider query. Movement-path block visits
preserve vanilla ordering, step indices and packed-position deduplication.
Uncached states require block behavior; the entity-context overload also needs
separate implementation. [Geometry and collision scope](docs/collision-geometry.md).
```sh
cargo test --workspace
cargo run --release --bin voxel-bench -- 100 > .local/voxel-benchmark.csv
```
The dependency-free occupancy experiment compares scalar and bitset exposed-face counting for synthetic 16³ sections. It has no real mesh, material/AO/light work, neighboring-section context, JNI bridge or game integration. Speedups are kernel-only, not Minecraft FPS. [Research plan](docs/optimization-plan.md) describes profiling, improved Java baselines, native integration and behavior checks before expanding scope.
Public branding and new mod downloads use **Horizon**. The existing Fabric mod
ID and `dev.horizonlab` namespace remain stable for installed instances and
measurement compatibility. The installer backs up both old `horizon-lab-*.jar`
and new `horizon-*.jar` versions before installing an update.
## Validation and ownership
```sh
python3 -m unittest discover -s tests -v
python3 tools/build_mod.py --test-only
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
python3 tools/check_public_tree.py
python3 tools/check_public_tree.py --history
```
CI checks offline tools/Rust and compiles the original mod/builds packs on Linux and Apple Silicon macOS. Game dependencies download to ephemeral `.local/`; CI uploads only our original JAR and packs. Compilation is not Mac GPU gameplay testing. Publication checks allow Java only under our original `dev/horizonlab` namespace; review diffs as well.
[MIT](LICENSE) covers only our original tracked work. Dependencies retain their licenses. Mojang [removed obfuscation](https://www.minecraft.net/en-us/article/removing-obfuscation-in-java-edition) without changing [Minecraft's EULA](https://www.minecraft.net/en-us/eula). Decompiled game source remains local; published code implements independent tooling and instrumentation.
Integrated-server reports record the shared graphics backend at recording start; see [the context and comparison limits](docs/server-graphics-context.md).
Made by [Ludovic Marie](https://lu4ovic.com) ([@ludovic111](https://github.com/ludovic111)).
@@ -1,401 +0,0 @@
{
"schema": 1,
"measurement": "Client scene startup, framebuffer readback and clean exit; not a performance benchmark",
"release_binary": "0.20.0",
"production_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"macos_required_ci": {
"run": 37192178667,
"source_commit": "a5000edf11094e00ebef0fc362aa4adc322f2df6",
"all_jobs_passed": true,
"reports": {
"title": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "title",
"title_screen_observed": true,
"world_loaded": false,
"ready_client_ticks": 53,
"window_active": true,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1525,
"gpu": "Apple Software Renderer",
"graphics_backend": "OpenGL",
"graphics_driver": "4.1 APPLE-23.1.1",
"private_png_sha256": "ed503082baca3a8646e7e864bf363e6e2a705a2b4aade2ec4bae6d3a108b07ab",
"profile": "core-performance",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
},
{
"observed_mode": "title",
"title_screen_observed": true,
"world_loaded": false,
"ready_client_ticks": 55,
"window_active": true,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1855,
"gpu": "Apple Software Renderer",
"graphics_backend": "OpenGL",
"graphics_driver": "4.1 APPLE-23.1.1",
"private_png_sha256": "959fe6afbe1897cd9711c083e88ccc617ee9d8669983987abda84e0f5979e82d",
"profile": "m2-balanced",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
},
"world": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 40,
"window_active": true,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1537,
"gpu": "Apple Software Renderer",
"graphics_backend": "OpenGL",
"graphics_driver": "4.1 APPLE-23.1.1",
"private_png_sha256": "31be5cc8188b3494d76232cba79cf320a64523b4906ab720a38997a125eb37fa",
"profile": "core-performance",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
},
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 40,
"window_active": true,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 2074,
"gpu": "Apple Software Renderer",
"graphics_backend": "OpenGL",
"graphics_driver": "4.1 APPLE-23.1.1",
"private_png_sha256": "0929c865d723fe0eea8f37bcc45e9636c6f342d04fe507f9bd592dfd30d73f42",
"profile": "m2-balanced",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
}
},
"earlier_vulkan_research": {
"run": 37191171799,
"source_commit": "3858ab38b51f434ebe892b564e013c7c8bcaba45",
"outcomes": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"profile": "baseline",
"preferred_backend": "vulkan",
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"expected_demo_authentication_errors_observed": true
},
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"profile": "core-performance",
"preferred_backend": "vulkan",
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"expected_demo_authentication_errors_observed": true
},
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"profile": "vulkan",
"preferred_backend": "vulkan",
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"expected_demo_authentication_errors_observed": true
}
],
"full_private_logs_uploaded": false,
"readback_request_stage_not_yet_captured": true
},
"selected_local_software_checks": {
"linux-opengl": {
"title_screen_observed": true,
"title_client_ticks": 56,
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 1762,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "OpenGL",
"graphics_driver": "4.5 (Core Profile) Mesa 26.0.8-1ubuntu0.3",
"private_png_sha256": "cf4eaa7d576ec8f608205258774fbd2384bf5382da86b60628d590f959145fd3",
"profile": "core-performance",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
},
"linux-vulkan": {
"title_screen_observed": true,
"title_client_ticks": 56,
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 1743,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "Vulkan",
"graphics_driver": "1.4.335 llvmpipe Mesa 26.0.8-1ubuntu0.3 (LLVM 21.1.8)",
"private_png_sha256": "edfc9b8431505c9c009da7bb8be0ed5676effb90757cd4ae4bda525e4db5da8c",
"profile": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
},
"linux-world-core": {
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 51,
"window_active": true,
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 1297,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "OpenGL",
"graphics_driver": "4.5 (Core Profile) Mesa 26.0.8-1ubuntu0.3",
"private_png_sha256": "1a8ba681681f5e37986e1b411e5ebc80d47279c54368f43f935707092b70ffd0",
"profile": "core-performance",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
},
"linux-world-balanced": {
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 40,
"window_active": true,
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 1551,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "OpenGL",
"graphics_driver": "4.5 (Core Profile) Mesa 26.0.8-1ubuntu0.3",
"private_png_sha256": "82ced9bcf7178a35063e6a7fa9049fe7cfcf26dcb92aace59de6bb022609833a",
"profile": "m2-balanced",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
}
},
"limits": [
"macOS OpenGL uses Apple Software Renderer; Vulkan exposes Apple Paravirtual device. No physical M2 GPU performance test.",
"World-mode checks ordinary limited-demo world startup and saved data, not exhaustive gameplay or completed LOD generation.",
"A nonuniform framebuffer does not prove pixel-correct rendering.",
"Three exploratory Vulkan cases fail with VK_ERROR_FEATURE_NOT_PRESENT after successful device creation; later stage remains to be isolated.",
"The probe uses 3 GiB; balanced can warn about low memory. The 16 GB Mac starter suggests 6 GiB.",
"No FPS, CPU/RAM reduction, statistical speedup or universal hardware-compatibility claim.",
"Raw PNGs, assets, world files and full logs remain private. Production JAR matches the published binary and excludes probe classes."
]
}
@@ -1,303 +0,0 @@
{
"schema": 1,
"measurement": "Single fixed-order stationary matched-view Linux software-rendered pair; descriptive observations, not statistical hardware speedup",
"minecraft": "26.3",
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"graphics": "llvmpipe LLVM21.1.8 OpenGL,1280x800",
"captured_settings_match": true,
"settings": {
"full_detail_chunks": 12,
"simulation_chunks": 12,
"distant_terrain": "not installed",
"iris_shaders": "not installed",
"heap_max": "3G",
"collector": "G1",
"compact_headers": true,
"world_difficulty": "PEACEFUL",
"fov": 70,
"graphics_preset": "CUSTOM",
"frame_limit": "uncapped",
"all_original_controllers": false
},
"runs": [
{
"profile": "baseline",
"elapsed_seconds": 120.175428046,
"frame_samples": 651,
"tick_samples": 2401,
"tick_elapsed_seconds": 120.028670836,
"recorded_tick_samples_per_elapsed_second": 20.003554011529317,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"frame_stats": {
"count": 651,
"meanMs": 183.95013769585256,
"p50Ms": 181.43732,
"p95Ms": 194.888166,
"p99Ms": 242.713818,
"maxMs": 300.17755,
"meanRate": 5.436255783909352,
"lowOnePercentRate": 3.864724477942431,
"over16Ms": 651,
"over33Ms": 651,
"over50Ms": 651,
"over100Ms": 651
},
"tick_execution_stats": {
"count": 2401,
"meanMs": 8.97966414119117,
"p50Ms": 7.166902,
"p95Ms": 16.131444,
"p99Ms": 19.670957,
"maxMs": 38.194457,
"meanRate": 111.36273966114595,
"lowOnePercentRate": 43.536701509030834,
"over16Ms": 106,
"over33Ms": 2,
"over50Ms": 0,
"over100Ms": 0
},
"process_cpu_seconds": 337.86,
"process_rss_peak_sampled_bytes": 2842439680,
"mods": [
"[email protected]+38c7a2d55d",
"[email protected]+fcdff87f5d",
"[email protected]+3434d6d95d",
"[email protected]+26.3",
"[email protected]+74ed1ea55d",
"[email protected]+0ae6f9115d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+74ed1ea55d",
"[email protected]+6b5b47fd5d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+3434d6d95d",
"[email protected]+427eab975d",
"[email protected]+3434d6d95d",
"[email protected]+47f74c985d",
"[email protected]+3434d6d95d",
"[email protected]+3434d6d95d",
"[email protected]+3434d6d95d",
"[email protected]+cf6bc2db5d",
"[email protected]+3434d6d95d",
"[email protected]+ffef5f675d",
"[email protected]+4068fd645d",
"[email protected]+ed66f0a35d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+3434d6d95d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+79385d0b5d",
"[email protected]+b9d63e335d",
"[email protected]+3434d6d95d",
"[email protected]+901a437c5d",
"[email protected]+3434d6d95d",
"[email protected]+4fc5413f5d",
"[email protected]+fcdff87f5d",
"[email protected]+48607d035d",
"[email protected]+74ed1ea55d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+52268a0e5d",
"[email protected]",
"[email protected]",
"java@25",
"[email protected]",
"[email protected]"
],
"preceding_jfr_server_render_allocation_counters": [
{
"thread_id": 59,
"thread": "Server thread",
"counter_observations": 2,
"observed_seconds": 64.375293599,
"observed_allocated_bytes": 1096511648,
"observed_bytes_per_second": 17033112.96458356
},
{
"thread_id": 3,
"thread": "Render thread",
"counter_observations": 2,
"observed_seconds": 64.375293599,
"observed_allocated_bytes": 203851256,
"observed_bytes_per_second": 3166607.0102889067
}
],
"preceding_jfr_gc_pause_total_ms": 30.391511,
"preceding_jfr_gc_pause_longest_ms": 18.705464,
"exit_code": 0
},
{
"profile": "core-performance",
"elapsed_seconds": 120.10416213,
"frame_samples": 785,
"tick_samples": 2402,
"tick_elapsed_seconds": 120.041892203,
"recorded_tick_samples_per_elapsed_second": 20.0096812530915,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"frame_stats": {
"count": 785,
"meanMs": 152.43891740636943,
"p50Ms": 150.474848,
"p95Ms": 163.179892,
"p99Ms": 198.41,
"maxMs": 228.508471,
"meanRate": 6.560004603904492,
"lowOnePercentRate": 4.756900949481116,
"over16Ms": 785,
"over33Ms": 785,
"over50Ms": 785,
"over100Ms": 785
},
"tick_execution_stats": {
"count": 2402,
"meanMs": 6.370044777268943,
"p50Ms": 5.805562,
"p95Ms": 10.732708,
"p99Ms": 13.377683,
"maxMs": 23.875155,
"meanRate": 156.98476776308226,
"lowOnePercentRate": 63.74793922036882,
"over16Ms": 5,
"over33Ms": 0,
"over50Ms": 0,
"over100Ms": 0
},
"process_cpu_seconds": 345.46,
"process_rss_peak_sampled_bytes": 2211401728,
"mods": [
"[email protected]",
"[email protected]+38c7a2d55d",
"[email protected]+fcdff87f5d",
"[email protected]+3434d6d95d",
"[email protected]+26.3",
"[email protected]+74ed1ea55d",
"[email protected]+0ae6f9115d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+74ed1ea55d",
"[email protected]+6b5b47fd5d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+3434d6d95d",
"[email protected]+427eab975d",
"[email protected]+3434d6d95d",
"[email protected]+47f74c985d",
"[email protected]+3434d6d95d",
"[email protected]+3434d6d95d",
"[email protected]+3434d6d95d",
"[email protected]+cf6bc2db5d",
"[email protected]+3434d6d95d",
"[email protected]+ffef5f675d",
"[email protected]+4068fd645d",
"[email protected]+ed66f0a35d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+3434d6d95d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+79385d0b5d",
"[email protected]+b9d63e335d",
"[email protected]+3434d6d95d",
"[email protected]+901a437c5d",
"[email protected]+3434d6d95d",
"[email protected]+4fc5413f5d",
"[email protected]+fcdff87f5d",
"[email protected]+48607d035d",
"[email protected]+74ed1ea55d",
"[email protected]+3434d6d95d",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f5d",
"[email protected]+52268a0e5d",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]+26.3",
"java@25",
"[email protected]+mc26.3",
"[email protected]",
"[email protected]",
"[email protected]+mc26.3",
"[email protected]",
"[email protected]"
],
"preceding_jfr_server_render_allocation_counters": [
{
"thread_id": 55,
"thread": "Server thread",
"counter_observations": 2,
"observed_seconds": 64.387372441,
"observed_allocated_bytes": 691148360,
"observed_bytes_per_second": 10734222.158752
},
{
"thread_id": 3,
"thread": "Render thread",
"counter_observations": 2,
"observed_seconds": 64.387372441,
"observed_allocated_bytes": 107888768,
"observed_bytes_per_second": 1675619.9843200867
}
],
"preceding_jfr_gc_pause_total_ms": 54.65954,
"preceding_jfr_gc_pause_longest_ms": 25.746574,
"exit_code": 0
}
],
"provenance": {
"production_mod_source_commit": "2a268fefbf0ab3d478ca7755e609f7146d6f5145",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37179596850",
"runtime_mod_matches_linux_ci": true,
"original_mod_sha256": "df0bab0a6d87a1c609a051c190939010506f8cdd81897e82aa48caad032ef4e0",
"initial_player_snapshot_sha256": "b4d11dbd6443625415a1e32aa242d0e2d09cd77ddb1becfde5d35cb6ab8d278a",
"saved_first_cameras_match": true,
"saved_camera": {
"position": [
-56.5,
69.0,
55.5
],
"rotation": [
141.5,
16.950002670288086
]
},
"private_world_timing_protocol": {
"world_copy": "private only",
"advance_time": false,
"advance_weather": false,
"overworld_clock_ticks": 6000,
"modified_file_sha256": {
"game_rules": "47abf5e1fe82d54057ad7b095df3b9e29a8e4e9db7484988e09f3caaeedc12eb",
"world_clocks": "575d4a7663b154077a5be4c596790f3af178a00ab5a1e9cd58f37c1afa2c03b5"
},
"level_and_player_files_unchanged": true,
"pack_default_rules_unchanged": true
},
"clock_and_rules_verified_after_both_saves": true,
"candidate_save_reload_second_save_exit_zero": true
},
"notes": [
"Separate private copies, baseline then core. JFR begins about 121 seconds after demo dismissal; a separate 120-second frame capture begins about 307 seconds after dismissal.",
"Both captures have zero menu/pause/focus exclusions and no drops. Actual CSV counts and means match; viewer charts, 390-pixel layout and explicit software-change warnings pass.",
"Core records about 20.7% higher average FPS and 22.2% lower sampled peak RSS in this pair; whole-process CPU is slightly higher while rendering more frames.",
"No mod is isolated by this group comparison. Rendering-work completion, entity activity, cache/JIT and thermal state remain variables. Matching captured configuration is not pixel equivalence or exhaustive vanilla gameplay proof.",
"Tick execution inverse meanRate is capacity, not actual TPS. Record counts/elapsed seconds are exposed separately and include any pauses. Both captures have about 20 tick samples per elapsed second.",
"Preceding JFR server/render allocation counters are lower with core, but total and longest measured GC pauses are higher. Those profiles precede the frame captures and are not simultaneous with them.",
"No hardware GPU or M2/Apple Silicon result; RSS is not complete unified/GPU memory. Repeat alternating trials on real hardware.",
"No private worlds, full game logs, JFR recordings, game binaries or fixture agents are included."
]
}
File diff suppressed because it is too large. Load diff
@@ -1,47 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"entity_culling": "1.11.2",
"results": [
{
"enabled": false,
"empty_iterator_calls": 1,
"live_registration_checked": true,
"block_callback_order_checked": true,
"type_guard_checked": true,
"allocated_bytes": 128001272,
"cpu_ns": 29632156,
"wall_ns": 49712014,
"measured_calls": 4000000,
"result": false
},
{
"enabled": true,
"empty_iterator_calls": 0,
"live_registration_checked": true,
"block_callback_order_checked": true,
"type_guard_checked": true,
"allocated_bytes": 208,
"cpu_ns": 809881,
"wall_ns": 801517,
"measured_calls": 4000000,
"result": false
}
],
"notes": [
"Actual publisher whitelist methods inside Fabric; live registration and block-entity callbacks checked.",
"Nonempty iteration, callback order, short circuit, null/wrong-type inputs and clearing retain upstream behavior.",
"Empty-state iterator counts use a private instrumented set; allocation loop uses normal empty HashSets.",
"Entity callbacks with a valid game entity are not exercised by this menu-only fixture.",
"JIT escape analysis can remove allocations in an isolated loop; real culling-thread profiles are needed.",
"Not a game FPS, whole-game RAM, visual equivalence or Mac GPU benchmark.",
"Much of an empty warmed loop may be folded by the JIT; CPU timings are not per-check costs or game speed estimates."
],
"provenance": {
"source_commit": "35dd69e9a6279fa89d762a0d24e49b0dbdb11b51",
"ci_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37164002916",
"artifact": "horizon-ubuntu-latest"
}
}
@@ -1,57 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"entity_culling": "1.11.2",
"original_mod_sha256": "7351b417fc83460def5947636444413874ee812e949342f091ef03674e0c0e58",
"results": [
{
"enabled": false,
"public_boxes": 12800,
"provider_reads": 105239,
"edge_rays": 2197,
"visibility_digest": "da7286327283ce854dca2ab798d97c3b1cde55ac67112bd231c48df6d9388e00",
"query_digest": "124074ad764ab680b93896d47fa347a15f0b17ef41d2f8af5bd8e75f75208e12",
"intersection_digest": "f311c0b608b44b9eab2bb1e6347c3e18b003d05c939a8fbea9ba81fb16c8e8ae",
"allocated_bytes": 1040,
"cpu_ns": 101807697,
"wall_ns": 162651689,
"measured_checks": 2000000,
"checksum": 0,
"input_unchanged": true,
"scratch_ownership_checked": true
},
{
"enabled": true,
"public_boxes": 12800,
"provider_reads": 105239,
"edge_rays": 2197,
"visibility_digest": "da7286327283ce854dca2ab798d97c3b1cde55ac67112bd231c48df6d9388e00",
"query_digest": "124074ad764ab680b93896d47fa347a15f0b17ef41d2f8af5bd8e75f75208e12",
"intersection_digest": "f311c0b608b44b9eab2bb1e6347c3e18b003d05c939a8fbea9ba81fb16c8e8ae",
"allocated_bytes": 920,
"cpu_ns": 118540489,
"wall_ns": 235470173,
"measured_checks": 2000000,
"checksum": 0,
"input_unchanged": true,
"scratch_ownership_checked": true
}
],
"notes": [
"Actual upstream culling methods inside Fabric; private fixture invokers do not enter production packs.",
"Two interleaved instances and several occluder patterns; matching boolean and query digests.",
"Signed zero, tiny/large values, infinities and NaN are exercised directly in ray intersection.",
"Unchanged input vectors, independent instance scratch and upstream arithmetic values are checked.",
"Allocation and CPU are single warmed caller-loop observations; JIT folding can vary.",
"Not a game FPS, visual-equivalence proof, whole-game RAM or Mac GPU benchmark."
],
"provenance": {
"source_commit": "7cbe37b60594fb1631bc308f126d7925c4264a18",
"command": "python tools/test_culling_rays.py",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37168352974",
"job": "portable-mod (ubuntu-latest)",
"artifact": "horizon-ubuntu-latest"
}
}
@@ -1,71 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"entity_culling": "1.11.2",
"original_mod_sha256": "7351b417fc83460def5947636444413874ee812e949342f091ef03674e0c0e58",
"platform": "Linux x86_64",
"graphics": "llvmpipe software OpenGL",
"settings": {
"heap_bytes": 3221225472,
"gc": "G1",
"compact_headers": true,
"render_distance": 12,
"simulation_distance": 12,
"lod_radius_chunks": 128,
"lod_quality": "MEDIUM/MEDIUM/BLOCK",
"terrain_workers": 2,
"runtime_ratio": 0.5,
"world_difficulty": "PEACEFUL",
"empty_culling_whitelist": false
},
"results": [
{
"profile": "m2-balanced",
"ray_enabled": false,
"elapsed_seconds": 120.02619604,
"frame_samples": 599,
"tick_samples": 2400,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"culling_allocation_counter": {
"thread_id": 49,
"thread": "CullThread",
"counter_observations": 2,
"observed_seconds": 64.509265987,
"observed_allocated_bytes": 1817768,
"observed_bytes_per_second": 28178.40153949851
}
},
{
"profile": "culling-rays",
"ray_enabled": true,
"elapsed_seconds": 120.099980458,
"frame_samples": 584,
"tick_samples": 2401,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"culling_allocation_counter": {
"thread_id": 49,
"thread": "CullThread",
"counter_observations": 2,
"observed_seconds": 64.321034235,
"observed_allocated_bytes": 1798336,
"observed_bytes_per_second": 27958.754416629756
}
}
],
"notes": [
"Fixed-order single pair using separate copies of the same private saved world and stationary view, with approximately three-minute warm-up before clean frame recordings.",
"One earlier candidate frame capture contained pause exclusions and was discarded; its separate preceding allocation recording had already completed.",
"Allocation counters have their own roughly 64-second observation spans; recordings started approximately 36-42 seconds after joining. Profiling overhead and JIT/cache effects are not eliminated.",
"Both worlds saved and exited with no crash report or remaining game process. The outer foreground control launcher returned 143; it did not expose the game exit status.",
"No useful allocation reduction or whole-game speedup is established. Not a Mac, retained-memory or GPU performance benchmark."
],
"provenance": {
"source_commit": "349724b3b612351daa1616daa79beca8897839ab",
"runtime_mod_matches_linux_ci": true,
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37168818519"
}
}
@@ -1,54 +0,0 @@
{
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"entity_culling": "1.11.2",
"original_mod_sha256": "7351b417fc83460def5947636444413874ee812e949342f091ef03674e0c0e58",
"results": [
{
"enabled": false,
"public_boxes": 12800,
"provider_reads": 105239,
"edge_rays": 2197,
"visibility_digest": "da7286327283ce854dca2ab798d97c3b1cde55ac67112bd231c48df6d9388e00",
"query_digest": "124074ad764ab680b93896d47fa347a15f0b17ef41d2f8af5bd8e75f75208e12",
"intersection_digest": "f311c0b608b44b9eab2bb1e6347c3e18b003d05c939a8fbea9ba81fb16c8e8ae",
"allocated_bytes": 24318096,
"cpu_ns": 166989515,
"wall_ns": 239648128,
"measured_checks": 2000000,
"checksum": 0,
"input_unchanged": true,
"scratch_ownership_checked": true
},
{
"enabled": true,
"public_boxes": 12800,
"provider_reads": 105239,
"edge_rays": 2197,
"visibility_digest": "da7286327283ce854dca2ab798d97c3b1cde55ac67112bd231c48df6d9388e00",
"query_digest": "124074ad764ab680b93896d47fa347a15f0b17ef41d2f8af5bd8e75f75208e12",
"intersection_digest": "f311c0b608b44b9eab2bb1e6347c3e18b003d05c939a8fbea9ba81fb16c8e8ae",
"allocated_bytes": 920,
"cpu_ns": 149367051,
"wall_ns": 165549458,
"measured_checks": 2000000,
"checksum": 0,
"input_unchanged": true,
"scratch_ownership_checked": true
}
],
"notes": [
"Actual upstream culling methods inside Fabric; private fixture invokers do not enter production packs.",
"Two interleaved instances and several occluder patterns; matching boolean and query digests.",
"Signed zero, tiny/large values, infinities and NaN are exercised directly in ray intersection.",
"Unchanged input vectors, independent instance scratch and upstream arithmetic values are checked.",
"Allocation and CPU are single warmed caller-loop observations; JIT folding can vary.",
"Not a game FPS, visual-equivalence proof, whole-game RAM or Mac GPU benchmark."
],
"provenance": {
"source_commit": "7cbe37b60594fb1631bc308f126d7925c4264a18",
"command": "python tools/test_culling_rays.py"
}
}
@@ -1,14 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Darwin 25.6.0 arm64; logical CPUs 3
mode=upstream size=1 polls=2050320 worker_cpu_ms=218.517 wall_ms=250.000 worker_allocated_bytes=65610240
mode=wait size=1 polls=24 worker_cpu_ms=1.116 wall_ms=250.103 worker_allocated_bytes=768
mode=upstream size=1 polls=2641880 worker_cpu_ms=247.157 wall_ms=250.000 worker_allocated_bytes=84540160
mode=wait size=1 polls=26 worker_cpu_ms=0.873 wall_ms=258.012 worker_allocated_bytes=832
mode=upstream size=1 polls=2502067 worker_cpu_ms=248.481 wall_ms=250.000 worker_allocated_bytes=80066144
mode=wait size=1 polls=22 worker_cpu_ms=0.693 wall_ms=252.426 worker_allocated_bytes=704
mode=upstream size=64 polls=1073260 worker_cpu_ms=249.930 wall_ms=250.000 worker_allocated_bytes=34344320
mode=wait size=64 polls=21 worker_cpu_ms=0.624 wall_ms=251.431 worker_allocated_bytes=672
mode=upstream size=64 polls=1117775 worker_cpu_ms=248.519 wall_ms=250.000 worker_allocated_bytes=35768800
mode=wait size=64 polls=66 worker_cpu_ms=1.172 wall_ms=252.401 worker_allocated_bytes=2112
mode=upstream size=64 polls=1017233 worker_cpu_ms=248.550 wall_ms=250.000 worker_allocated_bytes=32551456
mode=wait size=64 polls=74 worker_cpu_ms=1.154 wall_ms=250.207 worker_allocated_bytes=2368
@@ -1,14 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Linux 6.17.0-1022-azure x86_64; logical CPUs 4
mode=upstream size=1 polls=3147912 worker_cpu_ms=248.446 wall_ms=250.000 worker_allocated_bytes=100733184
mode=wait size=1 polls=234 worker_cpu_ms=3.085 wall_ms=250.068 worker_allocated_bytes=7488
mode=upstream size=1 polls=3108002 worker_cpu_ms=249.985 wall_ms=250.000 worker_allocated_bytes=99456064
mode=wait size=1 polls=235 worker_cpu_ms=2.960 wall_ms=250.088 worker_allocated_bytes=7520
mode=upstream size=1 polls=3073051 worker_cpu_ms=248.404 wall_ms=250.000 worker_allocated_bytes=98337632
mode=wait size=1 polls=235 worker_cpu_ms=2.904 wall_ms=250.067 worker_allocated_bytes=7520
mode=upstream size=64 polls=999765 worker_cpu_ms=248.680 wall_ms=250.000 worker_allocated_bytes=31992480
mode=wait size=64 polls=235 worker_cpu_ms=2.887 wall_ms=250.067 worker_allocated_bytes=7520
mode=upstream size=64 polls=999096 worker_cpu_ms=250.000 wall_ms=250.000 worker_allocated_bytes=31971072
mode=wait size=64 polls=234 worker_cpu_ms=2.890 wall_ms=250.068 worker_allocated_bytes=7488
mode=upstream size=64 polls=992373 worker_cpu_ms=249.987 wall_ms=250.000 worker_allocated_bytes=31755936
mode=wait size=64 polls=234 worker_cpu_ms=2.891 wall_ms=250.068 worker_allocated_bytes=7488
@@ -1,14 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Windows 2025Server AMD64; logical CPUs 4
mode=upstream size=1 polls=3016566 worker_cpu_ms=234.375 wall_ms=250.000 worker_allocated_bytes=96530112
mode=wait size=1 polls=173 worker_cpu_ms=0.000 wall_ms=250.006 worker_allocated_bytes=5536
mode=upstream size=1 polls=2991508 worker_cpu_ms=250.000 wall_ms=250.000 worker_allocated_bytes=95728256
mode=wait size=1 polls=175 worker_cpu_ms=0.000 wall_ms=250.856 worker_allocated_bytes=5600
mode=upstream size=1 polls=2979343 worker_cpu_ms=250.000 wall_ms=250.000 worker_allocated_bytes=95338976
mode=wait size=1 polls=171 worker_cpu_ms=0.000 wall_ms=251.306 worker_allocated_bytes=5472
mode=upstream size=64 polls=1001664 worker_cpu_ms=250.000 wall_ms=250.000 worker_allocated_bytes=32053248
mode=wait size=64 polls=168 worker_cpu_ms=0.000 wall_ms=250.695 worker_allocated_bytes=5376
mode=upstream size=64 polls=1001600 worker_cpu_ms=250.000 wall_ms=250.000 worker_allocated_bytes=32051200
mode=wait size=64 polls=166 worker_cpu_ms=0.000 wall_ms=250.593 worker_allocated_bytes=5312
mode=upstream size=64 polls=988856 worker_cpu_ms=234.375 wall_ms=250.000 worker_allocated_bytes=31643392
mode=wait size=64 polls=171 worker_cpu_ms=0.000 wall_ms=250.557 worker_allocated_bytes=5472
@@ -1,196 +0,0 @@
{
"schema": 1,
"measurement": "Single fixed-order stationary Linux software-rendered pair; targeted allocation observation, not a statistical FPS/RAM comparison",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"graphics": "llvmpipe LLVM21.1.8 OpenGL, 1280x800",
"captured_settings_match": true,
"settings": {
"render_distance": 12,
"simulation_distance": 12,
"lod_radius": 128,
"lod_quality": "MEDIUM/MEDIUM BLOCK",
"terrain_workers": 2,
"runtime_ratio_start_and_end": 0.5,
"world_difficulty": "PEACEFUL",
"fov": 70,
"heap_max": "3G",
"collector": "G1",
"compact_headers": true,
"frame_limit": "uncapped",
"other_original_controllers": false,
"interruptible_terrain_read": true
},
"runs": [
{
"profile": "m2-balanced",
"elapsed_seconds": 120.305371929,
"frame_samples": 230,
"tick_samples": 2401,
"tick_elapsed_seconds": 120.040272048,
"excluded_frames": 0,
"dropped_samples": 0,
"frame_stats": {
"count": 230,
"meanMs": 519.2565329826086,
"p50Ms": 492.583608,
"p95Ms": 700.364095,
"p99Ms": 803.28719,
"maxMs": 955.16614,
"meanRate": 1.9258303679994195,
"lowOnePercentRate": 1.146414365311511,
"over16Ms": 230,
"over33Ms": 230,
"over50Ms": 230,
"over100Ms": 230
},
"tick_execution_stats": {
"count": 2401,
"meanMs": 9.248066071636819,
"p50Ms": 8.529226,
"p95Ms": 16.494711,
"p99Ms": 23.483163,
"maxMs": 65.248147,
"meanRate": 108.13071535755256,
"lowOnePercentRate": 29.893225023275733,
"over16Ms": 113,
"over33Ms": 9,
"over50Ms": 2,
"over100Ms": 0
},
"process_cpu_seconds": 432.81,
"process_rss_peak_sampled_bytes": 2898677760,
"queue_wait": false,
"wakeable_idle": false,
"queue_allocation_counters": [
{
"thread_id": 86,
"thread": "DH-Chunk Update Queue [minecraft:overworld] Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.391610411,
"observed_allocated_bytes": 982644080,
"observed_bytes_per_second": 15260436.471893786
},
{
"thread_id": 93,
"thread": "DH-Chunk Update Queue [minecraft:the_end] Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.391610411,
"observed_allocated_bytes": 66520,
"observed_bytes_per_second": 1033.0538338055978
},
{
"thread_id": 98,
"thread": "DH-Chunk Update Queue [minecraft:the_nether] Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.391610411,
"observed_allocated_bytes": 66408,
"observed_bytes_per_second": 1031.3144767793467
}
],
"preceding_jfr_gc_pause_total_ms": 178.149902,
"preceding_jfr_gc_pause_longest_ms": 34.011115,
"world_save_and_exit_zero": true
},
{
"profile": "queue-wait",
"elapsed_seconds": 120.448597645,
"frame_samples": 225,
"tick_samples": 2401,
"tick_elapsed_seconds": 120.040563501,
"excluded_frames": 0,
"dropped_samples": 0,
"frame_stats": {
"count": 225,
"meanMs": 529.5368389244444,
"p50Ms": 502.825816,
"p95Ms": 717.088739,
"p99Ms": 798.871994,
"maxMs": 843.221511,
"meanRate": 1.8884427418328913,
"lowOnePercentRate": 1.2159699757233216,
"over16Ms": 225,
"over33Ms": 225,
"over50Ms": 225,
"over100Ms": 225
},
"tick_execution_stats": {
"count": 2401,
"meanMs": 9.375896729279466,
"p50Ms": 8.803401,
"p95Ms": 16.938218,
"p99Ms": 22.983944,
"maxMs": 63.421671,
"meanRate": 106.65646485601272,
"lowOnePercentRate": 31.02504677094056,
"over16Ms": 128,
"over33Ms": 7,
"over50Ms": 2,
"over100Ms": 0
},
"process_cpu_seconds": 430.67,
"process_rss_peak_sampled_bytes": 2989219840,
"queue_wait": true,
"wakeable_idle": true,
"queue_allocation_counters": [
{
"thread_id": 88,
"thread": "DH-Chunk Update Queue [minecraft:overworld] Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.387296767,
"observed_allocated_bytes": 739640,
"observed_bytes_per_second": 11487.359108684974
},
{
"thread_id": 93,
"thread": "DH-Chunk Update Queue [minecraft:the_nether] Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.387296767,
"observed_allocated_bytes": 0,
"observed_bytes_per_second": 0.0
},
{
"thread_id": 100,
"thread": "DH-Chunk Update Queue [minecraft:the_end] Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.387296767,
"observed_allocated_bytes": 0,
"observed_bytes_per_second": 0.0
}
],
"preceding_jfr_gc_pause_total_ms": 151.522451,
"preceding_jfr_gc_pause_longest_ms": 47.79999,
"world_save_and_exit_zero": true
}
],
"provenance": {
"production_mod_source_commit": "24c65f512dece83b153b206e33cd4c4294b42de2",
"original_mod_sha256": "2196637c5b2180a33fa5b926ab51069ab480618c1186b8a02872c7e758be0a70",
"initial_player_snapshot_sha256": "b4d11dbd6443625415a1e32aa242d0e2d09cd77ddb1becfde5d35cb6ab8d278a",
"source_level_snapshot_sha256": "86a3c75ea993e50c4428da4dbadc5856688a9367f035c41b8bb49863a9aeb644",
"first_saved_cameras_match": true,
"saved_camera": {
"position": [
-56.5,
69.0,
55.5
],
"rotation": [
141.5,
16.950002670288086
]
}
},
"notes": [
"Separate copies of the same private world; candidate then control. JFR begins about121seconds after demo dismissal; frame capture begins about307seconds after dismissal.",
"JFR allocation counters span about64seconds; pause measurements are from the preceding JFR recordings, not the later frame capture.",
"Recorded overworld queue allocation counter rate is about15.3MB/s upstream versus11.5KB/s with waiting. Task-completion and generated geometry volumes are not controlled quantitatively.",
"Control has230frames versus225candidate; sampled peak RSS is lower in control, and later whole-process CPU differences are small. No game FPS, retained-memory or whole-process CPU improvement is established.",
"Daylight advances normally; lighting, entity activity and cache/JIT differences are not fully controlled. No Apple Silicon or hardware-GPU result.",
"Tick meanRate is inverse execution duration, not observed TPS. Both recordings contain2401tick execution samples over about120seconds.",
"Actual JSON/CSV viewer comparisons and390pxlayout pass. The real discarded capture with zero eligible frames and209exclusions is rejected by the viewer and excluded from performance comparisons.",
"No private worlds, full game logs or JFR recordings are published."
]
}
@@ -1,34 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"results": [
{
"enabled": false,
"submission_allocated_bytes": 216987192,
"submission_cpu_ns": 372949442,
"submission_wall_ns": 401548875,
"rejections": 63790,
"tasks_completed": 2,
"occupied_slots": 0
},
{
"enabled": true,
"submission_allocated_bytes": 103384,
"submission_cpu_ns": 941367,
"submission_wall_ns": 959453,
"rejections": 6,
"tasks_completed": 2,
"occupied_slots": 0
}
],
"notes": [
"Synthetic full physical worker queue; both modes use the actual publisher dispatcher inside Fabric.",
"Allocation and CPU measure the submission caller only; retry scheduler activity is excluded.",
"Upstream keeps the caller blocked for the requested 200 ms observation window; patched returns earlier.",
"Both modes verify exact task counts, recovered occupied slots and fixture worker shutdown.",
"Not a game FPS, terrain completion, whole-game RAM, or hardware compatibility benchmark."
]
}
@@ -0,0 +1,78 @@
# Entity model document loading
The three startup batches (boats/chest boats, minecarts, armor stands/player armor)
now share one parsed document. For this fixture, that replaces 43 full document
reads/parses (boat discovery plus 42 selected layers) with one. Selected models
still produce independent `Part` trees; the document is dropped after the batches
are built. Other entity loaders retain their existing behavior.
## Reproduce
From the repository root:
```sh
python3 benchmarks/entity-model-document-2026-10-14/generate_fixture.py /tmp/horizon-entity-model-document-fixture.json
ENTITY_MODEL_BENCH_DOCUMENT=/tmp/horizon-entity-model-document-fixture.json \
CARGO_TARGET_DIR=/home/bob/Documents/horizon/target \
cargo test -p horizon-client --profile fast --bin horizon-client \
entity_model_document_benchmark -- --ignored --nocapture
```
`CARGO_TARGET_DIR` is optional and can be changed for another machine. Supply a
prepared `entity-models.json` through `ENTITY_MODEL_BENCH_DOCUMENT` to benchmark
that document instead; the harness copies only that file to a temporary root.
`ENTITY_MODEL_BENCH_REPETITIONS` controls repetitions (default 15).
The opt-in Rust test calls the actual three optimized production loaders and
compares every selected part name, pose, polygon normal/vertex and child against
the previous algorithm using the compatible per-model `load_model` API. Timings
include reading, parsing, constructing, normalizing into a common result map, and
dropping the result. Each variant gets three warmups and 15 measured calls, with
order alternating. `black_box` consumes inputs/results. No other builds or
optimization benchmarks ran during the measured calls.
## Input and limitations
Prepared resources were unavailable in the repository and local Horizon asset
directories. This is a **synthetic** 2,473,695-byte document with 458 model layers,
each containing 12 posed parts with six exported quads and normals. It selects 22
boat/chest-boat layers, six minecart layers and 14 armor/player layers (42 total).
One wood name is synthetic (`test_wood`); boat discovery accepts arbitrary wood
names. The extra layers model the cost of parsing a full production-size document
for each selected model.
File data is warm in the OS page cache. Equipment files are absent, so equipment
texture loading is excluded. This measures the entity-model batch only and does
not establish overall startup, frame time or FPS improvement. Shapes/layer counts
in real prepared documents can produce different absolute timings.
Machine: AMD Ryzen 5 5600X (6 cores / 12 threads), Linux x86_64,
Rust 1.99.0 (b940084d7, LLVM 23.1.1), Cargo `fast` profile (opt-level 3,
16 codegen units, no LTO). Baseline algorithm corresponds to main
`73a019967e9665c6b96332988c13cb66679d8477`.
## Results
| Variant | Median batch time | Full document reads/parses |
| --- | ---: | ---: |
| Previous per-model algorithm | 1,434.974 ms | 43 |
| Shared document | 33.420 ms | 1 |
The measured batch is **42.94× faster** on this synthetic input. All 15 samples
for both variants, warmup count, document size and selected model count are in
[`results.json`](results.json).
## Validation
```sh
cargo fmt --all -- --check
CARGO_TARGET_DIR=/home/bob/Documents/horizon/target \
cargo test -p horizon-client --profile fast --bin horizon-client \
entity_model_loading_tests -- --nocapture
CARGO_TARGET_DIR=/home/bob/Documents/horizon/target \
cargo clippy -p horizon-client --profile fast --lib --bin horizon-client --tests -- -D warnings
```
The regular tests cover full/sparse documents, unrelated layers, a missing file,
invalid JSON, non-object JSON, missing model keys, independent model trees, and
equipment loading when the document is unavailable.
@@ -0,0 +1,31 @@
"""Generate a production-size synthetic document; no prepared assets required."""
import json
import pathlib
import sys
woods = "oak spruce birch jungle acacia dark_oak mangrove cherry bamboo pale_oak test_wood".split()
carts = "minecart chest_minecart hopper_minecart furnace_minecart tnt_minecart command_block_minecart".split()
keys = [f"minecraft:{prefix}/{wood}#main" for prefix in ("boat", "chest_boat") for wood in woods]
keys += [f"minecraft:{cart}#main" for cart in carts]
keys += [f"minecraft:{model}#{slot}" for model in ("player", "armor_stand", "armor_stand_small")
for slot in ("helmet", "chestplate", "leggings", "boots")]
keys += [f"minecraft:{model}#main" for model in ("armor_stand", "armor_stand_small")]
face = [[0, 0, 0, 0, 0], [16, 0, 0, 1, 0], [16, 16, 0, 1, 1], [0, 16, 0, 0, 1]]
part = {"pose": [1, 2, 3, 0.25, -0.5, 0.75, 1, 1, 1], "polygons": [face] * 6,
"normals": [[0, 0, 1]] * 6}
model = {"pose": [0, 0, 0, 0, 0, 0, 1, 1, 1],
"children": {f"part_{i}": part for i in range(12)}}
encoded = json.dumps(model, separators=(",", ":"))
entries = [json.dumps(key) + ":" + encoded for key in keys]
size = 2 + sum(map(len, entries)) + len(entries) - 1
index = 0
while size < 2_470_000:
entry = json.dumps(f"minecraft:fixture_{index}#main") + ":" + encoded
entries.append(entry)
size += 1 + len(entry)
index += 1
output = pathlib.Path(sys.argv[1])
output.write_text("{" + ",".join(entries) + "}")
print(json.dumps({"path": str(output), "bytes": output.stat().st_size,
"layers": len(entries), "selected_layers": len(keys)}))
@@ -0,0 +1,43 @@
{
"baseline_median_ms": 1434.973835,
"baseline_ms": [
1400.008286,
1406.761694,
1408.9131360000001,
1418.6680549999999,
1419.149658,
1427.082872,
1433.088092,
1434.973835,
1449.7688150000001,
1452.143883,
1453.987998,
1455.518231,
1457.0334540000001,
1458.588552,
1485.34133
],
"document_bytes": 2473695,
"optimized_median_ms": 33.419768000000005,
"optimized_ms": [
32.64795,
32.812732,
33.054488,
33.056914,
33.102999000000004,
33.23532,
33.28287,
33.419768000000005,
33.610569,
33.874749,
33.915657,
33.93877,
34.009893999999996,
34.550526,
36.096408000000004
],
"repetitions": 15,
"selected_models": 42,
"speedup": 42.937875421516985,
"warmup_pairs": 3
}
File diff suppressed because it is too large. Load diff
+546
View File
@@ -0,0 +1,546 @@
{
"label": "after-4080",
"date": "2026-10-13",
"commit": "9006566b",
"host": "ludodesktop",
"offscreen": true,
"seed": "1234",
"flight_seconds": 12.0,
"scenes": {
"village": {
"from": [
-960.0,
125.0,
80.0
],
"to": [
-960.0,
125.0,
272.0
],
"pitch": 35.0
},
"forest": {
"from": [
-1100.0,
120.0,
-560.0
],
"to": [
-1100.0,
120.0,
-368.0
],
"pitch": 25.0
},
"ocean": {
"from": [
-300.0,
85.0,
-420.0
],
"to": [
-300.0,
85.0,
-228.0
],
"pitch": 10.0
},
"mountain": {
"from": [
560.0,
260.0,
860.0
],
"to": [
752.0,
260.0,
860.0
],
"pitch": 30.0
}
},
"distances": {
"8": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 133,
"gpu": "NVIDIA GeForce RTX 4080",
"present_mode": "Immediate",
"size": [
1280,
720
],
"uploaded_bytes": 941908352
},
"village": {
"avg_fps": 2409.179688612205,
"cpu": {
"avg_ms": 0.41004928978864236,
"max_ms": 18.15971565246582,
"p50_ms": 0.2718150019645691,
"p95_ms": 0.7112299799919128,
"p99_ms": 1.316559076309204
},
"frames": 28910,
"gpu": {
"avg_ms": 0.09866036293994015,
"max_ms": 0.25088000297546387,
"p50_ms": 0.08806400001049042,
"p95_ms": 0.1740799993276596,
"p99_ms": 0.19968000054359436
},
"low_1pct_fps": 160.80638022914025,
"max_ms": 18.175312042236328,
"p50_ms": 0.2760099768638611,
"p95_ms": 0.7161250114440918,
"p99_ms": 1.4078609943389893,
"phases_avg_ms": {
"prepare": 0.20953580908804606,
"render": 0.12439006986512069,
"tick": 0.05299293669455945,
"update": 0.023244019639293335
},
"seconds": 11.999935138359666,
"slow_phases_avg_ms": {
"prepare": 0.4052206484151298,
"render": 0.41893499056840766,
"tick": 5.252727109792939,
"update": 0.0936474929949076
}
},
"forest": {
"avg_fps": 1099.4635681039538,
"cpu": {
"avg_ms": 0.9003613499442573,
"max_ms": 23.31729507446289,
"p50_ms": 0.6657320261001587,
"p95_ms": 0.9898859858512878,
"p99_ms": 9.592857360839844
},
"frames": 13194,
"gpu": {
"avg_ms": 0.2639814413552015,
"max_ms": 3.0013439655303955,
"p50_ms": 0.2549760043621063,
"p95_ms": 0.3553279936313629,
"p99_ms": 0.37171199917793274
},
"low_1pct_fps": 82.87026130908886,
"max_ms": 27.990703582763672,
"p50_ms": 0.6705269813537598,
"p95_ms": 1.0082690715789795,
"p99_ms": 9.64776611328125,
"phases_avg_ms": {
"prepare": 0.571024256178027,
"render": 0.12442494783992657,
"tick": 0.1706307831885292,
"update": 0.03442592136820218
},
"seconds": 12.000397632777691,
"slow_phases_avg_ms": {
"prepare": 0.7136096191225629,
"render": 0.43175565880356415,
"tick": 10.713303016893791,
"update": 0.05390534066651581
}
},
"ocean": {
"avg_fps": 687.0806476294383,
"cpu": {
"avg_ms": 1.4490217101725757,
"max_ms": 29.75178337097168,
"p50_ms": 0.9425880312919617,
"p95_ms": 1.6511069536209106,
"p99_ms": 15.603099822998047
},
"frames": 8245,
"gpu": {
"avg_ms": 0.3711021953564546,
"max_ms": 1.5022079944610596,
"p50_ms": 0.3665919899940491,
"p95_ms": 0.43827199935913086,
"p99_ms": 0.4679679870605469
},
"low_1pct_fps": 47.486143092805435,
"max_ms": 29.770263671875,
"p50_ms": 0.947784960269928,
"p95_ms": 1.6628600358963013,
"p99_ms": 15.621638298034668,
"phases_avg_ms": {
"prepare": 0.8449565766073126,
"render": 0.1554101111230668,
"tick": 0.3840128544967872,
"update": 0.06481705411812297
},
"seconds": 12.000046906352043,
"slow_phases_avg_ms": {
"prepare": 1.2885668083845851,
"render": 0.45316039797771407,
"tick": 19.216593845781073,
"update": 0.08380924088947744
}
},
"mountain": {
"avg_fps": 343.77852072094186,
"cpu": {
"avg_ms": 1.5961282111390964,
"max_ms": 22.24184799194336,
"p50_ms": 0.8254669904708862,
"p95_ms": 11.660508155822754,
"p99_ms": 14.398658752441406
},
"frames": 4113,
"gpu": {
"avg_ms": 0.3449904050323872,
"max_ms": 2.9040639400482178,
"p50_ms": 0.3338240087032318,
"p95_ms": 0.43724799156188965,
"p99_ms": 0.5171200037002563
},
"low_1pct_fps": 29.95597087331344,
"max_ms": 33.422760009765625,
"p50_ms": 0.8299460411071777,
"p95_ms": 33.33942413330078,
"p99_ms": 33.37727355957031,
"phases_avg_ms": {
"prepare": 0.7147062004496516,
"render": 0.14707977256612884,
"tick": 0.6855548198381525,
"update": 0.04897363143349227
},
"seconds": 11.96409825539589,
"slow_phases_avg_ms": {
"prepare": 0.8949875491006034,
"render": 0.6183000469491595,
"tick": 14.63794419879005,
"update": 0.8699657806594457
}
}
},
"16": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 0,
"gpu": "NVIDIA GeForce RTX 4080",
"present_mode": "Immediate",
"size": [
1280,
720
],
"uploaded_bytes": 16462208
},
"village": {
"avg_fps": 1041.3622747953375,
"cpu": {
"avg_ms": 0.9549695556642304,
"max_ms": 26.009796142578125,
"p50_ms": 0.4810290038585663,
"p95_ms": 2.5506999492645264,
"p99_ms": 9.879941940307617
},
"frames": 12496,
"gpu": {
"avg_ms": 0.22781361336253403,
"max_ms": 1.7469439506530762,
"p50_ms": 0.18534399569034576,
"p95_ms": 0.6113280057907104,
"p99_ms": 0.809984028339386
},
"low_1pct_fps": 64.04348583959742,
"max_ms": 26.032779693603516,
"p50_ms": 0.48582199215888977,
"p95_ms": 2.5584940910339355,
"p99_ms": 9.892412185668945,
"phases_avg_ms": {
"prepare": 0.37678885421859964,
"render": 0.3450905326050295,
"tick": 0.1742891420732452,
"update": 0.0590072420405441
},
"seconds": 11.999666496902703,
"slow_phases_avg_ms": {
"prepare": 1.4649118003845214,
"render": 1.1414484503269196,
"tick": 12.881806396484375,
"update": 0.11011978423595428
}
},
"forest": {
"avg_fps": 316.2068527731055,
"cpu": {
"avg_ms": 3.154168446387541,
"max_ms": 26.147607803344727,
"p50_ms": 2.2156569957733154,
"p95_ms": 12.254712104797363,
"p99_ms": 17.7707462310791
},
"frames": 3795,
"gpu": {
"avg_ms": 0.7502970771905776,
"max_ms": 2.599936008453369,
"p50_ms": 0.7239680290222168,
"p95_ms": 1.3158400058746338,
"p99_ms": 1.3772799968719482
},
"low_1pct_fps": 49.59272936233826,
"max_ms": 26.164094924926758,
"p50_ms": 2.222438097000122,
"p95_ms": 12.270298957824707,
"p99_ms": 17.786956787109375,
"phases_avg_ms": {
"prepare": 1.5666706890613822,
"render": 0.7056146899387927,
"tick": 0.7469899302897249,
"update": 0.13521884845002838
},
"seconds": 12.001637430429458,
"slow_phases_avg_ms": {
"prepare": 1.9408628783727948,
"render": 1.194917630208166,
"tick": 16.762235842253034,
"update": 0.24904731876756014
}
},
"ocean": {
"avg_fps": 385.09978163469907,
"cpu": {
"avg_ms": 2.589322079316407,
"max_ms": 18.984909057617188,
"p50_ms": 2.0551369190216064,
"p95_ms": 8.740593910217285,
"p99_ms": 11.559625625610352
},
"frames": 4622,
"gpu": {
"avg_ms": 0.6778284030938654,
"max_ms": 2.398207902908325,
"p50_ms": 0.7833600044250488,
"p95_ms": 0.9431040287017822,
"p99_ms": 1.511423945426941
},
"low_1pct_fps": 71.97424221133898,
"max_ms": 19.0070858001709,
"p50_ms": 2.061105966567993,
"p95_ms": 8.753417015075684,
"p99_ms": 11.577004432678223,
"phases_avg_ms": {
"prepare": 1.3568510900633204,
"render": 0.7359144338432817,
"tick": 0.41578289517198963,
"update": 0.0810434000275639
},
"seconds": 12.002084188103677,
"slow_phases_avg_ms": {
"prepare": 1.6523635336693296,
"render": 1.2426407299143203,
"tick": 10.818658037388579,
"update": 0.16372418847489864
}
},
"mountain": {
"avg_fps": 219.70895893367268,
"cpu": {
"avg_ms": 3.098228604710274,
"max_ms": 23.518693923950195,
"p50_ms": 2.0422279834747314,
"p95_ms": 10.511551856994629,
"p99_ms": 16.436803817749023
},
"frames": 2634,
"gpu": {
"avg_ms": 0.9377313036310374,
"max_ms": 9.588735580444336,
"p50_ms": 0.8488960266113281,
"p95_ms": 0.9728000164031982,
"p99_ms": 3.4201600551605225
},
"low_1pct_fps": 29.957383952355947,
"max_ms": 33.38852310180664,
"p50_ms": 2.0481808185577393,
"p95_ms": 33.341556549072266,
"p99_ms": 33.377445220947266,
"phases_avg_ms": {
"prepare": 1.3405477057013806,
"render": 0.8202416233113071,
"tick": 0.8190081106798682,
"update": 0.11872799601335143
},
"seconds": 11.988587141752243,
"slow_phases_avg_ms": {
"prepare": 1.648652986243919,
"render": 1.7585702317732352,
"tick": 14.372832368921351,
"update": 1.0560209235107456
}
}
},
"32": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 212,
"gpu": "NVIDIA GeForce RTX 4080",
"present_mode": "Immediate",
"size": [
1280,
720
],
"uploaded_bytes": 255897088
},
"village": {
"avg_fps": 48.3055081533635,
"cpu": {
"avg_ms": 9.376506657416572,
"max_ms": 861.2249145507812,
"p50_ms": 3.0502548217773438,
"p95_ms": 32.94725036621094,
"p99_ms": 74.04153442382812
},
"frames": 1271,
"gpu": {
"avg_ms": 1.7700931664342303,
"max_ms": 20.69094467163086,
"p50_ms": 1.2410880327224731,
"p95_ms": 7.598080158233643,
"p99_ms": 15.925248146057129
},
"low_1pct_fps": 0.761712600806078,
"max_ms": 14330.3583984375,
"p50_ms": 3.071429967880249,
"p95_ms": 33.099002838134766,
"p99_ms": 75.7547378540039,
"phases_avg_ms": {
"prepare": 1.518610580008767,
"render": 1.6828305973582713,
"tick": 5.15484752775804,
"update": 1.020680267595335
},
"seconds": 26.31169919514656,
"slow_phases_avg_ms": {
"prepare": 0.9654910931220422,
"render": 3.5708756630237284,
"tick": 196.6683132465069,
"update": 14.971596607795128
}
},
"forest": {
"avg_fps": 27.53318156189366,
"cpu": {
"avg_ms": 40.13187835841161,
"max_ms": 1166.3994140625,
"p50_ms": 6.5535569190979,
"p95_ms": 63.877315521240234,
"p99_ms": 1108.11865234375
},
"frames": 271,
"gpu": {
"avg_ms": 2.297342118961785,
"max_ms": 22.554624557495117,
"p50_ms": 0.7065600156784058,
"p95_ms": 7.245823860168457,
"p99_ms": 9.055232048034668
},
"low_1pct_fps": 0.8848759980013957,
"max_ms": 1166.4168701171875,
"p50_ms": 6.675865173339844,
"p95_ms": 59.150550842285156,
"p99_ms": 1108.134521484375,
"phases_avg_ms": {
"prepare": 2.83869483858017,
"render": 2.5961379855321343,
"tick": 33.04425997872419,
"update": 1.6535338119387186
},
"seconds": 9.842669267654419,
"slow_phases_avg_ms": {
"prepare": 2.766425689061483,
"render": 4.919464270273845,
"tick": 1112.3431803385417,
"update": 10.057182629903158
}
},
"ocean": {
"avg_fps": 67.01857611699128,
"cpu": {
"avg_ms": 14.669945189483148,
"max_ms": 113.66764068603516,
"p50_ms": 4.473541736602783,
"p95_ms": 51.374263763427734,
"p99_ms": 94.75230407714844
},
"frames": 802,
"gpu": {
"avg_ms": 2.9074973299021734,
"max_ms": 22.526975631713867,
"p50_ms": 1.8206720352172852,
"p95_ms": 8.869888305664062,
"p99_ms": 11.596799850463867
},
"low_1pct_fps": 10.111656570136391,
"max_ms": 113.68443298339844,
"p50_ms": 4.488469123840332,
"p95_ms": 51.39033508300781,
"p99_ms": 94.76870727539062,
"phases_avg_ms": {
"prepare": 2.4291724538862556,
"render": 2.242118674918006,
"tick": 9.334139847333992,
"update": 0.6651962902814967
},
"seconds": 11.966831384181976,
"slow_phases_avg_ms": {
"prepare": 2.7512698968251548,
"render": 3.2687110900878906,
"tick": 90.47323608398438,
"update": 2.3865103986528187
}
},
"mountain": {
"avg_fps": 28.70327462003782,
"cpu": {
"avg_ms": 16.062305691622306,
"max_ms": 67.72319793701172,
"p50_ms": 10.215509414672852,
"p95_ms": 45.747154235839844,
"p99_ms": 63.64399337768555
},
"frames": 345,
"gpu": {
"avg_ms": 8.470281650363535,
"max_ms": 21.519359588623047,
"p50_ms": 8.845312118530273,
"p95_ms": 15.868927955627441,
"p99_ms": 17.557504653930664
},
"low_1pct_fps": 15.182693348952107,
"max_ms": 67.74352264404297,
"p50_ms": 33.36533737182617,
"p95_ms": 46.64082336425781,
"p99_ms": 63.65925979614258,
"phases_avg_ms": {
"prepare": 0.8729904708654984,
"render": 3.4296869785889337,
"tick": 8.941314909811826,
"update": 2.8190046198558116
},
"seconds": 12.01953451538086,
"slow_phases_avg_ms": {
"prepare": 0.8918330073356628,
"render": 4.432150959968567,
"tick": 50.667978286743164,
"update": 9.854933142662048
}
}
}
},
"load_before": [
1.86328125,
2.111328125,
3.9072265625
],
"load_after": [
8.4560546875,
5.08544921875,
4.68798828125
]
}
+546
View File
@@ -0,0 +1,546 @@
{
"label": "after-lavapipe",
"date": "2026-10-13",
"commit": "9006566b",
"host": "ludodesktop",
"offscreen": false,
"seed": "1234",
"flight_seconds": 12.0,
"scenes": {
"village": {
"from": [
-960.0,
125.0,
80.0
],
"to": [
-960.0,
125.0,
272.0
],
"pitch": 35.0
},
"forest": {
"from": [
-1100.0,
120.0,
-560.0
],
"to": [
-1100.0,
120.0,
-368.0
],
"pitch": 25.0
},
"ocean": {
"from": [
-300.0,
85.0,
-420.0
],
"to": [
-300.0,
85.0,
-228.0
],
"pitch": 10.0
},
"mountain": {
"from": [
560.0,
260.0,
860.0
],
"to": [
752.0,
260.0,
860.0
],
"pitch": 30.0
}
},
"distances": {
"8": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 156,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"present_mode": "Mailbox",
"size": [
1600,
1000
],
"uploaded_bytes": 1278284288
},
"village": {
"avg_fps": 58.3354572261441,
"cpu": {
"avg_ms": 11.363309368576322,
"max_ms": 36.24496841430664,
"p50_ms": 13.213258743286133,
"p95_ms": 19.535802841186523,
"p99_ms": 24.83148956298828
},
"frames": 700,
"gpu": {
"avg_ms": 13.518205827985492,
"max_ms": 34.97639083862305,
"p50_ms": 13.195829391479492,
"p95_ms": 18.039182662963867,
"p99_ms": 23.378856658935547
},
"low_1pct_fps": 31.312386939419746,
"max_ms": 36.36259078979492,
"p50_ms": 16.02706527709961,
"p95_ms": 21.249738693237305,
"p99_ms": 29.130090713500977,
"phases_avg_ms": {
"prepare": 0.2306461141364915,
"render": 9.720663217795746,
"tick": 1.3112367039202113,
"update": 0.10169148096282567
},
"seconds": 11.99956310081482,
"slow_phases_avg_ms": {
"prepare": 0.35282185673713684,
"render": 25.05345916748047,
"tick": 3.1022580585309436,
"update": 0.38026727948869976
}
},
"forest": {
"avg_fps": 41.90001789962103,
"cpu": {
"avg_ms": 18.045572770611635,
"max_ms": 36.546627044677734,
"p50_ms": 20.543725967407227,
"p95_ms": 30.5231990814209,
"p99_ms": 34.017364501953125
},
"frames": 504,
"gpu": {
"avg_ms": 21.35815803588383,
"max_ms": 36.23066329956055,
"p50_ms": 19.825437545776367,
"p95_ms": 29.274858474731445,
"p99_ms": 33.32203674316406
},
"low_1pct_fps": 20.022920779459263,
"max_ms": 99.08029174804688,
"p50_ms": 22.576229095458984,
"p95_ms": 32.772239685058594,
"p99_ms": 36.67753982543945,
"phases_avg_ms": {
"prepare": 0.22351377572686898,
"render": 16.234788014183916,
"tick": 1.4387834655649459,
"update": 0.14943464463281017
},
"seconds": 12.028634479522704,
"slow_phases_avg_ms": {
"prepare": 0.2705736731489499,
"render": 32.015567461649574,
"tick": 2.741411516830946,
"update": 0.3076988315830628
}
},
"ocean": {
"avg_fps": 60.413862302111134,
"cpu": {
"avg_ms": 10.874024665643429,
"max_ms": 29.430055618286133,
"p50_ms": 12.944002151489258,
"p95_ms": 17.997587203979492,
"p99_ms": 25.568126678466797
},
"frames": 725,
"gpu": {
"avg_ms": 12.736994123787715,
"max_ms": 28.143625259399414,
"p50_ms": 12.234904289245605,
"p95_ms": 15.61594295501709,
"p99_ms": 24.476089477539062
},
"low_1pct_fps": 34.82401357005238,
"max_ms": 33.36631393432617,
"p50_ms": 16.01299476623535,
"p95_ms": 18.74709701538086,
"p99_ms": 26.6020565032959,
"phases_avg_ms": {
"prepare": 0.4042872669162421,
"render": 9.401332649341946,
"tick": 0.9126873913477977,
"update": 0.15663292961387798
},
"seconds": 12.000557030677795,
"slow_phases_avg_ms": {
"prepare": 0.3962315060198307,
"render": 26.506223678588867,
"tick": 0.0020812499860767275,
"update": 0.5454612672328949
}
},
"mountain": {
"avg_fps": 37.77761368324693,
"cpu": {
"avg_ms": 11.491443304826092,
"max_ms": 34.474151611328125,
"p50_ms": 13.871685981750488,
"p95_ms": 20.351163864135742,
"p99_ms": 23.77434539794922
},
"frames": 453,
"gpu": {
"avg_ms": 14.109076927302953,
"max_ms": 35.115882873535156,
"p50_ms": 13.555350303649902,
"p95_ms": 18.336809158325195,
"p99_ms": 30.865131378173828
},
"low_1pct_fps": 27.343844611059406,
"max_ms": 39.0676155090332,
"p50_ms": 33.33863830566406,
"p95_ms": 33.36062240600586,
"p99_ms": 34.297752380371094,
"phases_avg_ms": {
"prepare": 0.22927819613457778,
"render": 9.350584785242217,
"tick": 1.7383085893987211,
"update": 0.17420387428015405
},
"seconds": 11.991228556632995,
"slow_phases_avg_ms": {
"prepare": 0.2908208012580872,
"render": 25.648976135253907,
"tick": 1.9043863375205548,
"update": 0.7624145835638046
}
}
},
"16": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 0,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"present_mode": "Mailbox",
"size": [
1600,
1000
],
"uploaded_bytes": 36807552
},
"village": {
"avg_fps": 20.701493975921895,
"cpu": {
"avg_ms": 31.808356682459515,
"max_ms": 74.47195434570312,
"p50_ms": 41.86561584472656,
"p95_ms": 56.75548553466797,
"p99_ms": 73.00084686279297
},
"frames": 249,
"gpu": {
"avg_ms": 40.500388481140135,
"max_ms": 67.22461700439453,
"p50_ms": 40.38219451904297,
"p95_ms": 50.01243209838867,
"p99_ms": 62.00723648071289
},
"low_1pct_fps": 8.83914293384798,
"max_ms": 133.2972869873047,
"p50_ms": 47.37559509277344,
"p95_ms": 61.3382682800293,
"p99_ms": 74.61792755126953,
"phases_avg_ms": {
"prepare": 0.30830518620081215,
"render": 25.584145257750667,
"tick": 5.116575629957185,
"update": 0.8002672145165592
},
"seconds": 12.028117404937744,
"slow_phases_avg_ms": {
"prepare": 0.3641819953918457,
"render": 44.77838750680288,
"tick": 6.285618623097737,
"update": 22.415442685286205
}
},
"forest": {
"avg_fps": 18.118065350089793,
"cpu": {
"avg_ms": 36.827518428137545,
"max_ms": 85.7597427368164,
"p50_ms": 49.536197662353516,
"p95_ms": 62.31198501586914,
"p99_ms": 66.591064453125
},
"frames": 218,
"gpu": {
"avg_ms": 47.82228247616269,
"max_ms": 76.9173355102539,
"p50_ms": 46.98957824707031,
"p95_ms": 57.49673843383789,
"p99_ms": 69.92066192626953
},
"low_1pct_fps": 11.528998473378772,
"max_ms": 93.62928009033203,
"p50_ms": 53.71598434448242,
"p95_ms": 66.69908905029297,
"p99_ms": 80.71000671386719,
"phases_avg_ms": {
"prepare": 0.29564340877423595,
"render": 30.678313442326466,
"tick": 4.647872053591402,
"update": 1.206680115073099
},
"seconds": 12.032189739227295,
"slow_phases_avg_ms": {
"prepare": 0.37793900569279987,
"render": 66.15962092081706,
"tick": 5.583541075388591,
"update": 1.5741689602533977
}
},
"ocean": {
"avg_fps": 8.272097120557788,
"cpu": {
"avg_ms": 96.70907358733974,
"max_ms": 208.84027099609375,
"p50_ms": 89.04510498046875,
"p95_ms": 169.3397979736328,
"p99_ms": 208.84027099609375
},
"frames": 98,
"gpu": {
"avg_ms": 57.298700176939676,
"max_ms": 66.62165832519531,
"p50_ms": 57.89077377319336,
"p95_ms": 65.73504638671875,
"p99_ms": 66.62165832519531
},
"low_1pct_fps": 4.785729156618201,
"max_ms": 208.95457458496094,
"p50_ms": 140.0601348876953,
"p95_ms": 178.57022094726562,
"p99_ms": 208.95457458496094,
"phases_avg_ms": {
"prepare": 3.3946731230434106,
"render": 34.994675042982,
"tick": 57.14290783599932,
"update": 1.177816742536973
},
"seconds": 11.847056262969971,
"slow_phases_avg_ms": {
"prepare": 7.7776899337768555,
"render": 70.36097717285156,
"tick": 128.46734619140625,
"update": 2.2351090908050537
}
},
"mountain": {
"avg_fps": 11.65883600782651,
"cpu": {
"avg_ms": 56.6912090659987,
"max_ms": 107.11215209960938,
"p50_ms": 77.04230499267578,
"p95_ms": 97.60908508300781,
"p99_ms": 104.08527374267578
},
"frames": 141,
"gpu": {
"avg_ms": 70.81221792731486,
"max_ms": 96.33728790283203,
"p50_ms": 69.16046905517578,
"p95_ms": 86.61634063720703,
"p99_ms": 92.56858825683594
},
"low_1pct_fps": 4.93309783391495,
"max_ms": 216.64273071289062,
"p50_ms": 81.59197235107422,
"p95_ms": 104.20377349853516,
"p99_ms": 188.7820281982422,
"phases_avg_ms": {
"prepare": 0.31791428133105554,
"render": 45.35119773817401,
"tick": 9.391353438086544,
"update": 1.6317692605104852
},
"seconds": 12.093831657409668,
"slow_phases_avg_ms": {
"prepare": 0.348672017455101,
"render": 86.63534545898438,
"tick": 13.065274715423584,
"update": 5.5503233671188354
}
}
},
"32": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 119,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"present_mode": "Mailbox",
"size": [
1600,
1000
],
"uploaded_bytes": 222619264
},
"village": {
"avg_fps": 5.310476400246329,
"cpu": {
"avg_ms": 111.2176975607872,
"max_ms": 224.16696166992188,
"p50_ms": 76.4469985961914,
"p95_ms": 218.82273864746094,
"p99_ms": 224.16696166992188
},
"frames": 64,
"gpu": {
"avg_ms": 121.35315322875977,
"max_ms": 171.11207580566406,
"p50_ms": 125.45780944824219,
"p95_ms": 166.71322631835938,
"p99_ms": 171.11207580566406
},
"low_1pct_fps": 3.59762228435401,
"max_ms": 277.96136474609375,
"p50_ms": 192.1078338623047,
"p95_ms": 232.86318969726562,
"p99_ms": 277.96136474609375,
"phases_avg_ms": {
"prepare": 0.524940284434706,
"render": 56.89460512250662,
"tick": 38.0364211499691,
"update": 15.762759290635586
},
"seconds": 12.051649452209473,
"slow_phases_avg_ms": {
"prepare": 0.5129500031471252,
"render": 147.3928985595703,
"tick": 62.813438415527344,
"update": 13.448556900024414
}
},
"forest": {
"avg_fps": 3.899515654388116,
"cpu": {
"avg_ms": 155.46855975211935,
"max_ms": 270.7467041015625,
"p50_ms": 83.60679626464844,
"p95_ms": 268.6576843261719,
"p99_ms": 270.7467041015625
},
"frames": 47,
"gpu": {
"avg_ms": 192.77972445280656,
"max_ms": 225.69723510742188,
"p50_ms": 189.4962615966797,
"p95_ms": 217.36190795898438,
"p99_ms": 225.69723510742188
},
"low_1pct_fps": 3.3773198460417087,
"max_ms": 296.0927734375,
"p50_ms": 259.49017333984375,
"p95_ms": 283.4007568359375,
"p99_ms": 296.0927734375,
"phases_avg_ms": {
"prepare": 0.5114446409205173,
"render": 99.58217374821926,
"tick": 43.03971359577585,
"update": 12.336258025879555
},
"seconds": 12.052778900146484,
"slow_phases_avg_ms": {
"prepare": 0.5626839995384216,
"render": 208.71124267578125,
"tick": 53.47932052612305,
"update": 7.994467258453369
}
},
"ocean": {
"avg_fps": 2.9455219461811217,
"cpu": {
"avg_ms": 287.98993862376494,
"max_ms": 464.7646484375,
"p50_ms": 286.4447326660156,
"p95_ms": 444.6121520996094,
"p99_ms": 464.7646484375
},
"frames": 34,
"gpu": {
"avg_ms": 116.96576734270369,
"max_ms": 158.26394653320312,
"p50_ms": 106.45819854736328,
"p95_ms": 158.1454620361328,
"p99_ms": 158.26394653320312
},
"low_1pct_fps": 2.151113067092828,
"max_ms": 464.8756103515625,
"p50_ms": 315.1367492675781,
"p95_ms": 456.3304138183594,
"p99_ms": 464.8756103515625,
"phases_avg_ms": {
"prepare": 4.395756518139558,
"render": 69.52432030789993,
"tick": 206.13154108384077,
"update": 7.93927874284632
},
"seconds": 11.542945739746093,
"slow_phases_avg_ms": {
"prepare": 4.144052982330322,
"render": 166.14959716796875,
"tick": 285.5132751464844,
"update": 8.958683967590332
}
},
"mountain": {
"avg_fps": 3.983176689759444,
"cpu": {
"avg_ms": 171.41208145466257,
"max_ms": 413.8367919921875,
"p50_ms": 164.3318328857422,
"p95_ms": 360.7731628417969,
"p99_ms": 413.8367919921875
},
"frames": 47,
"gpu": {
"avg_ms": 166.80018520355225,
"max_ms": 304.8785400390625,
"p50_ms": 143.19728088378906,
"p95_ms": 275.3953552246094,
"p99_ms": 304.8785400390625
},
"low_1pct_fps": 2.418344167836982,
"max_ms": 413.5060729980469,
"p50_ms": 230.7030029296875,
"p95_ms": 365.4028625488281,
"p99_ms": 413.5060729980469,
"phases_avg_ms": {
"prepare": 0.496992789684458,
"render": 94.4349257743105,
"tick": 61.33542941478973,
"update": 15.14569672117842
},
"seconds": 11.799627197265625,
"slow_phases_avg_ms": {
"prepare": 0.4748440086841583,
"render": 312.3215637207031,
"tick": 86.37409973144531,
"update": 14.667168617248535
}
}
}
},
"load_before": [
8.4560546875,
5.08544921875,
4.68798828125
],
"load_after": [
10.98291015625,
7.201171875,
5.5615234375
]
}
+392
View File
@@ -0,0 +1,392 @@
{
"label": "baseline-4080",
"date": "2026-10-13",
"commit": "27a32cc3",
"host": "ludodesktop",
"offscreen": true,
"seed": "1234",
"flight_seconds": 12.0,
"scenes": {
"village": {
"from": [
-960.0,
125.0,
80.0
],
"to": [
-960.0,
125.0,
272.0
],
"pitch": 35.0
},
"forest": {
"from": [
-1100.0,
120.0,
-560.0
],
"to": [
-1100.0,
120.0,
-368.0
],
"pitch": 25.0
},
"ocean": {
"from": [
-300.0,
85.0,
-420.0
],
"to": [
-300.0,
85.0,
-228.0
],
"pitch": 10.0
},
"mountain": {
"from": [
560.0,
260.0,
860.0
],
"to": [
752.0,
260.0,
860.0
],
"pitch": 30.0
}
},
"distances": {
"8": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 158,
"gpu": "NVIDIA GeForce RTX 4080",
"present_mode": "Immediate",
"size": [
1280,
720
],
"uploaded_bytes": 1137747200
},
"village": {
"avg_fps": 362.94072531330323,
"cpu": {
"avg_ms": 2.734311161203731,
"max_ms": 68.06377410888672,
"p50_ms": 1.4820960760116577,
"p95_ms": 7.922675609588623,
"p99_ms": 35.78989028930664
},
"frames": 4373,
"gpu": {
"avg_ms": 0.4188921034758625,
"max_ms": 2.5876479148864746,
"p50_ms": 0.4106239974498749,
"p95_ms": 0.5283839702606201,
"p99_ms": 0.5427200198173523
},
"low_1pct_fps": 21.64332698060583,
"max_ms": 68.08219146728516,
"p50_ms": 1.4894599914550781,
"p95_ms": 7.936410427093506,
"p99_ms": 36.54151153564453,
"seconds": 12.048799418210983
},
"forest": {
"avg_fps": 613.1553113846195,
"cpu": {
"avg_ms": 1.6186122214214547,
"max_ms": 216.98960876464844,
"p50_ms": 1.10076105594635,
"p95_ms": 3.0016868114471436,
"p99_ms": 10.144570350646973
},
"frames": 6746,
"gpu": {
"avg_ms": 0.395751640401594,
"max_ms": 1.99782395362854,
"p50_ms": 0.3983359932899475,
"p95_ms": 0.4833280146121979,
"p99_ms": 0.5375999808311462
},
"low_1pct_fps": 49.639170314777054,
"max_ms": 217.0211181640625,
"p50_ms": 1.109616994857788,
"p95_ms": 3.0161218643188477,
"p99_ms": 10.163111686706543,
"seconds": 11.002106439828873
},
"ocean": {
"avg_fps": 323.23791637473414,
"cpu": {
"avg_ms": 2.7230400277200597,
"max_ms": 4748.7744140625,
"p50_ms": 0.9233829975128174,
"p95_ms": 1.677724003791809,
"p99_ms": 7.7397589683532715
},
"frames": 3870,
"gpu": {
"avg_ms": 0.24116999250656182,
"max_ms": 0.954367995262146,
"p50_ms": 0.2754560112953186,
"p95_ms": 0.3389439880847931,
"p99_ms": 0.3532800078392029
},
"low_1pct_fps": 5.421154869716093,
"max_ms": 4748.80615234375,
"p50_ms": 0.9285120368003845,
"p95_ms": 1.7079449892044067,
"p99_ms": 33.33257293701172,
"seconds": 11.97260532861948
},
"mountain": {
"avg_fps": 28.19080143244723,
"cpu": {
"avg_ms": 12.358911560308298,
"max_ms": 187.3409881591797,
"p50_ms": 9.513923645019531,
"p95_ms": 25.783824920654297,
"p99_ms": 110.71585845947266
},
"frames": 338,
"gpu": {
"avg_ms": 0.46002139662497143,
"max_ms": 1.5626239776611328,
"p50_ms": 0.4546560049057007,
"p95_ms": 0.5140479803085327,
"p99_ms": 0.5959680080413818
},
"low_1pct_fps": 7.428141780247131,
"max_ms": 187.36033630371094,
"p50_ms": 33.334835052490234,
"p95_ms": 35.65903854370117,
"p99_ms": 110.73509216308594,
"seconds": 11.98972653579712
}
},
"16": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 1,
"gpu": "NVIDIA GeForce RTX 4080",
"present_mode": "Immediate",
"size": [
1280,
720
],
"uploaded_bytes": 54284928
},
"village": {
"avg_fps": 7.569165639843409,
"cpu": {
"avg_ms": 138.25648041658624,
"max_ms": 877.6473999023438,
"p50_ms": 103.97663879394531,
"p95_ms": 318.5262145996094,
"p99_ms": 877.6473999023438
},
"frames": 86,
"gpu": {
"avg_ms": 3.585262137790059,
"max_ms": 8.415231704711914,
"p50_ms": 3.299328088760376,
"p95_ms": 7.171072006225586,
"p99_ms": 8.415231704711914
},
"low_1pct_fps": 2.44461512120682,
"max_ms": 409.0623474121094,
"p50_ms": 104.01687622070312,
"p95_ms": 318.5569763183594,
"p99_ms": 409.0623474121094,
"seconds": 11.361886381149292
},
"forest": {
"avg_fps": 27.65529078792617,
"cpu": {
"avg_ms": 37.926895780927815,
"max_ms": 3484.08349609375,
"p50_ms": 3.398620128631592,
"p95_ms": 44.56385040283203,
"p99_ms": 684.4393920898438
},
"frames": 314,
"gpu": {
"avg_ms": 2.683724634467986,
"max_ms": 9.881600379943848,
"p50_ms": 1.8923519849777222,
"p95_ms": 7.221248149871826,
"p99_ms": 9.04089641571045
},
"low_1pct_fps": 0.4753349245465373,
"max_ms": 3484.115234375,
"p50_ms": 3.5420219898223877,
"p95_ms": 44.591251373291016,
"p99_ms": 159.3817901611328,
"seconds": 11.354066113710404
},
"ocean": {
"avg_fps": 59.16125632179682,
"cpu": {
"avg_ms": 16.807428855239674,
"max_ms": 106.0348129272461,
"p50_ms": 9.335607528686523,
"p95_ms": 44.57380294799805,
"p99_ms": 84.97154998779297
},
"frames": 712,
"gpu": {
"avg_ms": 1.958949391112736,
"max_ms": 8.635392189025879,
"p50_ms": 1.1182080507278442,
"p95_ms": 5.493760108947754,
"p99_ms": 7.108607769012451
},
"low_1pct_fps": 10.542641239411056,
"max_ms": 106.06544494628906,
"p50_ms": 9.364562034606934,
"p95_ms": 45.14366912841797,
"p99_ms": 84.9927749633789,
"seconds": 12.034903317928315
},
"mountain": {
"avg_fps": 26.78175419456072,
"cpu": {
"avg_ms": 20.230309660251326,
"max_ms": 128.05508422851562,
"p50_ms": 15.369550704956055,
"p95_ms": 67.15973663330078,
"p99_ms": 104.6961898803711
},
"frames": 325,
"gpu": {
"avg_ms": 7.143625645270714,
"max_ms": 21.25823974609375,
"p50_ms": 7.187456130981445,
"p95_ms": 12.228608131408691,
"p99_ms": 19.310592651367188
},
"low_1pct_fps": 7.777799947825389,
"max_ms": 155.30685424804688,
"p50_ms": 33.335182189941406,
"p95_ms": 68.94293975830078,
"p99_ms": 109.09304809570312,
"seconds": 12.135127431869506
}
},
"32": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 0,
"gpu": "NVIDIA GeForce RTX 4080",
"present_mode": "Immediate",
"size": [
1280,
720
],
"uploaded_bytes": 4829184
},
"village": {
"avg_fps": 4.1477100728464,
"cpu": {
"avg_ms": 244.17284844846142,
"max_ms": 386.7664489746094,
"p50_ms": 244.8783416748047,
"p95_ms": 363.0765380859375,
"p99_ms": 386.7664489746094
},
"frames": 49,
"gpu": {
"avg_ms": 10.357822744213806,
"max_ms": 23.010303497314453,
"p50_ms": 9.227264404296875,
"p95_ms": 19.309568405151367,
"p99_ms": 23.010303497314453
},
"low_1pct_fps": 2.5853636290905797,
"max_ms": 386.79278564453125,
"p50_ms": 230.8652801513672,
"p95_ms": 363.0941162109375,
"p99_ms": 386.79278564453125,
"seconds": 11.813747619628906
},
"forest": {
"avg_fps": 8.3624969613463,
"cpu": {
"avg_ms": 118.74922356747165,
"max_ms": 278.8187255859375,
"p50_ms": 123.03407287597656,
"p95_ms": 231.6608123779297,
"p99_ms": 260.8450622558594
},
"frames": 101,
"gpu": {
"avg_ms": 15.898816661669477,
"max_ms": 72.880126953125,
"p50_ms": 20.789247512817383,
"p95_ms": 28.441600799560547,
"p99_ms": 60.816383361816406
},
"low_1pct_fps": 3.7057290596141406,
"max_ms": 278.83917236328125,
"p50_ms": 123.19290161132812,
"p95_ms": 231.68026733398438,
"p99_ms": 260.8656921386719,
"seconds": 12.077732340812684
},
"ocean": {
"avg_fps": 2.3954947141714045,
"cpu": {
"avg_ms": 424.7621285574777,
"max_ms": 625.8532104492188,
"p50_ms": 435.64044189453125,
"p95_ms": 577.7593994140625,
"p99_ms": 625.8532104492188
},
"frames": 28,
"gpu": {
"avg_ms": 9.483117733682905,
"max_ms": 12.973055839538574,
"p50_ms": 9.90719985961914,
"p95_ms": 12.610560417175293,
"p99_ms": 12.973055839538574
},
"low_1pct_fps": 1.5977632874291703,
"max_ms": 625.8749389648438,
"p50_ms": 433.9859619140625,
"p95_ms": 577.7803955078125,
"p99_ms": 625.8749389648438,
"seconds": 11.688608551025391
},
"mountain": {
"avg_fps": 3.3756775332390268,
"cpu": {
"avg_ms": 300.512197249975,
"max_ms": 407.4363708496094,
"p50_ms": 292.483642578125,
"p95_ms": 394.8424377441406,
"p99_ms": 407.4363708496094
},
"frames": 39,
"gpu": {
"avg_ms": 9.728866460995796,
"max_ms": 18.930688858032227,
"p50_ms": 8.820735931396484,
"p95_ms": 17.399808883666992,
"p99_ms": 18.930688858032227
},
"low_1pct_fps": 2.4541792422631716,
"max_ms": 407.46820068359375,
"p50_ms": 292.4177551269531,
"p95_ms": 394.8649597167969,
"p99_ms": 407.46820068359375,
"seconds": 11.553236236572266
}
}
}
}
+392
View File
@@ -0,0 +1,392 @@
{
"label": "baseline-lavapipe",
"date": "2026-10-13",
"commit": "27a32cc3",
"host": "ludodesktop",
"offscreen": false,
"seed": "1234",
"flight_seconds": 12.0,
"scenes": {
"village": {
"from": [
-960.0,
125.0,
80.0
],
"to": [
-960.0,
125.0,
272.0
],
"pitch": 35.0
},
"forest": {
"from": [
-1100.0,
120.0,
-560.0
],
"to": [
-1100.0,
120.0,
-368.0
],
"pitch": 25.0
},
"ocean": {
"from": [
-300.0,
85.0,
-420.0
],
"to": [
-300.0,
85.0,
-228.0
],
"pitch": 10.0
},
"mountain": {
"from": [
560.0,
260.0,
860.0
],
"to": [
752.0,
260.0,
860.0
],
"pitch": 30.0
}
},
"distances": {
"8": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 146,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"present_mode": "Mailbox",
"size": [
1600,
1000
],
"uploaded_bytes": 1288851072
},
"village": {
"avg_fps": 16.38225374384963,
"cpu": {
"avg_ms": 48.17248754105975,
"max_ms": 134.31028747558594,
"p50_ms": 44.57072067260742,
"p95_ms": 97.15985870361328,
"p99_ms": 127.31073760986328
},
"frames": 199,
"gpu": {
"avg_ms": 26.732369270324707,
"max_ms": 47.3107795715332,
"p50_ms": 26.284116744995117,
"p95_ms": 35.006874084472656,
"p99_ms": 39.38005828857422
},
"low_1pct_fps": 6.569673692138871,
"max_ms": 169.97352600097656,
"p50_ms": 56.791988372802734,
"p95_ms": 109.15220642089844,
"p99_ms": 134.45559692382812,
"seconds": 12.147290788650512
},
"forest": {
"avg_fps": 19.917172468484612,
"cpu": {
"avg_ms": 31.039839970568817,
"max_ms": 106.39506530761719,
"p50_ms": 33.26064682006836,
"p95_ms": 70.09876251220703,
"p99_ms": 86.21255493164062
},
"frames": 240,
"gpu": {
"avg_ms": 37.272586759195285,
"max_ms": 77.586669921875,
"p50_ms": 34.38500213623047,
"p95_ms": 59.649635314941406,
"p99_ms": 66.52396392822266
},
"low_1pct_fps": 9.909291086862112,
"max_ms": 106.57542419433594,
"p50_ms": 46.05862808227539,
"p95_ms": 80.38935852050781,
"p99_ms": 94.94140625,
"seconds": 12.049903186798096
},
"ocean": {
"avg_fps": 27.969763129786234,
"cpu": {
"avg_ms": 25.69895526429727,
"max_ms": 930.7354125976562,
"p50_ms": 18.981081008911133,
"p95_ms": 39.42117691040039,
"p99_ms": 168.07225036621094
},
"frames": 336,
"gpu": {
"avg_ms": 18.856842384451912,
"max_ms": 57.835872650146484,
"p50_ms": 18.172868728637695,
"p95_ms": 28.62451171875,
"p99_ms": 44.414398193359375
},
"low_1pct_fps": 1.527565223414601,
"max_ms": 930.8734741210938,
"p50_ms": 26.45800018310547,
"p95_ms": 50.053672790527344,
"p99_ms": 180.92478942871094,
"seconds": 12.012972667694092
},
"mountain": {
"avg_fps": 26.5942562164059,
"cpu": {
"avg_ms": 22.482411369495093,
"max_ms": 104.89199829101562,
"p50_ms": 22.033512115478516,
"p95_ms": 46.385555267333984,
"p99_ms": 61.15697479248047
},
"frames": 320,
"gpu": {
"avg_ms": 23.762589550018312,
"max_ms": 48.10239028930664,
"p50_ms": 22.580347061157227,
"p95_ms": 35.14606475830078,
"p99_ms": 42.47938919067383
},
"low_1pct_fps": 11.197907022053611,
"max_ms": 105.07585906982422,
"p50_ms": 33.362815856933594,
"p95_ms": 53.36695098876953,
"p99_ms": 74.80219268798828,
"seconds": 12.03267342376709
}
},
"16": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 1,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"present_mode": "Mailbox",
"size": [
1600,
1000
],
"uploaded_bytes": 16106880
},
"village": {
"avg_fps": 10.754658718707336,
"cpu": {
"avg_ms": 69.22208800682655,
"max_ms": 193.21267700195312,
"p50_ms": 66.95130157470703,
"p95_ms": 154.44834899902344,
"p99_ms": 191.29208374023438
},
"frames": 130,
"gpu": {
"avg_ms": 49.041961078495945,
"max_ms": 73.83775329589844,
"p50_ms": 48.90928268432617,
"p95_ms": 60.60416793823242,
"p99_ms": 66.1044921875
},
"low_1pct_fps": 4.171866301284614,
"max_ms": 252.21458435058594,
"p50_ms": 79.8940200805664,
"p95_ms": 173.05947875976562,
"p99_ms": 227.18716430664062,
"seconds": 12.087784782409669
},
"forest": {
"avg_fps": 12.167278778001634,
"cpu": {
"avg_ms": 58.366991678873696,
"max_ms": 156.683349609375,
"p50_ms": 69.24014282226562,
"p95_ms": 110.83757019042969,
"p99_ms": 134.16554260253906
},
"frames": 147,
"gpu": {
"avg_ms": 56.45229888606716,
"max_ms": 78.26596069335938,
"p50_ms": 55.92947006225586,
"p95_ms": 63.54412841796875,
"p99_ms": 66.5202407836914
},
"low_1pct_fps": 5.722095670390665,
"max_ms": 212.99729919433594,
"p50_ms": 77.36986541748047,
"p95_ms": 122.84784698486328,
"p99_ms": 136.52499389648438,
"seconds": 12.081583950042724
},
"ocean": {
"avg_fps": 7.681804845753147,
"cpu": {
"avg_ms": 98.35419226740743,
"max_ms": 385.2493591308594,
"p50_ms": 78.85044860839844,
"p95_ms": 225.36231994628906,
"p99_ms": 385.2493591308594
},
"frames": 91,
"gpu": {
"avg_ms": 71.51263585297957,
"max_ms": 128.29212951660156,
"p50_ms": 67.92412567138672,
"p95_ms": 101.93219757080078,
"p99_ms": 128.29212951660156
},
"low_1pct_fps": 2.5948566279945817,
"max_ms": 385.37774658203125,
"p50_ms": 123.91693878173828,
"p95_ms": 225.49420166015625,
"p99_ms": 385.37774658203125,
"seconds": 11.846174411773681
},
"mountain": {
"avg_fps": 5.886844433101332,
"cpu": {
"avg_ms": 124.87309415575484,
"max_ms": 321.2157897949219,
"p50_ms": 117.2811050415039,
"p95_ms": 237.34304809570312,
"p99_ms": 321.2157897949219
},
"frames": 71,
"gpu": {
"avg_ms": 95.46965434816148,
"max_ms": 166.9488067626953,
"p50_ms": 83.54202270507812,
"p95_ms": 160.2403564453125,
"p99_ms": 166.9488067626953
},
"low_1pct_fps": 3.111272818975726,
"max_ms": 321.411865234375,
"p50_ms": 153.0963134765625,
"p95_ms": 275.37579345703125,
"p99_ms": 321.411865234375,
"seconds": 12.060790939331055
}
},
"32": {
"renderer": {
"backend": "Vulkan",
"drawn_sections": 1,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"present_mode": "Mailbox",
"size": [
1600,
1000
],
"uploaded_bytes": 19154560
},
"village": {
"avg_fps": 2.5956714101148957,
"cpu": {
"avg_ms": 345.63314671670236,
"max_ms": 474.2013854980469,
"p50_ms": 347.07415771484375,
"p95_ms": 468.0090026855469,
"p99_ms": 474.2013854980469
},
"frames": 31,
"gpu": {
"avg_ms": 85.50063645839691,
"max_ms": 134.11460876464844,
"p50_ms": 82.40946960449219,
"p95_ms": 133.71929931640625,
"p99_ms": 134.11460876464844
},
"low_1pct_fps": 2.01406006678458,
"max_ms": 496.509521484375,
"p50_ms": 390.230224609375,
"p95_ms": 493.8070373535156,
"p99_ms": 496.509521484375,
"seconds": 11.942960067749024
},
"forest": {
"avg_fps": 2.2283930626963917,
"cpu": {
"avg_ms": 354.7813931978666,
"max_ms": 611.8099975585938,
"p50_ms": 293.61376953125,
"p95_ms": 601.3502197265625,
"p99_ms": 611.8099975585938
},
"frames": 26,
"gpu": {
"avg_ms": 201.54420654296874,
"max_ms": 357.0310363769531,
"p50_ms": 172.65980529785156,
"p95_ms": 341.8655700683594,
"p99_ms": 357.0310363769531
},
"low_1pct_fps": 1.52339962842959,
"max_ms": 656.4265747070312,
"p50_ms": 407.1051330566406,
"p95_ms": 611.97119140625,
"p99_ms": 656.4265747070312,
"seconds": 11.667600494384766
},
"ocean": {
"avg_fps": 2.6137193379326398,
"cpu": {
"avg_ms": 330.783615620931,
"max_ms": 730.7304077148438,
"p50_ms": 296.65692138671875,
"p95_ms": 680.8717041015625,
"p99_ms": 730.7304077148438
},
"frames": 30,
"gpu": {
"avg_ms": 113.80178985595703,
"max_ms": 216.57342529296875,
"p50_ms": 104.23703002929688,
"p95_ms": 193.67672729492188,
"p99_ms": 216.57342529296875
},
"low_1pct_fps": 1.1784160273210693,
"max_ms": 848.5967407226562,
"p50_ms": 346.120849609375,
"p95_ms": 681.0716552734375,
"p99_ms": 848.5967407226562,
"seconds": 11.477896484375
},
"mountain": {
"avg_fps": 2.72441042065798,
"cpu": {
"avg_ms": 325.24547207740045,
"max_ms": 578.7177124023438,
"p50_ms": 295.25457763671875,
"p95_ms": 569.8099975585938,
"p99_ms": 578.7177124023438
},
"frames": 31,
"gpu": {
"avg_ms": 104.99177145957947,
"max_ms": 163.95635986328125,
"p50_ms": 99.96784210205078,
"p95_ms": 160.04824829101562,
"p99_ms": 163.95635986328125
},
"low_1pct_fps": 1.7544071931551564,
"max_ms": 569.9931030273438,
"p50_ms": 378.246337890625,
"p95_ms": 555.5369873046875,
"p99_ms": 569.9931030273438,
"seconds": 11.378608657836914
}
}
}
}
File diff suppressed because it is too large. Load diff
@@ -1,42 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Darwin 25.6.0 arm64; logical CPUs 3
mode=upstream trial=0 incoming_after_idle_ms=26.655 publication_to_pop_ms=27.930
mode=wakeable trial=0 incoming_after_idle_ms=23.086 publication_to_pop_ms=0.098
mode=upstream trial=1 incoming_after_idle_ms=25.029 publication_to_pop_ms=94.707
mode=wakeable trial=1 incoming_after_idle_ms=19.340 publication_to_pop_ms=16.096
mode=upstream trial=2 incoming_after_idle_ms=16.530 publication_to_pop_ms=98.696
mode=wakeable trial=2 incoming_after_idle_ms=12.085 publication_to_pop_ms=0.080
mode=upstream trial=3 incoming_after_idle_ms=20.350 publication_to_pop_ms=50.086
mode=wakeable trial=3 incoming_after_idle_ms=15.681 publication_to_pop_ms=0.051
mode=upstream trial=4 incoming_after_idle_ms=26.474 publication_to_pop_ms=90.380
mode=wakeable trial=4 incoming_after_idle_ms=21.794 publication_to_pop_ms=0.054
mode=upstream trial=5 incoming_after_idle_ms=20.069 publication_to_pop_ms=91.508
mode=wakeable trial=5 incoming_after_idle_ms=14.527 publication_to_pop_ms=0.069
mode=upstream trial=6 incoming_after_idle_ms=25.051 publication_to_pop_ms=58.889
mode=wakeable trial=6 incoming_after_idle_ms=20.193 publication_to_pop_ms=0.081
mode=upstream trial=7 incoming_after_idle_ms=12.084 publication_to_pop_ms=41.323
mode=wakeable trial=7 incoming_after_idle_ms=5.867 publication_to_pop_ms=0.057
mode=upstream trial=8 incoming_after_idle_ms=19.023 publication_to_pop_ms=99.615
mode=wakeable trial=8 incoming_after_idle_ms=18.833 publication_to_pop_ms=0.063
mode=upstream trial=9 incoming_after_idle_ms=13.648 publication_to_pop_ms=103.446
mode=wakeable trial=9 incoming_after_idle_ms=28.375 publication_to_pop_ms=0.056
mode=upstream trial=10 incoming_after_idle_ms=17.449 publication_to_pop_ms=98.829
mode=wakeable trial=10 incoming_after_idle_ms=24.812 publication_to_pop_ms=0.062
mode=upstream trial=11 incoming_after_idle_ms=26.751 publication_to_pop_ms=88.715
mode=wakeable trial=11 incoming_after_idle_ms=28.154 publication_to_pop_ms=0.067
mode=upstream trial=12 incoming_after_idle_ms=20.596 publication_to_pop_ms=73.247
mode=wakeable trial=12 incoming_after_idle_ms=16.397 publication_to_pop_ms=0.080
mode=upstream trial=13 incoming_after_idle_ms=19.685 publication_to_pop_ms=53.674
mode=wakeable trial=13 incoming_after_idle_ms=21.934 publication_to_pop_ms=0.050
mode=upstream trial=14 incoming_after_idle_ms=16.937 publication_to_pop_ms=37.755
mode=wakeable trial=14 incoming_after_idle_ms=18.296 publication_to_pop_ms=0.074
mode=upstream trial=15 incoming_after_idle_ms=17.572 publication_to_pop_ms=68.115
mode=wakeable trial=15 incoming_after_idle_ms=13.516 publication_to_pop_ms=0.072
mode=upstream trial=16 incoming_after_idle_ms=24.639 publication_to_pop_ms=100.433
mode=wakeable trial=16 incoming_after_idle_ms=22.918 publication_to_pop_ms=0.103
mode=upstream trial=17 incoming_after_idle_ms=30.593 publication_to_pop_ms=79.830
mode=wakeable trial=17 incoming_after_idle_ms=25.080 publication_to_pop_ms=0.053
mode=upstream trial=18 incoming_after_idle_ms=15.889 publication_to_pop_ms=108.892
mode=wakeable trial=18 incoming_after_idle_ms=27.297 publication_to_pop_ms=0.034
mode=upstream trial=19 incoming_after_idle_ms=10.808 publication_to_pop_ms=59.234
mode=wakeable trial=19 incoming_after_idle_ms=16.349 publication_to_pop_ms=0.083
@@ -1,42 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Linux 6.17.0-1022-azure x86_64; logical CPUs 4
mode=upstream trial=0 incoming_after_idle_ms=5.089 publication_to_pop_ms=45.143
mode=wakeable trial=0 incoming_after_idle_ms=5.100 publication_to_pop_ms=0.073
mode=upstream trial=1 incoming_after_idle_ms=5.125 publication_to_pop_ms=45.051
mode=wakeable trial=1 incoming_after_idle_ms=5.097 publication_to_pop_ms=0.055
mode=upstream trial=2 incoming_after_idle_ms=5.098 publication_to_pop_ms=45.135
mode=wakeable trial=2 incoming_after_idle_ms=5.088 publication_to_pop_ms=0.042
mode=upstream trial=3 incoming_after_idle_ms=5.091 publication_to_pop_ms=45.084
mode=wakeable trial=3 incoming_after_idle_ms=5.149 publication_to_pop_ms=0.049
mode=upstream trial=4 incoming_after_idle_ms=5.103 publication_to_pop_ms=45.060
mode=wakeable trial=4 incoming_after_idle_ms=5.141 publication_to_pop_ms=0.064
mode=upstream trial=5 incoming_after_idle_ms=5.127 publication_to_pop_ms=45.047
mode=wakeable trial=5 incoming_after_idle_ms=5.137 publication_to_pop_ms=0.053
mode=upstream trial=6 incoming_after_idle_ms=5.129 publication_to_pop_ms=45.177
mode=wakeable trial=6 incoming_after_idle_ms=5.134 publication_to_pop_ms=0.068
mode=upstream trial=7 incoming_after_idle_ms=5.107 publication_to_pop_ms=45.059
mode=wakeable trial=7 incoming_after_idle_ms=5.137 publication_to_pop_ms=0.061
mode=upstream trial=8 incoming_after_idle_ms=5.168 publication_to_pop_ms=45.005
mode=wakeable trial=8 incoming_after_idle_ms=5.134 publication_to_pop_ms=0.060
mode=upstream trial=9 incoming_after_idle_ms=5.105 publication_to_pop_ms=45.077
mode=wakeable trial=9 incoming_after_idle_ms=5.148 publication_to_pop_ms=0.070
mode=upstream trial=10 incoming_after_idle_ms=5.092 publication_to_pop_ms=45.197
mode=wakeable trial=10 incoming_after_idle_ms=5.136 publication_to_pop_ms=0.055
mode=upstream trial=11 incoming_after_idle_ms=5.113 publication_to_pop_ms=45.045
mode=wakeable trial=11 incoming_after_idle_ms=5.122 publication_to_pop_ms=0.044
mode=upstream trial=12 incoming_after_idle_ms=5.095 publication_to_pop_ms=45.070
mode=wakeable trial=12 incoming_after_idle_ms=5.147 publication_to_pop_ms=0.052
mode=upstream trial=13 incoming_after_idle_ms=5.118 publication_to_pop_ms=45.048
mode=wakeable trial=13 incoming_after_idle_ms=5.168 publication_to_pop_ms=0.047
mode=upstream trial=14 incoming_after_idle_ms=5.133 publication_to_pop_ms=45.129
mode=wakeable trial=14 incoming_after_idle_ms=5.155 publication_to_pop_ms=0.047
mode=upstream trial=15 incoming_after_idle_ms=5.098 publication_to_pop_ms=45.031
mode=wakeable trial=15 incoming_after_idle_ms=5.167 publication_to_pop_ms=0.044
mode=upstream trial=16 incoming_after_idle_ms=5.129 publication_to_pop_ms=45.051
mode=wakeable trial=16 incoming_after_idle_ms=5.135 publication_to_pop_ms=0.073
mode=upstream trial=17 incoming_after_idle_ms=5.148 publication_to_pop_ms=45.034
mode=wakeable trial=17 incoming_after_idle_ms=5.148 publication_to_pop_ms=0.044
mode=upstream trial=18 incoming_after_idle_ms=5.181 publication_to_pop_ms=45.103
mode=wakeable trial=18 incoming_after_idle_ms=5.127 publication_to_pop_ms=0.046
mode=upstream trial=19 incoming_after_idle_ms=5.094 publication_to_pop_ms=45.075
mode=wakeable trial=19 incoming_after_idle_ms=5.148 publication_to_pop_ms=0.051
@@ -1,42 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Windows 2025Server AMD64; logical CPUs 4
mode=upstream trial=0 incoming_after_idle_ms=5.487 publication_to_pop_ms=45.519
mode=wakeable trial=0 incoming_after_idle_ms=5.377 publication_to_pop_ms=0.127
mode=upstream trial=1 incoming_after_idle_ms=6.059 publication_to_pop_ms=44.593
mode=wakeable trial=1 incoming_after_idle_ms=5.539 publication_to_pop_ms=0.094
mode=upstream trial=2 incoming_after_idle_ms=5.096 publication_to_pop_ms=45.005
mode=wakeable trial=2 incoming_after_idle_ms=5.624 publication_to_pop_ms=0.079
mode=upstream trial=3 incoming_after_idle_ms=5.649 publication_to_pop_ms=44.691
mode=wakeable trial=3 incoming_after_idle_ms=4.731 publication_to_pop_ms=0.077
mode=upstream trial=4 incoming_after_idle_ms=5.312 publication_to_pop_ms=45.488
mode=wakeable trial=4 incoming_after_idle_ms=5.156 publication_to_pop_ms=0.108
mode=upstream trial=5 incoming_after_idle_ms=5.190 publication_to_pop_ms=45.580
mode=wakeable trial=5 incoming_after_idle_ms=5.457 publication_to_pop_ms=0.077
mode=upstream trial=6 incoming_after_idle_ms=5.141 publication_to_pop_ms=45.619
mode=wakeable trial=6 incoming_after_idle_ms=5.592 publication_to_pop_ms=0.074
mode=upstream trial=7 incoming_after_idle_ms=5.823 publication_to_pop_ms=44.487
mode=wakeable trial=7 incoming_after_idle_ms=5.355 publication_to_pop_ms=0.066
mode=upstream trial=8 incoming_after_idle_ms=5.675 publication_to_pop_ms=45.050
mode=wakeable trial=8 incoming_after_idle_ms=5.252 publication_to_pop_ms=0.075
mode=upstream trial=9 incoming_after_idle_ms=5.921 publication_to_pop_ms=44.505
mode=wakeable trial=9 incoming_after_idle_ms=6.002 publication_to_pop_ms=0.072
mode=upstream trial=10 incoming_after_idle_ms=5.797 publication_to_pop_ms=44.517
mode=wakeable trial=10 incoming_after_idle_ms=5.103 publication_to_pop_ms=0.070
mode=upstream trial=11 incoming_after_idle_ms=5.115 publication_to_pop_ms=45.066
mode=wakeable trial=11 incoming_after_idle_ms=5.638 publication_to_pop_ms=0.071
mode=upstream trial=12 incoming_after_idle_ms=5.239 publication_to_pop_ms=45.538
mode=wakeable trial=12 incoming_after_idle_ms=5.666 publication_to_pop_ms=0.083
mode=upstream trial=13 incoming_after_idle_ms=5.136 publication_to_pop_ms=45.251
mode=wakeable trial=13 incoming_after_idle_ms=4.163 publication_to_pop_ms=0.073
mode=upstream trial=14 incoming_after_idle_ms=5.256 publication_to_pop_ms=46.048
mode=wakeable trial=14 incoming_after_idle_ms=5.545 publication_to_pop_ms=0.074
mode=upstream trial=15 incoming_after_idle_ms=4.239 publication_to_pop_ms=47.028
mode=wakeable trial=15 incoming_after_idle_ms=5.292 publication_to_pop_ms=0.053
mode=upstream trial=16 incoming_after_idle_ms=5.959 publication_to_pop_ms=45.046
mode=wakeable trial=16 incoming_after_idle_ms=5.230 publication_to_pop_ms=0.182
mode=upstream trial=17 incoming_after_idle_ms=5.153 publication_to_pop_ms=45.005
mode=wakeable trial=17 incoming_after_idle_ms=5.220 publication_to_pop_ms=0.066
mode=upstream trial=18 incoming_after_idle_ms=5.358 publication_to_pop_ms=46.008
mode=wakeable trial=18 incoming_after_idle_ms=5.156 publication_to_pop_ms=0.062
mode=upstream trial=19 incoming_after_idle_ms=4.370 publication_to_pop_ms=47.015
mode=wakeable trial=19 incoming_after_idle_ms=5.162 publication_to_pop_ms=0.073
@@ -1,930 +0,0 @@
{
"schema": 1,
"measurement": "Failed hosted macOS Vulkan graphics probes, not performance measurements",
"source_commit": "8282a731ecc08691f798a3ec596c7cc1d4f1dad1",
"run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37193558884",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"cases": [
{
"case": [
"--profile",
"baseline",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"profile": "baseline",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"core-performance",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"profile": "core-performance",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"profile": "vulkan",
"preferred_backend": "vulkan"
}
]
}
],
"limits": [
"Apple Paravirtual device and MoltenVK on a hosted ARM Mac; not physical M2 Pro GPU testing.",
"Library/device creation and readback request were observed, but no completed nonuniform readback report was produced.",
"All failures retained; neither successful rendering nor a screenshot-specific root cause is established.",
"Baseline includes the same original measurement mod and private test fixture; no core optimization mods or distant terrain.",
"Full logs, screenshots, game binaries and assets remain private.",
"Later selected stack locations place the observed failures in the screenshot callback; the independently logged Vulkan identifier is not established as their cause.",
"Actual assertions rejected uniform callback images in all three cases. Overlay state was not recorded, and displayed-window correctness is not established.",
"After guarding overlays, core/distant-terrain title readbacks pass but vanilla remains uniform; the aggregate research run fails. No world-rendering or physical-M2 claim.",
"Later world probes pass all three Vulkan cases on the hosted Mac; failed title cases remain retained. These are short startup/readback/save probes, not physical-GPU performance tests."
],
"later_stack_run": {
"source_commit": "a77476b54e7bf4a1b3a96cb9d8108ed7c1c7b2b0",
"run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37193954843",
"cases": [
{
"case": [
"--profile",
"baseline",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "baseline",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"core-performance",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "core-performance",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "vulkan",
"preferred_backend": "vulkan"
}
]
}
]
},
"later_pixel_run": {
"source_commit": "213498c77ed643617083dacf4aaa283a1cb4815a",
"run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37194354615",
"cases": [
{
"case": [
"--profile",
"baseline",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"readback_callback_received": true,
"readback_inspections": [
{
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1
}
],
"probe_failure_categories": [
"uniform_readback"
],
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "baseline",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"core-performance",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"readback_callback_received": true,
"readback_inspections": [
{
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1
}
],
"probe_failure_categories": [
"uniform_readback"
],
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "core-performance",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"readback_callback_received": true,
"readback_inspections": [
{
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1
}
],
"probe_failure_categories": [
"uniform_readback"
],
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "vulkan",
"preferred_backend": "vulkan"
}
]
}
]
},
"later_overlay_run": {
"source_commit": "a1d8c1b8246008ac4076cdcaf0f64c71eaf4c767",
"run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37194690645",
"cases": [
{
"case": [
"--profile",
"baseline",
"--backend",
"vulkan"
],
"exit_code": 1,
"failure": [
{
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"readback_callback_received": true,
"readback_inspections": [
{
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1
}
],
"probe_failure_categories": [
"uniform_readback"
],
"vulkan_error_codes": [
"VK_ERROR_FEATURE_NOT_PRESENT"
],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
],
"profile": "baseline",
"preferred_backend": "vulkan"
}
]
},
{
"case": [
"--profile",
"core-performance",
"--backend",
"vulkan"
],
"exit_code": 0,
"report": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "title",
"title_screen_observed": true,
"world_loaded": false,
"ready_client_ticks": 42,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 105,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 163,
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2",
"private_png_sha256": "3c802923766cf9e7f45020bc2d858c23de655cb8e35fa058a050e7b09a1d3708",
"profile": "core-performance",
"preferred_backend": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
},
{
"case": [
"--profile",
"vulkan"
],
"exit_code": 0,
"report": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "title",
"title_screen_observed": true,
"world_loaded": false,
"ready_client_ticks": 42,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 122,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 163,
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2",
"private_png_sha256": "3c802923766cf9e7f45020bc2d858c23de655cb8e35fa058a050e7b09a1d3708",
"profile": "vulkan",
"preferred_backend": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
}
]
},
"later_world_run": {
"source_commit": "5f9f973295c5cc948a6999a849c2c843f5e831f6",
"run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37195149166",
"cases": [
{
"case": [
"--profile",
"baseline",
"--backend",
"vulkan",
"--world"
],
"exit_code": 0,
"report": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 42,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 323,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1278,
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2",
"private_png_sha256": "9e9be2562390f24fe8c8e0442ef9cdfd47910febd95d8f0c0f5706191a53f1f6",
"profile": "baseline",
"preferred_backend": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
},
{
"case": [
"--profile",
"core-performance",
"--backend",
"vulkan",
"--world"
],
"exit_code": 0,
"report": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 51,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 90,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1024,
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2",
"private_png_sha256": "e0a6ad253ca0490b35217ce9ad799dc7d4c04e4ecf446eeacd1aa5196db317bb",
"profile": "core-performance",
"preferred_backend": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
},
{
"case": [
"--profile",
"vulkan",
"--world"
],
"exit_code": 0,
"report": {
"schema": 1,
"platform": "macOS-26.6.2-arm64-arm-64bit",
"architecture": "arm64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 53,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 88,
"framebuffer_width": 1280,
"framebuffer_height": 646,
"sampled_pixels": 4160,
"distinct_sampled_rgb": 1287,
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2",
"private_png_sha256": "a17d1740e34cc9f49b67a4c56f51d0843f756e9d2eb3d19d6a926ad5f8f0ed36",
"profile": "vulkan",
"preferred_backend": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
}
]
},
"local_linux_core_vulkan_world": {
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 47,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 111,
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 1895,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "Vulkan",
"graphics_driver": "1.4.335 llvmpipe Mesa 26.0.8-1ubuntu0.3 (LLVM 21.1.8)",
"private_png_sha256": "52b26102b3037cab4ab6b7011a6c1255eebaa808d1d3dd5e77ff23fcde092acb",
"profile": "core-performance",
"preferred_backend": "vulkan",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
}
}
@@ -0,0 +1,69 @@
# Reuse parsed model states
`models::prepare` parsed `model-states.json` to select blocks, then
`StateModels::load` reopened and parsed the same document for binding and baking.
`StateModels::from_facts` now borrows the first parsed map. The public `load`
entry point still reads, parses and validates its own document. Both paths retain
the `fs::read` + `serde_json::from_slice` strategy merged in PR #205.
The shared map uses `BTreeMap`, preserving the original catalog loader's JSON
validation, including rejection of top-level `null`. The old selection map was
`serde_json::Map`, also backed by a BTreeMap with the project's current features.
Catalog binding, model selection and baking are unchanged. Preparation no longer
holds a second complete JSON tree while constructing the catalog; no persistent
cache or extra clones were added.
## Measurement
The committed `model_states_bench` example runs main's two-parse sequence after PR #205
(first a serde JSON map, then `StateModels::load`) and the new one-parse sequence
(first a BTreeMap, then `StateModels::from_facts`). Both select blocks from the
same generated document with slice parsing and call the actual catalog binding/baking code. Timing
includes file reads, parsing, filtering, binding, baking and result destruction.
Fixture generation and equality checks run outside the timed region.
Prepared Minecraft resources were unavailable locally, so this is a synthetic
2,836,696-byte document containing 843 block schemas and 53,952 states. Schemas
combine integer and named properties. Blockstate resources use weighted and
conditional multipart choices with rotations and UV locking, sharing one model
with a baked face. Its absent texture uses the normal missing-sprite fallback.
Both paths read identical files with a warm OS cache. The workload does not
represent the full diversity of production model and texture assets.
On AMD Ryzen 5 5600X, Linux 7.2.8-zen1-2-zen x86_64, rustc 1.99.0
(b940084d7 2026-09-28), Cargo `fast` profile, serial execution:
| Path | Median (15 samples) |
| --- | ---: |
| Before: parse twice, with #205 slice readers | 96.080 ms |
| After: reuse first parse, with #205 slice readers | 73.585 ms |
**1.306x speedup; 23.41% less elapsed time** for this loading segment after PR #205. Each path
has two warmups, sample order alternates, and inputs/results use `black_box`.
This excludes gallery placements, GPU work and overall application startup.
These measurements supersede the original unbuffered-reader timings
(2732.004 ms → 1386.060 ms, 1.971x) after rebasing onto main at
`e96e1571`. The reviewer measured approximately 1.05x with real prepared resources;
the generated fixture's balance of parsing and binding differs from production.
The change still removes one complete document read, parse and JSON tree.
Equality validation compares every state's selected variants and baked geometry
at three positions, plus sprite layers and opacity/translucency flags. The
focused test also checks matching schema/registry errors, malformed/missing
source files, rejection of `null`, and successful shared-facts loading after the
source file has been deleted.
## Reproduce
```sh
export CARGO_TARGET_DIR=/home/bob/Documents/horizon/target
export CARGO_INCREMENTAL=0
cargo run -p horizon-client --profile fast --example model_states_bench -- 15
cargo test -p horizon-client --profile fast --example model_states_bench
cargo clippy -p horizon-client --all-targets --profile fast -- -D warnings
cargo fmt --all -- --check
```
The target directory can be changed for another machine. The example creates and
removes its fixtures in the system temporary directory.
@@ -1,104 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Darwin 25.6.0 arm64; logical CPUs 3
fork=0 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=0 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
fork=1 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=1 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
fork=2 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=2 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
@@ -1,104 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Linux 6.17.0-1022-azure x86_64; logical CPUs 4
fork=0 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=0 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
fork=1 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=1 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
fork=2 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=2 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
@@ -1,104 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Windows 2025Server AMD64; logical CPUs 4
fork=0 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=0 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
fork=1 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=1 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
fork=2 requested_compact_headers=False
compact_object_headers=false
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=AABB objects=100000 allocated_bytes=6400000 bytes_per_object=64.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=Vec3 objects=100000 allocated_bytes=4000000 bytes_per_object=40.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
fork=2 requested_compact_headers=True
compact_object_headers=true
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=AABB objects=100000 allocated_bytes=5600000 bytes_per_object=56.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=Vec3 objects=100000 allocated_bytes=3200000 bytes_per_object=32.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=DhChunkPos objects=100000 allocated_bytes=2400000 bytes_per_object=24.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Long objects=100000 allocated_bytes=1600000 bytes_per_object=16.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
type=Object objects=100000 allocated_bytes=800000 bytes_per_object=8.000
@@ -0,0 +1,54 @@
{
"date": "2026-10-15",
"environment": "Linux x86_64/ext4/NVMe, Ryzen5 5600X, Rust1.99.0, Cargo fast",
"scope": "actual resource_root vs original wrapper/builder; warmed storage; output equivalence outside timing",
"warmups": 2,
"median_samples": 11,
"prepared_minecraft": "26.3",
"prepared_schema": 7,
"prepared_manifest_sha256": "fd03c686302748748e132ef3978b7b0bcf42024257e802985a5cc7175cc74298",
"packs": [
{
"project": "faithful-32x",
"version": "lDYpMiqk",
"version_name": "[26.3] Faithful 32x \u2013 September 2026 Release",
"publisher_page": "https://modrinth.com/resourcepack/faithful-32x/version/lDYpMiqk",
"download_url": "https://cdn.modrinth.com/data/w0TnApzs/versions/lDYpMiqk/Faithful%2032x%20-%2026.3.zip",
"zip_bytes": 13116019,
"zip_sha512": "e90ec63af7f239dbb99aa20c98b23d830e76898f65d3e31b7f0b53bb36db12dcd8c38d6930c743237c9c3db7bf708423fa1d1b2fd497dd6c281dbe216b779db9",
"asset_files": 5063,
"assets_uncompressed_bytes": 12524266,
"original_ms": 159.827,
"cold_ms": 162.711,
"hit_ms": 0.707
},
{
"project": "default-hd-128x",
"version": "rErHu3BE",
"version_name": "Default HD 128x Demo/Alpha 1.8.2.7",
"publisher_page": "https://modrinth.com/resourcepack/default-hd-128x/version/rErHu3BE",
"download_url": "https://cdn.modrinth.com/data/orfTV6nk/versions/rErHu3BE/Default%20HD%20128x%20Demo%201.8.2.7.zip",
"zip_bytes": 16876419,
"zip_sha512": "f5f9606e92b986cd9c8b8e5ff2bb52db720cc7b38e013355bdc90089e01975a08d09750ef2fd727f753d88ec3fbcd067355179b490587f667b2995f8be81640f",
"asset_files": 2318,
"assets_uncompressed_bytes": 17315416,
"original_ms": 111.501,
"cold_ms": 114.386,
"hit_ms": 0.31
},
{
"project": "fpbr",
"version": "dynf82xk",
"version_name": "support 1.21.9 and newer",
"publisher_page": "https://modrinth.com/resourcepack/fpbr/version/dynf82xk",
"download_url": "https://cdn.modrinth.com/data/nvEpbd8t/versions/dynf82xk/FPBR-Main-1.21.9-R1.3.zip",
"zip_bytes": 46737770,
"zip_sha512": "64f1bbd036e205118f1d9c49a79558db2c1356ee988fb939c0023db1967d78e1bd05047f341ce6d65355717ba7ddb1330af57edbb4d5b8713c96ae62987274c5",
"asset_files": 7001,
"assets_uncompressed_bytes": 56356903,
"original_ms": 347.639,
"cold_ms": 348.012,
"hit_ms": 0.448
}
]
}
@@ -1,67 +0,0 @@
{
"schema": 1,
"purpose": "Earlier private quad-reuse explorations; CPU mixed and allocation reduction is not retained RAM/FPS",
"original_mod_sha256": "98f8db7ca8962a71625eef835f57d25c8afb802f2cf1b7c4c832fc070757e011",
"private_fixture_sources": "Uncommitted private prototype before the production-hook fixture; not the final reproducible protocol",
"observations": [
{
"private_probe": "latest-discarded-object",
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"geometry_digest": "31509677879305c6a721677b38516fda0336f8c7b53dc3946839eb6fbf7fd0ee",
"geometry_quads": 108358,
"input_faces": 55296,
"measured_faces": 3072000,
"checksum": 60000,
"cpu_ns": 166481448,
"allocated_bytes": 144576000,
"observations": [
{
"cpu_ns": 54349387,
"allocated_bytes": 48192000
},
{
"cpu_ns": 84133914,
"allocated_bytes": 48192000
},
{
"cpu_ns": 27998147,
"allocated_bytes": 48192000
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"geometry_digest": "31509677879305c6a721677b38516fda0336f8c7b53dc3946839eb6fbf7fd0ee",
"geometry_quads": 108358,
"input_faces": 55296,
"measured_faces": 3072000,
"checksum": 60000,
"cpu_ns": 185505067,
"allocated_bytes": 2016000,
"observations": [
{
"cpu_ns": 59897923,
"allocated_bytes": 672000
},
{
"cpu_ns": 63778316,
"allocated_bytes": 672000
},
{
"cpu_ns": 61828828,
"allocated_bytes": 672000
}
]
}
]
},
{
"private_probe": "first-discarded-object",
"results": []
}
]
}
@@ -1,75 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "2196637c5b2180a33fa5b926ab51069ab480618c1186b8a02872c7e758be0a70",
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"geometry_digest": "8251175aa3e3cac30bb1366f8b40d0576c17978076ea7d244ff4d7cc361da7ee",
"thread_geometry_digest": "096a85be06031d248f12e536e19e5c0496bb00c80f3387f670a0fae29438a732",
"thread_workers": 4,
"geometry_quads": 108358,
"input_faces": 55296,
"measured_faces": 3072000,
"checksum": 60000,
"cpu_ns": 40437624,
"allocated_bytes": 144576000,
"observations": [
{
"cpu_ns": 13455029,
"allocated_bytes": 48192000
},
{
"cpu_ns": 13828075,
"allocated_bytes": 48192000
},
{
"cpu_ns": 13154520,
"allocated_bytes": 48192000
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"geometry_digest": "8251175aa3e3cac30bb1366f8b40d0576c17978076ea7d244ff4d7cc361da7ee",
"thread_geometry_digest": "096a85be06031d248f12e536e19e5c0496bb00c80f3387f670a0fae29438a732",
"thread_workers": 4,
"geometry_quads": 108358,
"input_faces": 55296,
"measured_faces": 3072000,
"checksum": 60000,
"cpu_ns": 44074799,
"allocated_bytes": 2016000,
"observations": [
{
"cpu_ns": 16004752,
"allocated_bytes": 672000
},
{
"cpu_ns": 14047833,
"allocated_bytes": 672000
},
{
"cpu_ns": 14022214,
"allocated_bytes": 672000
}
]
}
],
"notes": [
"Actual publisher quad builder inside Fabric with generated faces and lighting/material values.",
"Opaque/translucent geometry, pooled error flags and every retained quad field match before and after upstream merging.",
"Fresh allocations reuse at most one discarded successful-premerge quad; existing pool selection stays upstream.",
"Three sequential warmed caller-loop observations are not independent forks; compilation can vary.",
"Allocation reduction is not retained RAM, game FPS or a Mac GPU benchmark."
],
"provenance": {
"source_commit": "0a0cd667d5cfdee7c59f5fe2c7a2eb15bd19e66e",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37175709062"
}
}
@@ -1,166 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "2196637c5b2180a33fa5b926ab51069ab480618c1186b8a02872c7e758be0a70",
"platform": "Linux x86_64",
"graphics": "llvmpipe software OpenGL",
"settings": {
"heap_bytes": 3221225472,
"gc": "G1",
"compact_headers": true,
"render_distance": 12,
"simulation_distance": 12,
"lod_radius_chunks": 128,
"lod_quality": "MEDIUM/MEDIUM/BLOCK",
"terrain_workers": 2,
"runtime_ratio": 0.5,
"world_difficulty": "PEACEFUL"
},
"results": [
{
"profile": "m2-balanced",
"quad_reuse_enabled": false,
"elapsed_seconds": 120.415309971,
"frame_samples": 220,
"tick_samples": 2400,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"frame_stats": {
"count": 220,
"meanMs": 542.3438610045455,
"p50Ms": 522.365908,
"p95Ms": 713.237831,
"p99Ms": 860.91664,
"maxMs": 885.115974,
"meanRate": 1.8438486574693962,
"lowOnePercentRate": 1.1446485854821962,
"over16Ms": 220,
"over33Ms": 220,
"over50Ms": 220,
"over100Ms": 220
},
"tick_stats": {
"count": 2400,
"meanMs": 9.639125558749999,
"p50Ms": 9.137695,
"p95Ms": 16.989389,
"p99Ms": 25.152306,
"maxMs": 52.879001,
"meanRate": 103.74385040479541,
"lowOnePercentRate": 30.37834831626593,
"over16Ms": 133,
"over33Ms": 8,
"over50Ms": 2,
"over100Ms": 0
},
"process_rss_peak_sampled_bytes": 3129790464,
"render_loader_allocation_counters": [
{
"thread_id": 124,
"thread": "DH-Render Loader Thread[1]",
"counter_observations": 2,
"observed_seconds": 64.375191422,
"observed_allocated_bytes": 97869576,
"observed_bytes_per_second": 1520299.5725237317
},
{
"thread_id": 123,
"thread": "DH-Render Loader Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.375191422,
"observed_allocated_bytes": 91443128,
"observed_bytes_per_second": 1420471.5509203072
}
],
"preceding_jfr_gc_pause_total_ms": 263.975028,
"preceding_jfr_gc_pause_longest_ms": 45.0698
},
{
"profile": "quad-reuse",
"quad_reuse_enabled": true,
"elapsed_seconds": 120.476138714,
"frame_samples": 224,
"tick_samples": 2401,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"frame_stats": {
"count": 224,
"meanMs": 532.6331643258928,
"p50Ms": 505.6209,
"p95Ms": 735.235244,
"p99Ms": 774.189261,
"maxMs": 926.006251,
"meanRate": 1.8774647674551252,
"lowOnePercentRate": 1.208934822852848,
"over16Ms": 224,
"over33Ms": 224,
"over50Ms": 224,
"over100Ms": 224
},
"tick_stats": {
"count": 2401,
"meanMs": 9.308558193669304,
"p50Ms": 8.82277,
"p95Ms": 16.529268,
"p99Ms": 22.206144,
"maxMs": 95.741877,
"meanRate": 107.42802259968617,
"lowOnePercentRate": 30.32324112917506,
"over16Ms": 114,
"over33Ms": 8,
"over50Ms": 3,
"over100Ms": 0
},
"process_rss_peak_sampled_bytes": 3100016640,
"render_loader_allocation_counters": [
{
"thread_id": 125,
"thread": "DH-Render Loader Thread[1]",
"counter_observations": 2,
"observed_seconds": 64.347664971,
"observed_allocated_bytes": 116155920,
"observed_bytes_per_second": 1805130.3035214841
},
{
"thread_id": 124,
"thread": "DH-Render Loader Thread[0]",
"counter_observations": 2,
"observed_seconds": 64.347664971,
"observed_allocated_bytes": 104401656,
"observed_bytes_per_second": 1622462.229935638
}
],
"preceding_jfr_gc_pause_total_ms": 166.770211,
"preceding_jfr_gc_pause_longest_ms": 46.786101
}
],
"provenance": {
"source_commit": "0a0cd667d5cfdee7c59f5fe2c7a2eb15bd19e66e",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37175709062",
"runtime_mod_matches_linux_ci": true,
"initial_player_snapshot_sha256": "b4d11dbd6443625415a1e32aa242d0e2d09cd77ddb1becfde5d35cb6ab8d278a",
"source_level_snapshot_sha256": "86a3c75ea993e50c4428da4dbadc5856688a9367f035c41b8bb49863a9aeb644",
"first_saved_player_position": [
-56.5,
69.0,
55.5
],
"first_saved_player_rotation": [
141.5,
16.950002670288086
],
"first_saved_cameras_matched": true
},
"notes": [
"Fixed-order candidate then control single pair from separate copies of the same private world. Both stationary captures start approximately 307 seconds after the demo popup is dismissed; first saved cameras match.",
"Both reports have zero menu/pause/focus exclusions, no dropped samples and matching captured settings apart from the isolated quad hook. CSV counts and actual offline viewer timelines pass.",
"The preceding 60-second JFR recordings begin approximately 121 seconds after dismissal. Allocation counters have their own approximately 64-second spans; GC pause data is from those recordings, not from the later frame captures.",
"Render-loader allocation counter rates are higher in this candidate observation. Task-completion/geometry volumes and cache/JIT effects are not controlled quantitatively. No useful live allocation improvement is established.",
"Frame count and sampled peak RSS differences in this single software-rendered pair do not establish a meaningful game speed or retained-memory gain. RSS is not complete GPU/unified RAM. Not an Apple Silicon benchmark.",
"Candidate saved, reloaded, saved again and exited with launcher code zero. Control saved, closed all terrain databases and exited with launcher code zero.",
"No private worlds, full game logs or JFR recordings are included in these selected observations."
]
}
@@ -1,75 +0,0 @@
{
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "2196637c5b2180a33fa5b926ab51069ab480618c1186b8a02872c7e758be0a70",
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"geometry_digest": "8251175aa3e3cac30bb1366f8b40d0576c17978076ea7d244ff4d7cc361da7ee",
"thread_geometry_digest": "096a85be06031d248f12e536e19e5c0496bb00c80f3387f670a0fae29438a732",
"thread_workers": 4,
"geometry_quads": 108358,
"input_faces": 55296,
"measured_faces": 3072000,
"checksum": 60000,
"cpu_ns": 198847198,
"allocated_bytes": 144576000,
"observations": [
{
"cpu_ns": 82119774,
"allocated_bytes": 48192000
},
{
"cpu_ns": 60671068,
"allocated_bytes": 48192000
},
{
"cpu_ns": 56056356,
"allocated_bytes": 48192000
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"geometry_digest": "8251175aa3e3cac30bb1366f8b40d0576c17978076ea7d244ff4d7cc361da7ee",
"thread_geometry_digest": "096a85be06031d248f12e536e19e5c0496bb00c80f3387f670a0fae29438a732",
"thread_workers": 4,
"geometry_quads": 108358,
"input_faces": 55296,
"measured_faces": 3072000,
"checksum": 60000,
"cpu_ns": 178894413,
"allocated_bytes": 2016000,
"observations": [
{
"cpu_ns": 60070905,
"allocated_bytes": 672000
},
{
"cpu_ns": 60020252,
"allocated_bytes": 672000
},
{
"cpu_ns": 58803256,
"allocated_bytes": 672000
}
]
}
],
"notes": [
"Actual publisher quad builder inside Fabric with generated faces and lighting/material values.",
"Opaque/translucent geometry, pooled error flags and every retained quad field match before and after upstream merging.",
"Fresh allocations reuse at most one discarded successful-premerge quad; existing pool selection stays upstream.",
"Three sequential warmed caller-loop observations are not independent forks; compilation can vary.",
"Allocation reduction is not retained RAM, game FPS or a Mac GPU benchmark."
],
"provenance": {
"source_commit": "0a0cd667d5cfdee7c59f5fe2c7a2eb15bd19e66e",
"fixture_protocol": "55,296 generated faces plus four concurrent builders, geometry/list boundaries checked before and after upstream merge; warm 2,000 batches, then 500 warm batches and 2,000 measured batches per sequential observation, 512 faces/batch"
}
}
@@ -1,87 +0,0 @@
{
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "2196637c5b2180a33fa5b926ab51069ab480618c1186b8a02872c7e758be0a70",
"results": [
{
"enabled": false,
"compact_headers": false,
"builder_shallow_bytes": 48,
"quad_shallow_bytes": 56,
"pending_scratch_shallow_bytes": 0,
"geometry_quads": 1,
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"object_alignment_bytes": 8,
"compressed_oops": true,
"compressed_class_pointers": true
},
{
"enabled": true,
"compact_headers": false,
"builder_shallow_bytes": 48,
"quad_shallow_bytes": 56,
"pending_scratch_shallow_bytes": 56,
"geometry_quads": 1,
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"object_alignment_bytes": 8,
"compressed_oops": true,
"compressed_class_pointers": true
},
{
"enabled": false,
"compact_headers": true,
"builder_shallow_bytes": 40,
"quad_shallow_bytes": 48,
"pending_scratch_shallow_bytes": 0,
"geometry_quads": 1,
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"object_alignment_bytes": 8,
"compressed_oops": true,
"compressed_class_pointers": true
},
{
"enabled": true,
"compact_headers": true,
"builder_shallow_bytes": 48,
"quad_shallow_bytes": 48,
"pending_scratch_shallow_bytes": 48,
"geometry_quads": 1,
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"object_alignment_bytes": 8,
"compressed_oops": true,
"compressed_class_pointers": true
}
],
"differences": [
{
"compact_headers": false,
"additional_builder_shallow_bytes": 0,
"additional_builder_and_scratch_bytes": 56
},
{
"compact_headers": true,
"additional_builder_shallow_bytes": 8,
"additional_builder_and_scratch_bytes": 56
}
],
"notes": [
"Instrumentation.getObjectSize measures shallow object sizes inside real applied Fabric clients.",
"Four adjacent north-facing quads premerge to one retained geometry quad in each combination.",
"Builder plus pending scratch difference excludes referenced lists, existing pools and every other game object.",
"Object alignment/header/compressed-reference settings can differ on other JVMs or architectures.",
"Not deep heap, GC residency, whole-game RSS/unified RAM, FPS or Apple Silicon performance.",
"The agent and fixture are private test binaries excluded from playable packs."
],
"provenance": {
"source_commit": "1243e148d455cd83f18b66f70bcfe2b8a4b746c9",
"four_processes_exited_successfully": true,
"agent_path_with_spaces_verified_separately": true
}
}
@@ -1,69 +0,0 @@
{
"schema": 1,
"measurement": "Instrumentation.getObjectSize inside four private applied Fabric clients",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"java_vendor": "Ubuntu",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"original_mod_sha256": "2196637c5b2180a33fa5b926ab51069ab480618c1186b8a02872c7e758be0a70",
"production_source_commit": "24c65f512dece83b153b206e33cd4c4294b42de2",
"results": [
{
"enabled": false,
"compact_headers": false,
"builder_shallow_bytes": 48,
"quad_shallow_bytes": 56,
"pending_scratch_shallow_bytes": 0,
"geometry_quads": 1
},
{
"enabled": true,
"compact_headers": false,
"builder_shallow_bytes": 48,
"quad_shallow_bytes": 56,
"pending_scratch_shallow_bytes": 56,
"geometry_quads": 1
},
{
"enabled": false,
"compact_headers": true,
"builder_shallow_bytes": 40,
"quad_shallow_bytes": 48,
"pending_scratch_shallow_bytes": 0,
"geometry_quads": 1
},
{
"enabled": true,
"compact_headers": true,
"builder_shallow_bytes": 48,
"quad_shallow_bytes": 48,
"pending_scratch_shallow_bytes": 48,
"geometry_quads": 1
}
],
"differences": [
{
"compact_headers": false,
"additional_builder_shallow_bytes": 0,
"additional_builder_and_scratch_bytes": 56
},
{
"compact_headers": true,
"additional_builder_shallow_bytes": 8,
"additional_builder_and_scratch_bytes": 56
}
],
"provenance": {
"protocol": "Initial private size agent and corrected system-loader reflection probe; metadata was later expanded in the reusable source.",
"agent_source_sha256": "4783850bf80e9eb0379570bb7794a610406b48bddd7fe36ff499222d01e789b1",
"fixture_source_sha256": "842514f97116a1e9cf5eb9a4b951657c90f7639effdfd526357831e2424282bf"
},
"notes": [
"Shallow object sizes only, not a heap walk or whole-game memory measurement.",
"Four north-facing adjacent quads produce one retained geometry quad in every process.",
"Header modes use separate upstream/patched JVMs.",
"Layouts can differ with JVM, architecture, compressed references and object alignment.",
"The hook remains optional; these sizes do not establish an FPS or RAM improvement.",
"No test agent binaries, game binaries, private worlds, full logs or JFR recordings are published."
]
}
@@ -1,54 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"resource_models": 2883,
"graph_fixtures": 440,
"rejected_roots": 1039,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaModelBakingOracle.java": "d05e04d25ed5e5aef260ce21cac627a79bdc5376326a5cb34ffb98462b79c79b",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCuboidModelOracle.java": "7526f20513c549483122ab0d5ad24b9e87f38dc2f6aae55addd701a91ac85e43",
"tools/test_model_baking_parity.py": "392ffec44918fb91740ca4a1316d684480d39f14bd34d46175f7f44946d15bd7",
"tools/test_cuboid_model_parity.py": "4a8b1cdcac335751c23413341ae939eea1c49c38d33d70d0708b8904ab8d0461",
"tools/test_model_resolution_parity.py": "d9595f2f1442f1f590b72d2a46600657e79ae103bec3d4c45db98242b964bde0",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-assets/Cargo.toml": "2f2cffacec0b4e22dd7cb032d594289bc51c94ae6cc4e985fee3e310f441d751",
"crates/horizon-assets/examples/blockstate_binding_fixture.rs": "e58fdb432f6bfc1e400729baa9b48d4f00955b3143b98b52506b47dd8b065cf8",
"crates/horizon-assets/examples/blockstate_model_fixture.rs": "8f063322e57abdf9361a5a3a3badce2a7e727ee6d5e3947071cb448dfb38e8fd",
"crates/horizon-assets/examples/cuboid_model_fixture.rs": "97609d90e3f6ce340f3590296db2dc778113bb2b33c7d1b54080a1d6f3023f40",
"crates/horizon-assets/examples/model_baking_fixture.rs": "a762a8b48f09b5ac5e9c48d4a578b18b700810807fe5d3fc50798365cce1c314",
"crates/horizon-assets/examples/model_choice_fixture.rs": "a4c8a46501d2b5ae7051f10f2307ade048e96c2d330af51cd2431bb44977a99a",
"crates/horizon-assets/examples/model_resolution_fixture.rs": "c071067140299e49345a6ebd94e15b3b6d853cb9ae11d8de46e3cbdfb8b01f0e",
"crates/horizon-assets/examples/sprite_animation_fixture.rs": "254314d52deda129ab461221d3d8b95323a60730d374e566c1cd599fba85f072",
"crates/horizon-assets/examples/support/mod.rs": "bcf5a6d8a54845982191e037911c24139237771d6afa4b01b1e83c011489c3f5",
"crates/horizon-assets/src/animation.rs": "ebbf7952146a0e66b41396174492f5702627170b03a57e6cd5a45c97a08c975e",
"crates/horizon-assets/src/bake/transform.rs": "a95e658fef85b21bcb2f9f7512f98f98d57022d62c1199885b7133beae35a09d",
"crates/horizon-assets/src/bake.rs": "f55dda6b6cee5ac6e65a8ee4837fdd2c6674437d59e59b4c45718f6324d4a4d5",
"crates/horizon-assets/src/blockstate/bind.rs": "6278962e55c9786bba8184bdf2939af9c6e3b9002b08c3022129964b49a60009",
"crates/horizon-assets/src/blockstate/choice.rs": "5a66c8b9833e2f19dd8b0773f3593d97ff5941d3c5b773896b98049efa1395ba",
"crates/horizon-assets/src/blockstate.rs": "a4299dfd7adaeb4173982ffaa8e9c9eda2925739ae579a714193c99da2e7ce56",
"crates/horizon-assets/src/json.rs": "99fe8af4fbf5d4eed408a92e829ac1a39597a0d92471a6bff73771fad9c830a8",
"crates/horizon-assets/src/lib.rs": "e39f21c59a2c3e1c53d977b29bd5e0638e5fc41d86ff0fcc1882a6d90fd961e4",
"crates/horizon-assets/src/model.rs": "57ddb3d65e88e7a8aa22c62bc298a2dae7f4e994326a873a31f06c0f36ed051b",
"crates/horizon-assets/src/resolve.rs": "3927ac926cdcbd7d334901cc32d0ecc1e498b1bec98f76a46bca6d4964c13541"
},
"fixtures_sha256": {
".local/rust-model-baking-parity/inputs.jsonl": "aba24d38f4fc1af060502f983923c2f279c016d0fd412d40f6d50093fac1d811"
},
"rust_output_sha256": "9216be3bbae9e59bb89b6ed780ccedc5608cd4583c8e7527e50b165a0d8d30da",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "9216be3bbae9e59bb89b6ed780ccedc5608cd4583c8e7527e50b165a0d8d30da",
"matched_output_lines": 7100
}
],
"scope": "Actual client FaceBakery geometry overload with a real unit-atlas sprite and default JOML math options. Identity blockstate transform, all bundled cuboid geometry and synthetic rotations, rescaling, default/explicit UVs, winding, degenerate and reversed bounds, inherited models and missing materials. Positions, UVs and element matrix coefficients compare by float bits. This does not cover blockstate transforms/UV lock, atlas packing, transparency classification, lighting, GPU rendering or gameplay."
}
@@ -1,44 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"commands": {
"position": 12375,
"legacy": 23,
"xoroshiro": 23,
"xoroshiro_state": 5,
"storage": 274
},
"inputs_sha256": "dbdebadd4b14ec57d198d22f15e196e0cc9a6b88bac6691db702348a769459c1",
"rust_output_sha256": "7801e3274307aab1852d96d996d7f29b1ca1567750d231c5f74c9e3263f84f87",
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCoreOracle.java": "649b8353fcc3c45a3baf8e2d78dc76cfedfd96de36030b0dddfb2305829cd844",
"tools/test_rust_parity.py": "d2d06842abb80d9c718a5bf0e71ab0c098ad4c519b8ef35711e30cf58af140d7",
"crates/horizon-core/src/bin/parity.rs": "7b455f2181862e1430e7387633c146877c2d317c2ea682c1e6fa64345dbc5885",
"crates/horizon-core/src/lib.rs": "deb2e339f78c9f5bd55a1c8a8428f3e37fae93a02268f9a2fc782dc3e27c2869",
"crates/horizon-core/src/position.rs": "8c2a54e912f8c31a774682b3377ca5f2138910350fbf605e760b24e2cbcacfba",
"crates/horizon-core/src/random.rs": "2f304dfb580a6bc1b5c51b048a2fa2a57f73c5f28f5eb2447f925bf138513389",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/Cargo.toml": "1928b71e389c24c506804f0d8e3104976da6feb27d9bfdbb3b55fb7af0c62664",
"Cargo.toml": "9ca59fba126895de9e58952eb5e9421bee0ffdfb5f6d2fcb03d7726e394e7c3f",
"Cargo.lock": "f2b104dbb3f64512b6c72e8d8732b7adda849212689e8c816f9a6abf564f4660"
},
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "7801e3274307aab1852d96d996d7f29b1ca1567750d231c5f74c9e3263f84f87",
"matched_output_lines": 1017920
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "7801e3274307aab1852d96d996d7f29b1ca1567750d231c5f74c9e3263f84f87",
"matched_output_lines": 1017920
}
],
"scope": "Selected integer position, seeded RNG and packed-storage operations only. No gameplay, rendering or performance claim."
}
@@ -1,40 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"resource_models": 2883,
"synthetic_models": 2337,
"rejected_models": 1034,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCuboidModelOracle.java": "7526f20513c549483122ab0d5ad24b9e87f38dc2f6aae55addd701a91ac85e43",
"tools/test_cuboid_model_parity.py": "3b7c018570b0f609aae43cef60ff3139c543d5d629be804a5aa257e3ab2dd67c",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "7b4ab0ffa35af7ea8b6e38525f18ff6c3e94768198915f5ffe560d84263423f8",
"crates/horizon-assets/Cargo.toml": "fadb78cf819e026500606c45d27138ed67fcbbc967ae8cee6c1e7c82c9046b36",
"crates/horizon-assets/examples/cuboid_model_fixture.rs": "97609d90e3f6ce340f3590296db2dc778113bb2b33c7d1b54080a1d6f3023f40",
"crates/horizon-assets/examples/model_resolution_fixture.rs": "c071067140299e49345a6ebd94e15b3b6d853cb9ae11d8de46e3cbdfb8b01f0e",
"crates/horizon-assets/examples/support/mod.rs": "bcf5a6d8a54845982191e037911c24139237771d6afa4b01b1e83c011489c3f5",
"crates/horizon-assets/src/json.rs": "e7b89bf4852f561a0e5bf1a984857c61e755961dfd86fcc326b6d55558615f39",
"crates/horizon-assets/src/lib.rs": "0d31dd0fa84d7b4467a78a1a2b8a8e179533ef5e64a7cbae88e5358e59160a40",
"crates/horizon-assets/src/model.rs": "57ddb3d65e88e7a8aa22c62bc298a2dae7f4e994326a873a31f06c0f36ed051b",
"crates/horizon-assets/src/resolve.rs": "3927ac926cdcbd7d334901cc32d0ecc1e498b1bec98f76a46bca6d4964c13541"
},
"fixtures_sha256": {
".local/rust-cuboid-model-parity/inputs.jsonl": "9c1822180e1d6869e65eea81a38cbcf3786b9286d4c839e31ba686501694d171"
},
"rust_output_sha256": "80c4b305084658ab968ed466fb1609bfa78d60738d09790c6243b4de27dfb8fc",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "80c4b305084658ab968ed466fb1609bfa78d60738d09790c6243b4de27dfb8fc",
"matched_output_lines": 5220
}
],
"scope": "Actual pinned CuboidModel.fromStream parser compared over every bundled block model and synthetic JSON/numeric/syntax cases. Decoded geometry, texture materials/references, nullable children, inheritance markers, face quadrants, light emission and display transforms; floats compare by IEEE-754 bits. Rejections normalize exception text. This client-only API is absent from the server. Does not yet validate parent resolution, rotation matrices, quad baking, blockstate dispatch, rendered pixels or gameplay."
}
@@ -1,373 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"exhaustive": false,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFloatLogOracle.java": "1794510183faa07892761e93094301b69665d4b6a5300ef7117b5482832165f2",
"tools/test_float_log_parity.py": "1ba733163133ea6232a9021fcee5b38255887d62ebab8d1b42e4ccad259b21f3",
"tools/test_rust_parity.py": "7efa699a38c5820424f5fc8992ee601dbfe26d6482da9d2dab2c17c41fe8f12a",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"crates/horizon-core/src/bin/density_parity.rs": "ca79feb1ff690557a54dcb3a504967453dd0190ac65d7322512c778048127c5e",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/density/arithmetic.rs": "e42a19893a8d75f8f62b564bd9e527131d87fb469c808422fb8d3b14eb9edac0",
"crates/horizon-core/src/density/cache.rs": "3ccc1268dca96259890279e9f91cb7a099c74b12e6ca2973880d4fa246f7a619",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ede1da60dec40f6df846e44a663bff03c21631c21f2b6e25a58c358115f122a1",
"crates/horizon-core/src/density/graph/mod.rs": "47f1716a8b5fffc1012b9e4654e223b0ff818f00f6a059818ab3dfe8c37e3056",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "3034eccba649851d7a95e276a48472efd70cdf747b54526b565fb0feb88ce43a",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "3e56cc0f6b51c6faa4bd8d9fc259bf01a0c3bf647f36be8be7640971cfe3b334",
"crates/horizon-core/src/density/power.rs": "b18a5b0d524de52a3d1e6028adcddd183424be2913f24d3f098ff56c5e1c6942",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "de22acd7430df3f69ef3632d427c57dffe57f3bdb78950bc75eac7e179ccf9df",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "3968e2a337a6a23226c485057c79359e66df16683f00fb4ebc9fabb03910a015",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random.rs": "92135a94c79111cc810b4b071dbd76043ee47c2585fd431e7486ea381f19e5db",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "84852599dde78687d782f115a5b4b3ef6856c1f9cc92917255167e89c72ab01e",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"Cargo.toml": "dc370d5fdde37238c3e4820046f11c3201020406a4edfa1308257c13edbdcda4",
"Cargo.lock": "faae2edce8b573fd32fcb4bd1f898be7d700a5b38479439f5bec96df764688fd"
},
"comparisons": [
{
"start_bits": 0,
"count": 65536,
"rust_output_sha256": "1e684e3e6b93407fb3f37762a4de01f8706c047cf5294cf9d2a1ac173fc02075",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "1e684e3e6b93407fb3f37762a4de01f8706c047cf5294cf9d2a1ac173fc02075",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "1e684e3e6b93407fb3f37762a4de01f8706c047cf5294cf9d2a1ac173fc02075",
"matched_float_values": 65536
}
]
},
{
"start_bits": 8388608,
"count": 65536,
"rust_output_sha256": "4200cba9cf0053911e1d672fabbee94f5267d5b7aa109fbe57ddc5a4f7b70393",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "4200cba9cf0053911e1d672fabbee94f5267d5b7aa109fbe57ddc5a4f7b70393",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "4200cba9cf0053911e1d672fabbee94f5267d5b7aa109fbe57ddc5a4f7b70393",
"matched_float_values": 65536
}
]
},
{
"start_bits": 1056899072,
"count": 65536,
"rust_output_sha256": "cae10428767d3e776f5183caba1780897d2e1831913c05ae6dd8d843a6e25a76",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "cae10428767d3e776f5183caba1780897d2e1831913c05ae6dd8d843a6e25a76",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "cae10428767d3e776f5183caba1780897d2e1831913c05ae6dd8d843a6e25a76",
"matched_float_values": 65536
}
]
},
{
"start_bits": 1065287680,
"count": 65536,
"rust_output_sha256": "59024062288c0bc65906a38484eff0fb73aaba11cb8110aaebc6dde8891ed10c",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "59024062288c0bc65906a38484eff0fb73aaba11cb8110aaebc6dde8891ed10c",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "59024062288c0bc65906a38484eff0fb73aaba11cb8110aaebc6dde8891ed10c",
"matched_float_values": 65536
}
]
},
{
"start_bits": 1065353216,
"count": 65536,
"rust_output_sha256": "01849695d0e9a30ccd132270cb79ecaaf1065411d66b323a36f1b87f5d0e4596",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "01849695d0e9a30ccd132270cb79ecaaf1065411d66b323a36f1b87f5d0e4596",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "01849695d0e9a30ccd132270cb79ecaaf1065411d66b323a36f1b87f5d0e4596",
"matched_float_values": 65536
}
]
},
{
"start_bits": 1073741824,
"count": 65536,
"rust_output_sha256": "0df001f091df446399cccd24b0fa1e4114894c263d5cdc707b8c4a2ded269936",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "0df001f091df446399cccd24b0fa1e4114894c263d5cdc707b8c4a2ded269936",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "0df001f091df446399cccd24b0fa1e4114894c263d5cdc707b8c4a2ded269936",
"matched_float_values": 65536
}
]
},
{
"start_bits": 2139029504,
"count": 65536,
"rust_output_sha256": "c39faee80d047d450472ae5eb25f2811e4010b5aad1ccad80ff4d8f7638bd3d5",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "c39faee80d047d450472ae5eb25f2811e4010b5aad1ccad80ff4d8f7638bd3d5",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "c39faee80d047d450472ae5eb25f2811e4010b5aad1ccad80ff4d8f7638bd3d5",
"matched_float_values": 65536
}
]
},
{
"start_bits": 2139095040,
"count": 65536,
"rust_output_sha256": "1c60d380d4dc55a05bed3452e32f4d5c813c9beb4459ba890338c27f0b047345",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "1c60d380d4dc55a05bed3452e32f4d5c813c9beb4459ba890338c27f0b047345",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "1c60d380d4dc55a05bed3452e32f4d5c813c9beb4459ba890338c27f0b047345",
"matched_float_values": 65536
}
]
},
{
"start_bits": 2147418112,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
},
{
"start_bits": 2147483648,
"count": 65536,
"rust_output_sha256": "b365699b17956be9409c58c88b48da5f7edf7e4783fcca72efa00b0dae84455f",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "b365699b17956be9409c58c88b48da5f7edf7e4783fcca72efa00b0dae84455f",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "b365699b17956be9409c58c88b48da5f7edf7e4783fcca72efa00b0dae84455f",
"matched_float_values": 65536
}
]
},
{
"start_bits": 2155872256,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
},
{
"start_bits": 3212771328,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
},
{
"start_bits": 3212836864,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
},
{
"start_bits": 4286513152,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
},
{
"start_bits": 4286578688,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
},
{
"start_bits": 4294901760,
"count": 65536,
"rust_output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "f3b37b44be6c4c25b1d85b2bce7844c67cc9f3e5a3270d4a53101d99049b966e",
"matched_float_values": 65536
}
]
}
],
"scope": "Compiled scalar UnaryFunction.LogSampler compared by float result bits across the recorded input bit ranges, including signed zeros, subnormals, finite values, infinities and NaNs. NaN results are canonicalized as Float.floatToIntBits. Exhaustive mode checks all 2^32 float input bit patterns against both checksum-pinned JARs on this machine's JDK. Bulk composition, range propagation, compiler rewriting and other operations belong to the separate density suite. This does not establish double-precision Math.log parity, other-platform math parity, complete terrain, gameplay or performance."
}
@@ -1,202 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 8338,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "d2f5b022be1ee2111c38acf6710c21b59da09506e246fb22b8c7c8eeb253a7d9",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "a40c9d7a4e0a734c124dc856e31359fd4d8de3d1bfc79c86787afa8e8e05e480",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "e321bed47d34ef1fdcdd99dad07cc537d34ed3cfbc07f10f10ec8b6848daf208",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/collision_context_fixture.rs": "22701112922a2f806a1d6906f0e56bfbff309093bbbc7c140bf077d9686e854f"
},
"fixtures_sha256": {
".local/rust-collision-context-parity/inputs.txt": "60b49e91a7a4999cfb8eb6ac3fbc6ec0a931d68cd53f9737959a2bd2b42be7a5"
},
"rust_output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"matched_output_lines": 225126
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"matched_output_lines": 225126
}
],
"scope": "Actual CollisionContext factories and EntityCollisionContext/Empty/PositionCollisionContext queries on controlled player and marker snapshots. Checks entity identity, captured descending and placement flags, fluid collision flags, empty-stack AIR identity, height thresholds including f32 epsilon, null factories, callback arguments/order/failures and all five fluid type pairs. Entity lifecycle, inventory mutations after capture, experimental minecart contexts, contextual block shape dispatch and live movement integration remain pending."
}
@@ -1,204 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 56448,
"block_states": 32,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "d2f5b022be1ee2111c38acf6710c21b59da09506e246fb22b8c7c8eeb253a7d9",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2",
"tools/test_scaffolding_collision_parity.py": "bab75e2cad68a3193035a87497eaa372466c405293cc547e39dbd7bd4450d69d",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "a40c9d7a4e0a734c124dc856e31359fd4d8de3d1bfc79c86787afa8e8e05e480",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "e321bed47d34ef1fdcdd99dad07cc537d34ed3cfbc07f10f10ec8b6848daf208",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/collision_context_fixture.rs": "22701112922a2f806a1d6906f0e56bfbff309093bbbc7c140bf077d9686e854f"
},
"fixtures_sha256": {
".local/rust-scaffolding-collision-parity/inputs.txt": "5945054e86700237a7b6de6b362a37a98bdc8afaa67004e8aaa92da1421b552c"
},
"rust_output_sha256": "33a33cd612c999ab21f1acbbdee522f2ec2b3f877d62f922c665715e3012e207",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "33a33cd612c999ab21f1acbbdee522f2ec2b3f877d62f922c665715e3012e207",
"matched_output_lines": 524300
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "33a33cd612c999ab21f1acbbdee522f2ec2b3f877d62f922c665715e3012e207",
"matched_output_lines": 524300
}
],
"scope": "Actual CollisionContext.getCollisionShape dispatch and native scaffolding behavior for all 32 scaffolding states, nine context variants, descending flags, integer Y extremes, nonfinite positions and adjacent double values around the top/bottom float-epsilon thresholds. Full shape coordinates, extrema, box ordering and cube metadata match. A rejecting world proxy verifies selection performs no world reads. Scaffolding placement/update/falling behavior and live movement remain pending."
}
@@ -1,141 +0,0 @@
{
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"arch": "x86_64",
"camera_pitch": -0.3839724354387525,
"camera_position": [
25.0,
18.0,
25.0
],
"camera_yaw": -2.356194490192345,
"elapsed_seconds": 0.541997659,
"error": null,
"merged_quads": 166,
"os": "linux",
"presented_frames": 30,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native opaque-cube renderer and free inspection camera; no gameplay simulation",
"window_size": [
1280,
720
],
"executable_sha256": "4907a5678c323ab250934f3dfa32ba10e1554635f81d226ed2a88e7625737c5f",
"resource_manifest_sha256": "eda44ebee6904eab880c15458dbd1212dc2799d320a4419fc810e2ceb0e5d9d6",
"sources": {
"crates/horizon-client/src/assets.rs": "f35107193fc6d08be41891181da1803abf15bd373b62dd63758213809e2c5cbf",
"crates/horizon-client/src/camera.rs": "f9821c8a51a004dd4ad9c0952e746eb07926f6040cf8660bc26da5a0728ae572",
"crates/horizon-client/src/main.rs": "0cc250b695ba0d1e49107f581695edea1d24cdc2fb8ffa3a46368ef2c40430a7",
"crates/horizon-client/src/mesh.rs": "e2fa00435ec8239ba8a3c6539022bb50a10ff9c3850c6faab72f86aabea896ef",
"crates/horizon-client/src/render.rs": "4d58443465ea25769d73701d138db6a99c4f939a288e89e1f2b1ee3d017a2737",
"crates/horizon-client/src/world.rs": "901aa59c23ea084e926eec014589f4d511c41691a8dc1520534e039c28cfc76c",
"crates/horizon-client/src/world.wgsl": "dd7d579d0afb8a61da849171e444fa05a3e9d15bbfe6d019ff6653e8e0774c66",
"Cargo.toml": "4f803d21656a1420555bee6369617ddc825219a2cf05f842a209b3f8eaa583ec",
"Cargo.lock": "b1674833e1d5e66032589eea75643bf1c1eb2f2d6503e79ff7da8efa1b6d21dc",
"crates/horizon-client/Cargo.toml": "3047995858c9cd103ce358dfd991cb81e7d0688a149f4874cc73c36b859bbff7",
"tools/prepare_native_client.py": "b16f62acfc6242552af14ff405e2169ebba3adab12b991fc011e78edb4ffa982",
"tools/test_native_client.py": "adb9aa87cc28b0980d811ce47c1b09878d2d72cef2e083b278ec41183d231f1b"
},
"validation": {
"rust_workspace_tests": "passed",
"clippy_all_targets": "passed",
"python_tooling_tests": 149,
"mesh_tests": 2,
"manual_visual_checks": [
"textured scene with 81 chunks and 382 merged quads",
"window resize from 1600x1000 to 1280x720"
],
"input_checks": [
"physical W movement",
"physical Right rotation",
"captured relative mouse delta (150,-50) changed yaw by -0.3 and pitch by +0.1 radians",
"Escape and Ctrl+Q"
]
},
"environment": {
"os": "Ubuntu 26.04.1 LTS",
"kernel": "7.0.0-31-generic",
"cpu": "Intel Core i7-7500U",
"display": "headless Sway Wayland",
"renderer": "Vulkan llvmpipe software rasterizer"
},
"limits": [
"Controlled development scene only; no gameplay simulation or vanilla pixel-parity claim",
"No hardware FPS or render-distance improvement demonstrated",
"macOS and Windows runtime checks and final playable packages remain pending",
"Private game resources and screenshots excluded from this report"
],
"mouse_check": {
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"arch": "x86_64",
"camera_pitch": -0.2839724354387525,
"camera_position": [
25.0,
18.0,
25.0
],
"camera_yaw": -2.6561944901923447,
"elapsed_seconds": 8.654220098,
"error": null,
"merged_quads": 166,
"os": "linux",
"presented_frames": 532,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native opaque-cube renderer and free inspection camera; no gameplay simulation",
"window_size": [
1280,
720
]
},
"physical_keyboard_check": {
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"arch": "x86_64",
"camera_pitch": -0.3839724354387525,
"camera_position": [
18.943610750255,
18.0,
18.943610750255
],
"camera_yaw": -2.6478875051923443,
"elapsed_seconds": 17.488515374,
"error": null,
"merged_quads": 166,
"os": "linux",
"presented_frames": 1080,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native opaque-cube renderer and free inspection camera; no gameplay simulation",
"window_size": [
1280,
720
],
"source_note": "Same camera/input behavior; before subsequent diagnostic formatting and equivalent let-chain cleanup"
},
"private_capture_sha256": {
"first-launch.png": "7e53fa26d3d55f943db41828e1c8dd5b65279f9a130854fff288c75a394ee5aa",
"moved-resized.png": "be5a0473ab505740d18ba8eecf1512c15ba93d53d046f49b8dfa96357b25bf22",
"mouse-look.png": "7103678309f06938de40ac294f2f9ca1f56b253bc463e792b121ba607cd7b0a3"
}
}
@@ -1,800 +0,0 @@
{
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"animated_sprites": 1,
"animation_uploads": 1,
"arch": "x86_64",
"camera_pitch": -0.3839724354387525,
"camera_position": [
25.0,
18.0,
25.0
],
"camera_yaw": -2.356194490192345,
"collision_camera": false,
"culled_model_faces": 59636,
"elapsed_seconds": 0.547544857,
"error": null,
"fall_damage_requests": 0,
"last_requested_fall_damage": null,
"merged_quads": 3169,
"mesh_revision": 0,
"model_blocks": 10919,
"model_gallery": [
{
"block": "minecraft:oak_stairs",
"models": [
{
"model": "minecraft:block/oak_stairs_inner",
"rotations": [
2,
3,
0
],
"uv_lock": true
}
],
"position": [
-7,
4,
14
],
"properties": {
"facing": "north",
"half": "top",
"shape": "inner_left",
"waterlogged": "false"
},
"state_id": 5466
},
{
"block": "minecraft:stone_slab",
"models": [
{
"model": "minecraft:block/stone_slab_top",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
14
],
"properties": {
"type": "top",
"waterlogged": "false"
},
"state_id": 15250
},
{
"block": "minecraft:anvil",
"models": [
{
"model": "minecraft:block/anvil",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
14
],
"properties": {
"facing": "east"
},
"state_id": 12965
},
{
"block": "minecraft:torch",
"models": [
{
"model": "minecraft:block/torch",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
14
],
"properties": {},
"state_id": 4926
},
{
"block": "minecraft:lantern",
"models": [
{
"model": "minecraft:block/lantern",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
18
],
"properties": {
"hanging": "false",
"waterlogged": "false"
},
"state_id": 24197
},
{
"block": "minecraft:oak_fence",
"models": [
{
"model": "minecraft:block/oak_fence_post",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
0,
0
],
"uv_lock": true
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
-3,
4,
18
],
"properties": {
"east": "true",
"north": "true",
"south": "false",
"waterlogged": "false",
"west": "false"
},
"state_id": 8642
},
{
"block": "minecraft:oak_fence_gate",
"models": [
{
"model": "minecraft:block/oak_fence_gate_open",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
1,
4,
18
],
"properties": {
"facing": "west",
"in_wall": "false",
"open": "true",
"powered": "false"
},
"state_id": 10401
},
{
"block": "minecraft:iron_bars",
"models": [
{
"model": "minecraft:block/iron_bars_post_ends",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side_alt",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
18
],
"properties": {
"east": "false",
"north": "true",
"south": "true",
"waterlogged": "false",
"west": "false"
},
"state_id": 9711
},
{
"block": "minecraft:cobweb",
"models": [
{
"model": "minecraft:block/cobweb",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
22
],
"properties": {},
"state_id": 2362
},
{
"block": "minecraft:grindstone",
"models": [
{
"model": "minecraft:block/grindstone",
"rotations": [
1,
3,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
22
],
"properties": {
"face": "wall",
"facing": "west"
},
"state_id": 24135
},
{
"block": "minecraft:ladder",
"models": [
{
"model": "minecraft:block/ladder",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
22
],
"properties": {
"facing": "west",
"waterlogged": "false"
},
"state_id": 7312
},
{
"block": "minecraft:amethyst_cluster",
"models": [
{
"model": "minecraft:block/amethyst_cluster",
"rotations": [
1,
1,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
22
],
"properties": {
"facing": "east",
"waterlogged": "false"
},
"state_id": 26764
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone_mirrored",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
26
],
"properties": {},
"state_id": 1
}
],
"model_quads": 179,
"movement_ticks": 0,
"os": "linux",
"player_absorption": null,
"player_dead": null,
"player_exhaustion": null,
"player_fall_distance": null,
"player_food": null,
"player_food_timer": null,
"player_health": null,
"player_hurt_cooldown": null,
"player_on_ground": null,
"player_position": null,
"player_saturation": null,
"player_velocity": null,
"presented_frames": 30,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native resident-scene renderer with inspection camera and optional fixed-rate dry walking test; full gameplay remains unfinished",
"sprite_layers": 18,
"visible_model_faces": 5991,
"walking": false,
"window_size": [
1280,
720
],
"world_revision": 0,
"native_scene_culling": {
"blocks": 10919,
"culled_faces": 59636,
"visible_faces": 5991
},
"native_selection": {
"matched_placements": 16,
"selected_parts": 20,
"client_jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "a2ff1c890d6f3a5292c3a9402f02ca5404a993dc117853b25cbe64ac92b76d30",
"scope": "Actual native registry states, blockstate dispatch, tagged root baking and legacy collection using state.getSeed(position). All 16 featured placements match model names/transforms. An independently constructed native scene also matches total occupied blocks and visible/culled model faces using native parent resolution, rotated culling directions and Block.shouldRenderFace. No shader/pixel parity claim."
},
"resource_files": {
"files": 5590,
"sha256": "62f859d4d21b82158ab73e26cfa4973d58ab5926ab63d71c70c7a4d173502b7b"
},
"executable_sha256": "62fc8ff8bc750d2afeede7aaf830484de869655d7334c2a6405c9194e9a79cf9",
"resource_manifest_sha256": "92a51de578be0e7c37d21e94caa3f22503f7d88b73827a5fce109b1b889e5d18",
"sources": {
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "6884c7209f007ab9ee742b9c3c73828cfa1c6753d35b5fe25a87cab5955b33f8",
"tools/test_native_client.py": "6c615fed67fd7bcf09b3184216e08a82012049880a0d4da7c89f86553090cbda",
"crates/horizon-client/Cargo.toml": "d56524457d761c2613c0699b20e21ad6977d93e009d59ef150bbd9fc20d7a025",
"crates/horizon-assets/Cargo.toml": "2f2cffacec0b4e22dd7cb032d594289bc51c94ae6cc4e985fee3e310f441d751",
"crates/horizon-client/src/assets.rs": "e595afa610e0425d0b3ad694218794bf9e680e46ae80f3925c278ef1a823c914",
"crates/horizon-client/src/camera.rs": "d386a56ca8fb3b37ba2b2ed9d09342f61b409a575bb21590e934120b4ccebfa6",
"crates/horizon-client/src/clock.rs": "4851ada3e8e65d935eda8c0b57d3b51233b34f74aab4f040fd53db0e0d40b8df",
"crates/horizon-client/src/collisions.rs": "112286b07c4cd11b36da8b6799e0e069e69dfddf9a8a3f9ce36dcb282c791d67",
"crates/horizon-client/src/health.rs": "b5e2d3cde4bd58d906e6f6d47cd756ed23aa6706c71b10c3aedde30c11806403",
"crates/horizon-client/src/hunger.rs": "01d8a35f570f2a0991ac17a078f2066a5a83037a728158585765723d208b4611",
"crates/horizon-client/src/input.rs": "55b259ca6425c502270e7abc4d3ae1b3838633e2bd77d3817c6e00d9143a2beb",
"crates/horizon-client/src/landing.rs": "b9d0ecc5ec60a09d75ab9fe778e0a2e5bbb36fd8364a7ce996405f3dc9cb3b9f",
"crates/horizon-client/src/lib.rs": "bc1d0a7e42c11a9090abfebc4ed1f595415dd8b72a6a04b63c765b0deba29f6f",
"crates/horizon-client/src/main.rs": "aeb6b5220f8b89a1c9e85bf23fa2bbbafbc876108e59a222d383ad6e6fa238a6",
"crates/horizon-client/src/mesh.rs": "4ac8d85b30f599b37a98b92adcc016b16434816b93c401bd39b8215f591f9330",
"crates/horizon-client/src/models/catalog.rs": "620103719167fc9ab76e730d68eeacb50014e95b7ad209ae7adf2cbbe69f70f7",
"crates/horizon-client/src/models/cube.rs": "1067229f9dd9b276950bf7ec0c5f67061ce3d40a21932dca8034b9748e7439a4",
"crates/horizon-client/src/models.rs": "98dd3b969947c2b297862a934e6235067ddc1fc8cda5adcc6276d19014d4b048",
"crates/horizon-client/src/motion.rs": "673cc4bf6c4bc5523c104981e7c1cd640081a1b6ddca1e0ebe02181f04830347",
"crates/horizon-client/src/render.rs": "75cb40c257cf61e51009d292a06cd96532f59320b12ed7c3a509bbdbe1accdd4",
"crates/horizon-client/src/sprites.rs": "292f844a31f6e8884008df9630e2b8862db1acfbc4640cc07d526e25f21f0bc5",
"crates/horizon-client/src/world.rs": "0333ecf3e18ccc63117295feb2cf77661462ba13feb293eeec667c12811423b5",
"crates/horizon-client/src/world.wgsl": "972a58ccb34e9965515adbb30c47a93fceca5b742390db6d9f69cba1ec31f559",
"crates/horizon-assets/src/animation.rs": "ebbf7952146a0e66b41396174492f5702627170b03a57e6cd5a45c97a08c975e",
"crates/horizon-assets/src/bake/transform.rs": "a95e658fef85b21bcb2f9f7512f98f98d57022d62c1199885b7133beae35a09d",
"crates/horizon-assets/src/bake.rs": "f55dda6b6cee5ac6e65a8ee4837fdd2c6674437d59e59b4c45718f6324d4a4d5",
"crates/horizon-assets/src/blockstate/bind.rs": "6278962e55c9786bba8184bdf2939af9c6e3b9002b08c3022129964b49a60009",
"crates/horizon-assets/src/blockstate/choice.rs": "5a66c8b9833e2f19dd8b0773f3593d97ff5941d3c5b773896b98049efa1395ba",
"crates/horizon-assets/src/blockstate.rs": "a4299dfd7adaeb4173982ffaa8e9c9eda2925739ae579a714193c99da2e7ce56",
"crates/horizon-assets/src/json.rs": "99fe8af4fbf5d4eed408a92e829ac1a39597a0d92471a6bff73771fad9c830a8",
"crates/horizon-assets/src/lib.rs": "e39f21c59a2c3e1c53d977b29bd5e0638e5fc41d86ff0fcc1882a6d90fd961e4",
"crates/horizon-assets/src/model.rs": "57ddb3d65e88e7a8aa22c62bc298a2dae7f4e994326a873a31f06c0f36ed051b",
"crates/horizon-assets/src/resolve.rs": "3927ac926cdcbd7d334901cc32d0ecc1e498b1bec98f76a46bca6d4964c13541",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaGallerySelectionOracle.java": "dc5433f1ce1de629b30cb70f031a43a691fc1df1fb218ce23de89769c164d562",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCuboidModelOracle.java": "7526f20513c549483122ab0d5ad24b9e87f38dc2f6aae55addd701a91ac85e43",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
"tools/test_model_baking_parity.py": "392ffec44918fb91740ca4a1316d684480d39f14bd34d46175f7f44946d15bd7",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"tools/prepare_native_client.py": "159c12846058954a35ce86d415dc12fc89a6f11d46d21d1616ee686b7af4eee4",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/border.rs": "1386f8080521231d05ba3e84d94a3e1d5218d35ccb3d5e9fe2bbb05a8739e573",
"crates/horizon-core/src/geometry/mod.rs": "c650386f9860e44a96c55f18c8f1428ca715fcb0bc5c2434db5b1caa43df27fe",
"crates/horizon-core/src/geometry/movement.rs": "bcfb452752940ce53ae6dc267a3c4eb29459046a063c1f884684ab4f4bd0068f",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/Cargo.toml": "18bbad377a8047e4d4ecd0fc87d83d46d1c0f1ce2b8c47bbe64633e7b4420b57",
"crates/horizon-world/src/active_effect_tick.rs": "88f19cfc3532c47a58c646bb3e9d99ff239a900752302b6a444dda3013e95cbf",
"crates/horizon-world/src/active_effects.rs": "daaf352a69511a7d69fb329997f783b86585e486e0379c84ab0a55641771646c",
"crates/horizon-world/src/attribute_health.rs": "1420a80787d10dd2e2954a3ee6193ff313289d00c7c78ca26ece8bafa21f4380",
"crates/horizon-world/src/attribute_map.rs": "3d871cd530f5c035e0753f3ba065c2b9c5b49cdee75d4119f7dd584b22af67e6",
"crates/horizon-world/src/attribute_updates.rs": "4cb322d75a50d222298994607097ba7f7e6674021128fa02a98a74c057ad05f1",
"crates/horizon-world/src/attributes/entity.rs": "64ac99682a3aa06b1fb94b776b47794234c76b1cf70f1f54933d51e545e69279",
"crates/horizon-world/src/attributes/live.rs": "8198c45134f69135d48ef203e71b6e702529568fd1ed9174d0aa843570bbf9e7",
"crates/horizon-world/src/attributes/mod.rs": "5c2fcbbde58c19261874d227ea98332f00336c9fa53446da2e9adb6aa64a5e5a",
"crates/horizon-world/src/attributes/operation_map.rs": "fc5bc8921d78ea6721a2eaa915e67483e2a33683927467bdba24f0492356ad97",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "39207247f2f6dd3ddc77640229044246f91b32054563f88a435f1bd92ad2092c",
"crates/horizon-world/src/block_collision_scan.rs": "20802862364c110ff85eeaf48606596a8468b83768dda46b412d337958790b41",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_entity_push.rs": "12ee91bf604946234b24a0da4333f07d1830ab9743a422d41c8d0afac7d49cfd",
"crates/horizon-world/src/block_landing.rs": "33083fe39266fbefec1b3ea1a19f2afc609791d189da247c895e116ad6eb266a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/blocking_item_damage.rs": "afea3cb5761e8b82ee4d9bb4ef3c6fd10182a324dbaec99e6c9ebfac255dda09",
"crates/horizon-world/src/blocking_rules.rs": "83c5e2105cec56a90182ce582e1c67ade2b189be6de1a34d08035000cc07c492",
"crates/horizon-world/src/bundle_weight.rs": "a0e7b0587ab5d46cd55588f25d55a088b7a4725099c13ba6df146957be36014c",
"crates/horizon-world/src/chunk.rs": "795895284d6e615bcb2082fceacdfe7025c152fb2934bb43f598f17a00ab46f1",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/climbing.rs": "6cd2f919872ff0b726effddaa57eccb805b8eae43f9d01144716010853891879",
"crates/horizon-world/src/collision.rs": "a749794d5c27ccd6c0d964ad02f9dc31d49d9f4fe4b7366cd4bd8155e681b00b",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/combat_rules.rs": "01131f70d1acdd96a910e7f96deaa12e51a1e3bb9208085f04e3ec7b657d3cd4",
"crates/horizon-world/src/component_durability.rs": "37a46e184f95bc5027e2b9af72ff52f729ad03601d08e1827f181fca383a35af",
"crates/horizon-world/src/component_patch.rs": "f6f8992f241dfb25e012a06a7ba3fecab8d958686dddd096595a4806e56f0ab3",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/consumable.rs": "ba3575cb85866cb940f33a1ac86455d71cf0cc6395b848588a8ee1fe33f5c326",
"crates/horizon-world/src/consume_effect.rs": "03f2aac6879ce133347d42f6f6667d62c06d956ff9faac5dc14182a788b6a236",
"crates/horizon-world/src/damage_immunity.rs": "fd39c41124d694e755cf7faadcf93c636df4042c78ec345092a856b5f952dbcf",
"crates/horizon-world/src/damage_reduction.rs": "f5a599ab11e077f526237018aeda803ea3c420c5b35c78ae9d85e32267e23bf3",
"crates/horizon-world/src/damage_source.rs": "24945e397a926d34695652980923609e4723e02fe6b6e56d4aaf673e45d759f7",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/edge_backoff.rs": "5259d7aa44e64f88351d1556c44dd0edcad3b400a099c659755792efba7b5773",
"crates/horizon-world/src/effect_attribute_modifiers.rs": "0bc7ab63d0f3f34a7133fe20364cae0ec1fdbd3773cba90faa1f08e0d63a5646",
"crates/horizon-world/src/effect_notifications.rs": "ea66bfa010d6d44aee97b9672902f41cd99d0d80239f41c6d4eae5c9a9472d3d",
"crates/horizon-world/src/effect_particles.rs": "a42dc4ec55929dce1db0f22f8816ecf7621fdce1cd2ac0c90f6a57fea4e0afd2",
"crates/horizon-world/src/effect_sync.rs": "1388d4a69b42a14ff4cd474f5e36f0fad5a2874031e64fa2b19b2ea179deed2b",
"crates/horizon-world/src/entity_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"crates/horizon-world/src/entity_fluid.rs": "02991040ae879a8914f09913128a3506e9e7a1ca33ffc0a22b5729a168346600",
"crates/horizon-world/src/entity_fluid_tick.rs": "4f9e070b88a73c98a4e2e659360ddd6edee636bca29377f1ea9011fd5a556f64",
"crates/horizon-world/src/entity_move.rs": "a40a50d3e841625a75d4cfbb7c2630ab5a62a574456567e7234f401ae8441b32",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/extra_items.rs": "6eba0a0c795d5fd841d31471708e78324b4852adebb2e6ed700dcc0caab668cd",
"crates/horizon-world/src/fall_damage.rs": "8c28e2933493569fe05dea22332024287d28b0746b514dd465681040b003296b",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/fluid_box.rs": "b586af72b1c04a9354fe66205c28dc8b619e205ab9ea19a68232722e4b6e96c1",
"crates/horizon-world/src/fluid_flow.rs": "7c7e486b5c565df3602799648b37b879bcca51414337f607962d6c7951b86d05",
"crates/horizon-world/src/fluid_occupancy.rs": "26037579caeef6c8a5a2bde2c3d142d278558b76d77ebff401cee6e35f2ea961",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/food.rs": "3cf416fa632a5555a8116bb528a6e80bcb5b6b754b0748b4959ed310102418d3",
"crates/horizon-world/src/food_properties.rs": "0926fa3f3bc3d0608c45d02f564355825ca3c3526a82bf9c1375c7a191fa5e12",
"crates/horizon-world/src/food_storage.rs": "58c433801a285efcc973638c11d694a41f85dc96703a3a7ce8d3673f3eb31d52",
"crates/horizon-world/src/free_space.rs": "913536bf4c85ddeeb378d76d1b5110b4175f5688e1a749f32fe6a6d86fbb478e",
"crates/horizon-world/src/ground_support.rs": "3e371d74ecede4d30beef0a7e8a2ee33463584a5b1ed3d852b394efcce1ffbe0",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/identifier.rs": "37c921889c4f5d91f7c09ab2ee68d1a5e5a3c4fb1c49b4b189c987b4615fd2d6",
"crates/horizon-world/src/interaction_shapes.rs": "f321284ddab440a394372b6dedc8b5cc29a653c0745251a9e96c650f21c33dea",
"crates/horizon-world/src/inventory_pickup.rs": "ea830c7916e7f2d95c6db7ef48be1e876e6ebafcb438e47fc72f9a5bd7c37d07",
"crates/horizon-world/src/inventory_tick.rs": "293a3d57a1689337cfd58e5a73dcdbed4cb360f94d98ff5458f0df92de387365",
"crates/horizon-world/src/inventory_use.rs": "6a6c2ecc73c83dda4cd798c0304df12ace6096eb110d899f4f0c7ffd852bf001",
"crates/horizon-world/src/item_after_use.rs": "2b6598ce5b7b304dea2c8057b4a1eb6530264ac4d0546c3da0c76deed9609da5",
"crates/horizon-world/src/item_blocking.rs": "f6eee0d6d177cc3148960122327ba1b459a2f0e85241c1d9a3e40f0b8c169296",
"crates/horizon-world/src/item_cooldowns.rs": "7b625868509ab3c51e72db0ac714bb0e7ec5e2610d37271005a1a737f4d14431",
"crates/horizon-world/src/item_durability.rs": "9fdf835e5c7bd0e1dd63ef2ba0076b770cdd4d6d14cdcd11de27690f0702f94e",
"crates/horizon-world/src/item_particles.rs": "861b14f65adb9b14f8158fe9f0b7128beac3df8107b1337c31b8b9b49434ba3f",
"crates/horizon-world/src/item_stack_refs.rs": "18d3ca85cac0daf59200857513761359e5690f719cb3f7f64ae552f0c4169ea3",
"crates/horizon-world/src/item_stack_storage.rs": "b4dcb83dcaa346848c5484161feb3e2cf08e83f7793d7ed83be25b14b9d12884",
"crates/horizon-world/src/item_template.rs": "dc80025215d1867e656924ea2a9d273aacbcaea21293d986ba42d0004ee93b69",
"crates/horizon-world/src/item_use.rs": "b1c79428986efbf9dd5ede703a39eb387fb6dcc7d9950f0e49243a353a5b8070",
"crates/horizon-world/src/item_use_catalog.rs": "a9b53d2e816583239a75c3c61e78dacc5e3b27dee595be34b1c7fa169f17a571",
"crates/horizon-world/src/item_use_lifecycle.rs": "4639b70440cf811e79de09c48a3e035143fcb6be8a64c2f61b10ae55a2f133b7",
"crates/horizon-world/src/item_use_start.rs": "a84092dfb8b8f0a89d0928bb2f8ac252bd9bfd3f8d74fce1a7f7a5b3c3f4f50b",
"crates/horizon-world/src/java_hash_map.rs": "955502e696d7b0b33bae3ec485c8eb1453a8956116aad68226cf1fc67d60babc",
"crates/horizon-world/src/lib.rs": "577c16c021352b706d123f0f1c734375fc4a5a67b508caccbc38c1e1f693f6f4",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/live_attribute_updates.rs": "778171faaaf7077deb0b62c4cc1db16351eba41adb8bb07656ba65e827056199",
"crates/horizon-world/src/living_air.rs": "b2de36bb50bed15e2808fe4a874fcef07f9fea0d2c96385b7b5e8ee9560d4442",
"crates/horizon-world/src/living_damage.rs": "2b448209629b9bf2e678d667ad0d6c7fa22146892dd106b169d96b31b0df12bb",
"crates/horizon-world/src/living_fall.rs": "da0f176f4731e1c86e08bfeee8167742fd1b86380ff0e9304c13c1ce3f1c67ab",
"crates/horizon-world/src/living_fluid.rs": "d7cd914cfb2a1f4876ce0ae95e999bf0ff1af732cce3ab4a3aa2d1ab881c7339",
"crates/horizon-world/src/living_health.rs": "221659f85552424e937d503bba6d8003006b106ced042b32d3a6f6cc23e12ed0",
"crates/horizon-world/src/living_hurt.rs": "844239ad7d15c39629bb3cfc06ebae6d1cff20b7627468f26e0ee8dff3abdcb8",
"crates/horizon-world/src/living_landing.rs": "8bca4eb7977abc2b14fb7174be4ea355352106ea1e76ff5f3ad8696969d9eefd",
"crates/horizon-world/src/living_motion.rs": "56f8c84cfbe205a7a69912d5f76b52ef1efca149c1b6801d4684e25fb179aeb9",
"crates/horizon-world/src/living_use_flags.rs": "826f4fdeba7e208368cbbf910fa408db0afbc6442d842d178a70fae53e0d0ea6",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/movement_emission.rs": "76e7d6f5b19c94676190f54389f9c4ce12cf89945ccfcb9c750de473223e7753",
"crates/horizon-world/src/movement_properties.rs": "6f01ab920b376a13f5ae12c3718f4dd067e1dff2b829585af00a8b2100f3775d",
"crates/horizon-world/src/movement_restitution.rs": "04b4fe0947e7e52576145bd8ed15920278e8a538afcc74d125eaca513dffa0ef",
"crates/horizon-world/src/movement_support.rs": "02d85cf572847f2e60b5a7f9d60b856888a67b3c1f4df03e81998c66fdf874be",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/object_open_map.rs": "b4934a9cc38df93ed206ab0bc3bbc4499acd8e40b41b7def7d47067b7170065b",
"crates/horizon-world/src/object_open_set.rs": "d3e0373bf1b652dd054345d5a8e25ec828e06dd7cad65aada35163c95df4e637",
"crates/horizon-world/src/piston_movement.rs": "7a3fd2549a582b5f3a5c21aa05d67d944d62ca1105856679e100ac5b44e9a52f",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/player_equipment.rs": "1fa8c53e67624c4641246249d79a800a28a4858c62482bd880b4e3b866b936ef",
"crates/horizon-world/src/player_food.rs": "f188dc110745bcc7acc15e6c521db943b06b404f69cd251bf74a345516070304",
"crates/horizon-world/src/player_health.rs": "8155b315453c569db2fbe46228886c5881d1fd55eb095c5849e69bdb500ba2bd",
"crates/horizon-world/src/player_hurt.rs": "99c9bbd8587ec2dc287806049897b8034d2f5349ad47fc497b70d54148844a36",
"crates/horizon-world/src/player_inventory.rs": "f4f67d8312793f25930626c4ac06db688fcf2e2292d6675071d105fb1708d952",
"crates/horizon-world/src/player_travel.rs": "6841a677a900495eb6223031ef3ebe8d859bb98908dda0e2209e5f28839dc593",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/registry_collision_scan.rs": "97cc950a9a4ba387b78e368f36d595f8664ab7730d132900d220ce23b92826ea",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/registry_fluid.rs": "b8959c05850cfeaaad1e4de8ca7c7d0d6ac56da9b2c1de3ebefa5871a11ed35e",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/server_player_combat.rs": "0a94885c4b7a0d294ba7f4cee18b96ee59649b50112988250b53cc224059a979",
"crates/horizon-world/src/server_player_damage.rs": "29af22dec321fe01776cee5334f050c5bc3e27a688f99c8c3da4c0ad8bc8254e",
"crates/horizon-world/src/simple_container.rs": "0fedbc7e974b1db79b88bd6aff977654189a5d553cf42852fe8bf0885cf90b30",
"crates/horizon-world/src/status_effect.rs": "588bfcf4d93f50be86cb89545bd5c431edbc71771f704ff55cb52906b1964c37",
"crates/horizon-world/src/stored_consume.rs": "621a52c9fba447c393e561f881a16cf1f97d336e3a0ce493725ef51e2db12ffd",
"crates/horizon-world/src/stored_effect_attributes.rs": "c79f6a52d3cfee1a5288225bf8fa91a7bf3ea8cd21faea9f6dc748ecefc6309a",
"crates/horizon-world/src/suffocation.rs": "bed219dd5bbab6263b98fbe3d0eb512cb96c52ae847210efe49514d05f22f11e",
"crates/horizon-world/src/swimming.rs": "49d2dae13c109b37ff832cde98a857944ff45247b864a527b9c4f03ecca7a7b7",
"crates/horizon-world/src/synced_floats.rs": "0152f2752bafaf68769d56dbc88494a976496a680c6b113d6b48a446158ba072",
"crates/horizon-world/src/synced_values.rs": "a1d4b53ae77d1899ba2b4ead67c9ec1e3c96615558e446f9d0760c1b4a520169",
"crates/horizon-world/src/teleport_consume.rs": "d6a53bbb6ac4dbbd4c0591d0646017898a95beb8ef093dc5d81b9833963be6c3",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/use_remainder.rs": "f555335afeca7970888131a6da2f5a614a73253b631185d1ba804593a349535e",
"crates/horizon-world/src/view_direction.rs": "e18120ae26dc5cf702b29fc4c8487088bab133c8ce5abce01226833fafb0d5a4",
"crates/horizon-world/src/water_splash.rs": "e0461ae1b2e8c851cca6e3251a188334293292201d7f80dc9e7d60fd1815f4d1",
"crates/horizon-world/src/world_movement.rs": "f8fe9e34f2395d2a04c839d1c8ba78e09ce493c26de6f6e4e237b9c19c061da5",
"crates/horizon-world/src/world_ray.rs": "879bdbbe12f56deb705cc183933431489e840b71eade40c33391eed5949c2e61",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "74e4110fb19c4c4047192fd65c38015b8afc7f9fc50404d75380b5063808148c",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f"
}
}
@@ -1,790 +0,0 @@
{
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"animated_sprites": 1,
"animation_uploads": 1,
"arch": "x86_64",
"camera_pitch": -0.3839724354387525,
"camera_position": [
25.0,
18.0,
25.0
],
"camera_yaw": -2.356194490192345,
"collision_camera": false,
"culled_model_faces": 59636,
"elapsed_seconds": 0.547517663,
"error": null,
"fall_damage_requests": 0,
"last_requested_fall_damage": null,
"merged_quads": 3169,
"mesh_revision": 0,
"model_blocks": 10919,
"model_gallery": [
{
"block": "minecraft:oak_stairs",
"models": [
{
"model": "minecraft:block/oak_stairs_inner",
"rotations": [
2,
3,
0
],
"uv_lock": true
}
],
"position": [
-7,
4,
14
],
"properties": {
"facing": "north",
"half": "top",
"shape": "inner_left",
"waterlogged": "false"
},
"state_id": 5466
},
{
"block": "minecraft:stone_slab",
"models": [
{
"model": "minecraft:block/stone_slab_top",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
14
],
"properties": {
"type": "top",
"waterlogged": "false"
},
"state_id": 15250
},
{
"block": "minecraft:anvil",
"models": [
{
"model": "minecraft:block/anvil",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
14
],
"properties": {
"facing": "east"
},
"state_id": 12965
},
{
"block": "minecraft:torch",
"models": [
{
"model": "minecraft:block/torch",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
14
],
"properties": {},
"state_id": 4926
},
{
"block": "minecraft:lantern",
"models": [
{
"model": "minecraft:block/lantern",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
18
],
"properties": {
"hanging": "false",
"waterlogged": "false"
},
"state_id": 24197
},
{
"block": "minecraft:oak_fence",
"models": [
{
"model": "minecraft:block/oak_fence_post",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
0,
0
],
"uv_lock": true
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
-3,
4,
18
],
"properties": {
"east": "true",
"north": "true",
"south": "false",
"waterlogged": "false",
"west": "false"
},
"state_id": 8642
},
{
"block": "minecraft:oak_fence_gate",
"models": [
{
"model": "minecraft:block/oak_fence_gate_open",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
1,
4,
18
],
"properties": {
"facing": "west",
"in_wall": "false",
"open": "true",
"powered": "false"
},
"state_id": 10401
},
{
"block": "minecraft:iron_bars",
"models": [
{
"model": "minecraft:block/iron_bars_post_ends",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side_alt",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
18
],
"properties": {
"east": "false",
"north": "true",
"south": "true",
"waterlogged": "false",
"west": "false"
},
"state_id": 9711
},
{
"block": "minecraft:cobweb",
"models": [
{
"model": "minecraft:block/cobweb",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
22
],
"properties": {},
"state_id": 2362
},
{
"block": "minecraft:grindstone",
"models": [
{
"model": "minecraft:block/grindstone",
"rotations": [
1,
3,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
22
],
"properties": {
"face": "wall",
"facing": "west"
},
"state_id": 24135
},
{
"block": "minecraft:ladder",
"models": [
{
"model": "minecraft:block/ladder",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
22
],
"properties": {
"facing": "west",
"waterlogged": "false"
},
"state_id": 7312
},
{
"block": "minecraft:amethyst_cluster",
"models": [
{
"model": "minecraft:block/amethyst_cluster",
"rotations": [
1,
1,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
22
],
"properties": {
"facing": "east",
"waterlogged": "false"
},
"state_id": 26764
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone_mirrored",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
26
],
"properties": {},
"state_id": 1
}
],
"model_quads": 179,
"movement_ticks": 0,
"os": "linux",
"player_fall_distance": null,
"player_on_ground": null,
"player_position": null,
"player_velocity": null,
"presented_frames": 30,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native resident-scene renderer with inspection camera and optional fixed-rate dry walking test; full gameplay remains unfinished",
"sprite_layers": 18,
"visible_model_faces": 5991,
"walking": false,
"window_size": [
1280,
720
],
"world_revision": 0,
"native_scene_culling": {
"blocks": 10919,
"culled_faces": 59636,
"visible_faces": 5991
},
"native_selection": {
"matched_placements": 16,
"selected_parts": 20,
"client_jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "a2ff1c890d6f3a5292c3a9402f02ca5404a993dc117853b25cbe64ac92b76d30",
"scope": "Actual native registry states, blockstate dispatch, tagged root baking and legacy collection using state.getSeed(position). All 16 featured placements match model names/transforms. An independently constructed native scene also matches total occupied blocks and visible/culled model faces using native parent resolution, rotated culling directions and Block.shouldRenderFace. No shader/pixel parity claim."
},
"resource_files": {
"files": 5586,
"sha256": "df3e6624ad08800f224dbe4c90fd3753ba84e7643f93475701957108a73acb25"
},
"executable_sha256": "fcfd655b756ed003cd5b97fe9ca5afba8b965813b2d7cb30e7639168f8d17e22",
"resource_manifest_sha256": "91491cf250a0032f6a7fc8e4a10807f7384310d927babe178ffc75ded8ef25b0",
"sources": {
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "6884c7209f007ab9ee742b9c3c73828cfa1c6753d35b5fe25a87cab5955b33f8",
"tools/test_native_client.py": "9310a571c3a8908c6c4804a8b14935882382da0f4755ffc4d1087d379824bb32",
"crates/horizon-client/Cargo.toml": "d56524457d761c2613c0699b20e21ad6977d93e009d59ef150bbd9fc20d7a025",
"crates/horizon-assets/Cargo.toml": "2f2cffacec0b4e22dd7cb032d594289bc51c94ae6cc4e985fee3e310f441d751",
"crates/horizon-client/src/assets.rs": "e595afa610e0425d0b3ad694218794bf9e680e46ae80f3925c278ef1a823c914",
"crates/horizon-client/src/camera.rs": "d386a56ca8fb3b37ba2b2ed9d09342f61b409a575bb21590e934120b4ccebfa6",
"crates/horizon-client/src/clock.rs": "4851ada3e8e65d935eda8c0b57d3b51233b34f74aab4f040fd53db0e0d40b8df",
"crates/horizon-client/src/collisions.rs": "112286b07c4cd11b36da8b6799e0e069e69dfddf9a8a3f9ce36dcb282c791d67",
"crates/horizon-client/src/input.rs": "55b259ca6425c502270e7abc4d3ae1b3838633e2bd77d3817c6e00d9143a2beb",
"crates/horizon-client/src/landing.rs": "4192ce43717696b2c893b69f7f156b3084cd5a92dd275f0c5be1ee7c6228918b",
"crates/horizon-client/src/lib.rs": "6eb8caa81741cabc56651603f9be8d15a8d219be5a5ae4dc2045c557fc24bb79",
"crates/horizon-client/src/main.rs": "aa602d14ab9512de90165c9aeee40dd04d5cd602d8fc2a9d2d7139f12a7db1ec",
"crates/horizon-client/src/mesh.rs": "4ac8d85b30f599b37a98b92adcc016b16434816b93c401bd39b8215f591f9330",
"crates/horizon-client/src/models/catalog.rs": "620103719167fc9ab76e730d68eeacb50014e95b7ad209ae7adf2cbbe69f70f7",
"crates/horizon-client/src/models/cube.rs": "1067229f9dd9b276950bf7ec0c5f67061ce3d40a21932dca8034b9748e7439a4",
"crates/horizon-client/src/models.rs": "98dd3b969947c2b297862a934e6235067ddc1fc8cda5adcc6276d19014d4b048",
"crates/horizon-client/src/motion.rs": "0b2ecde5118b60a158e18aa5cf7746ef88566a0ad0fc3c97594b8d5ee00b1cdb",
"crates/horizon-client/src/render.rs": "75cb40c257cf61e51009d292a06cd96532f59320b12ed7c3a509bbdbe1accdd4",
"crates/horizon-client/src/sprites.rs": "292f844a31f6e8884008df9630e2b8862db1acfbc4640cc07d526e25f21f0bc5",
"crates/horizon-client/src/world.rs": "66c921c4a0c4e5bf97f2594ed243f6769d0dcebe9fe227177df928df22d6d03e",
"crates/horizon-client/src/world.wgsl": "972a58ccb34e9965515adbb30c47a93fceca5b742390db6d9f69cba1ec31f559",
"crates/horizon-assets/src/animation.rs": "ebbf7952146a0e66b41396174492f5702627170b03a57e6cd5a45c97a08c975e",
"crates/horizon-assets/src/bake/transform.rs": "a95e658fef85b21bcb2f9f7512f98f98d57022d62c1199885b7133beae35a09d",
"crates/horizon-assets/src/bake.rs": "f55dda6b6cee5ac6e65a8ee4837fdd2c6674437d59e59b4c45718f6324d4a4d5",
"crates/horizon-assets/src/blockstate/bind.rs": "6278962e55c9786bba8184bdf2939af9c6e3b9002b08c3022129964b49a60009",
"crates/horizon-assets/src/blockstate/choice.rs": "5a66c8b9833e2f19dd8b0773f3593d97ff5941d3c5b773896b98049efa1395ba",
"crates/horizon-assets/src/blockstate.rs": "a4299dfd7adaeb4173982ffaa8e9c9eda2925739ae579a714193c99da2e7ce56",
"crates/horizon-assets/src/json.rs": "99fe8af4fbf5d4eed408a92e829ac1a39597a0d92471a6bff73771fad9c830a8",
"crates/horizon-assets/src/lib.rs": "e39f21c59a2c3e1c53d977b29bd5e0638e5fc41d86ff0fcc1882a6d90fd961e4",
"crates/horizon-assets/src/model.rs": "57ddb3d65e88e7a8aa22c62bc298a2dae7f4e994326a873a31f06c0f36ed051b",
"crates/horizon-assets/src/resolve.rs": "3927ac926cdcbd7d334901cc32d0ecc1e498b1bec98f76a46bca6d4964c13541",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaGallerySelectionOracle.java": "dc5433f1ce1de629b30cb70f031a43a691fc1df1fb218ce23de89769c164d562",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCuboidModelOracle.java": "7526f20513c549483122ab0d5ad24b9e87f38dc2f6aae55addd701a91ac85e43",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
"tools/test_model_baking_parity.py": "392ffec44918fb91740ca4a1316d684480d39f14bd34d46175f7f44946d15bd7",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"tools/prepare_native_client.py": "3a02b5f384235eb2d7002396cbddffb3bf3840534c205c85aefac090562b76c4",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/border.rs": "1386f8080521231d05ba3e84d94a3e1d5218d35ccb3d5e9fe2bbb05a8739e573",
"crates/horizon-core/src/geometry/mod.rs": "c650386f9860e44a96c55f18c8f1428ca715fcb0bc5c2434db5b1caa43df27fe",
"crates/horizon-core/src/geometry/movement.rs": "bcfb452752940ce53ae6dc267a3c4eb29459046a063c1f884684ab4f4bd0068f",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/Cargo.toml": "18bbad377a8047e4d4ecd0fc87d83d46d1c0f1ce2b8c47bbe64633e7b4420b57",
"crates/horizon-world/src/active_effect_tick.rs": "88f19cfc3532c47a58c646bb3e9d99ff239a900752302b6a444dda3013e95cbf",
"crates/horizon-world/src/active_effects.rs": "daaf352a69511a7d69fb329997f783b86585e486e0379c84ab0a55641771646c",
"crates/horizon-world/src/attribute_health.rs": "1420a80787d10dd2e2954a3ee6193ff313289d00c7c78ca26ece8bafa21f4380",
"crates/horizon-world/src/attribute_map.rs": "3d871cd530f5c035e0753f3ba065c2b9c5b49cdee75d4119f7dd584b22af67e6",
"crates/horizon-world/src/attribute_updates.rs": "4cb322d75a50d222298994607097ba7f7e6674021128fa02a98a74c057ad05f1",
"crates/horizon-world/src/attributes/entity.rs": "64ac99682a3aa06b1fb94b776b47794234c76b1cf70f1f54933d51e545e69279",
"crates/horizon-world/src/attributes/live.rs": "8198c45134f69135d48ef203e71b6e702529568fd1ed9174d0aa843570bbf9e7",
"crates/horizon-world/src/attributes/mod.rs": "5c2fcbbde58c19261874d227ea98332f00336c9fa53446da2e9adb6aa64a5e5a",
"crates/horizon-world/src/attributes/operation_map.rs": "fc5bc8921d78ea6721a2eaa915e67483e2a33683927467bdba24f0492356ad97",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "39207247f2f6dd3ddc77640229044246f91b32054563f88a435f1bd92ad2092c",
"crates/horizon-world/src/block_collision_scan.rs": "20802862364c110ff85eeaf48606596a8468b83768dda46b412d337958790b41",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_entity_push.rs": "12ee91bf604946234b24a0da4333f07d1830ab9743a422d41c8d0afac7d49cfd",
"crates/horizon-world/src/block_landing.rs": "33083fe39266fbefec1b3ea1a19f2afc609791d189da247c895e116ad6eb266a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/blocking_item_damage.rs": "afea3cb5761e8b82ee4d9bb4ef3c6fd10182a324dbaec99e6c9ebfac255dda09",
"crates/horizon-world/src/blocking_rules.rs": "83c5e2105cec56a90182ce582e1c67ade2b189be6de1a34d08035000cc07c492",
"crates/horizon-world/src/bundle_weight.rs": "a0e7b0587ab5d46cd55588f25d55a088b7a4725099c13ba6df146957be36014c",
"crates/horizon-world/src/chunk.rs": "795895284d6e615bcb2082fceacdfe7025c152fb2934bb43f598f17a00ab46f1",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/climbing.rs": "6cd2f919872ff0b726effddaa57eccb805b8eae43f9d01144716010853891879",
"crates/horizon-world/src/collision.rs": "a749794d5c27ccd6c0d964ad02f9dc31d49d9f4fe4b7366cd4bd8155e681b00b",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/combat_rules.rs": "01131f70d1acdd96a910e7f96deaa12e51a1e3bb9208085f04e3ec7b657d3cd4",
"crates/horizon-world/src/component_durability.rs": "37a46e184f95bc5027e2b9af72ff52f729ad03601d08e1827f181fca383a35af",
"crates/horizon-world/src/component_patch.rs": "f6f8992f241dfb25e012a06a7ba3fecab8d958686dddd096595a4806e56f0ab3",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/consumable.rs": "ba3575cb85866cb940f33a1ac86455d71cf0cc6395b848588a8ee1fe33f5c326",
"crates/horizon-world/src/consume_effect.rs": "03f2aac6879ce133347d42f6f6667d62c06d956ff9faac5dc14182a788b6a236",
"crates/horizon-world/src/damage_immunity.rs": "fd39c41124d694e755cf7faadcf93c636df4042c78ec345092a856b5f952dbcf",
"crates/horizon-world/src/damage_reduction.rs": "f5a599ab11e077f526237018aeda803ea3c420c5b35c78ae9d85e32267e23bf3",
"crates/horizon-world/src/damage_source.rs": "24945e397a926d34695652980923609e4723e02fe6b6e56d4aaf673e45d759f7",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/edge_backoff.rs": "5259d7aa44e64f88351d1556c44dd0edcad3b400a099c659755792efba7b5773",
"crates/horizon-world/src/effect_attribute_modifiers.rs": "0bc7ab63d0f3f34a7133fe20364cae0ec1fdbd3773cba90faa1f08e0d63a5646",
"crates/horizon-world/src/effect_notifications.rs": "ea66bfa010d6d44aee97b9672902f41cd99d0d80239f41c6d4eae5c9a9472d3d",
"crates/horizon-world/src/effect_particles.rs": "a42dc4ec55929dce1db0f22f8816ecf7621fdce1cd2ac0c90f6a57fea4e0afd2",
"crates/horizon-world/src/effect_sync.rs": "1388d4a69b42a14ff4cd474f5e36f0fad5a2874031e64fa2b19b2ea179deed2b",
"crates/horizon-world/src/entity_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"crates/horizon-world/src/entity_fluid.rs": "02991040ae879a8914f09913128a3506e9e7a1ca33ffc0a22b5729a168346600",
"crates/horizon-world/src/entity_fluid_tick.rs": "4f9e070b88a73c98a4e2e659360ddd6edee636bca29377f1ea9011fd5a556f64",
"crates/horizon-world/src/entity_move.rs": "a40a50d3e841625a75d4cfbb7c2630ab5a62a574456567e7234f401ae8441b32",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/extra_items.rs": "6eba0a0c795d5fd841d31471708e78324b4852adebb2e6ed700dcc0caab668cd",
"crates/horizon-world/src/fall_damage.rs": "8c28e2933493569fe05dea22332024287d28b0746b514dd465681040b003296b",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/fluid_box.rs": "b586af72b1c04a9354fe66205c28dc8b619e205ab9ea19a68232722e4b6e96c1",
"crates/horizon-world/src/fluid_flow.rs": "7c7e486b5c565df3602799648b37b879bcca51414337f607962d6c7951b86d05",
"crates/horizon-world/src/fluid_occupancy.rs": "26037579caeef6c8a5a2bde2c3d142d278558b76d77ebff401cee6e35f2ea961",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/food.rs": "3cf416fa632a5555a8116bb528a6e80bcb5b6b754b0748b4959ed310102418d3",
"crates/horizon-world/src/food_properties.rs": "0926fa3f3bc3d0608c45d02f564355825ca3c3526a82bf9c1375c7a191fa5e12",
"crates/horizon-world/src/food_storage.rs": "58c433801a285efcc973638c11d694a41f85dc96703a3a7ce8d3673f3eb31d52",
"crates/horizon-world/src/free_space.rs": "913536bf4c85ddeeb378d76d1b5110b4175f5688e1a749f32fe6a6d86fbb478e",
"crates/horizon-world/src/ground_support.rs": "3e371d74ecede4d30beef0a7e8a2ee33463584a5b1ed3d852b394efcce1ffbe0",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/identifier.rs": "37c921889c4f5d91f7c09ab2ee68d1a5e5a3c4fb1c49b4b189c987b4615fd2d6",
"crates/horizon-world/src/interaction_shapes.rs": "f321284ddab440a394372b6dedc8b5cc29a653c0745251a9e96c650f21c33dea",
"crates/horizon-world/src/inventory_pickup.rs": "ea830c7916e7f2d95c6db7ef48be1e876e6ebafcb438e47fc72f9a5bd7c37d07",
"crates/horizon-world/src/inventory_tick.rs": "293a3d57a1689337cfd58e5a73dcdbed4cb360f94d98ff5458f0df92de387365",
"crates/horizon-world/src/inventory_use.rs": "6a6c2ecc73c83dda4cd798c0304df12ace6096eb110d899f4f0c7ffd852bf001",
"crates/horizon-world/src/item_after_use.rs": "2b6598ce5b7b304dea2c8057b4a1eb6530264ac4d0546c3da0c76deed9609da5",
"crates/horizon-world/src/item_blocking.rs": "f6eee0d6d177cc3148960122327ba1b459a2f0e85241c1d9a3e40f0b8c169296",
"crates/horizon-world/src/item_cooldowns.rs": "7b625868509ab3c51e72db0ac714bb0e7ec5e2610d37271005a1a737f4d14431",
"crates/horizon-world/src/item_durability.rs": "9fdf835e5c7bd0e1dd63ef2ba0076b770cdd4d6d14cdcd11de27690f0702f94e",
"crates/horizon-world/src/item_particles.rs": "861b14f65adb9b14f8158fe9f0b7128beac3df8107b1337c31b8b9b49434ba3f",
"crates/horizon-world/src/item_stack_refs.rs": "18d3ca85cac0daf59200857513761359e5690f719cb3f7f64ae552f0c4169ea3",
"crates/horizon-world/src/item_stack_storage.rs": "b4dcb83dcaa346848c5484161feb3e2cf08e83f7793d7ed83be25b14b9d12884",
"crates/horizon-world/src/item_template.rs": "dc80025215d1867e656924ea2a9d273aacbcaea21293d986ba42d0004ee93b69",
"crates/horizon-world/src/item_use.rs": "b1c79428986efbf9dd5ede703a39eb387fb6dcc7d9950f0e49243a353a5b8070",
"crates/horizon-world/src/item_use_catalog.rs": "a9b53d2e816583239a75c3c61e78dacc5e3b27dee595be34b1c7fa169f17a571",
"crates/horizon-world/src/item_use_lifecycle.rs": "4639b70440cf811e79de09c48a3e035143fcb6be8a64c2f61b10ae55a2f133b7",
"crates/horizon-world/src/item_use_start.rs": "a84092dfb8b8f0a89d0928bb2f8ac252bd9bfd3f8d74fce1a7f7a5b3c3f4f50b",
"crates/horizon-world/src/java_hash_map.rs": "955502e696d7b0b33bae3ec485c8eb1453a8956116aad68226cf1fc67d60babc",
"crates/horizon-world/src/lib.rs": "577c16c021352b706d123f0f1c734375fc4a5a67b508caccbc38c1e1f693f6f4",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/live_attribute_updates.rs": "778171faaaf7077deb0b62c4cc1db16351eba41adb8bb07656ba65e827056199",
"crates/horizon-world/src/living_air.rs": "b2de36bb50bed15e2808fe4a874fcef07f9fea0d2c96385b7b5e8ee9560d4442",
"crates/horizon-world/src/living_damage.rs": "2b448209629b9bf2e678d667ad0d6c7fa22146892dd106b169d96b31b0df12bb",
"crates/horizon-world/src/living_fall.rs": "da0f176f4731e1c86e08bfeee8167742fd1b86380ff0e9304c13c1ce3f1c67ab",
"crates/horizon-world/src/living_fluid.rs": "d7cd914cfb2a1f4876ce0ae95e999bf0ff1af732cce3ab4a3aa2d1ab881c7339",
"crates/horizon-world/src/living_health.rs": "221659f85552424e937d503bba6d8003006b106ced042b32d3a6f6cc23e12ed0",
"crates/horizon-world/src/living_hurt.rs": "844239ad7d15c39629bb3cfc06ebae6d1cff20b7627468f26e0ee8dff3abdcb8",
"crates/horizon-world/src/living_landing.rs": "8bca4eb7977abc2b14fb7174be4ea355352106ea1e76ff5f3ad8696969d9eefd",
"crates/horizon-world/src/living_motion.rs": "56f8c84cfbe205a7a69912d5f76b52ef1efca149c1b6801d4684e25fb179aeb9",
"crates/horizon-world/src/living_use_flags.rs": "826f4fdeba7e208368cbbf910fa408db0afbc6442d842d178a70fae53e0d0ea6",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/movement_emission.rs": "76e7d6f5b19c94676190f54389f9c4ce12cf89945ccfcb9c750de473223e7753",
"crates/horizon-world/src/movement_properties.rs": "6f01ab920b376a13f5ae12c3718f4dd067e1dff2b829585af00a8b2100f3775d",
"crates/horizon-world/src/movement_restitution.rs": "04b4fe0947e7e52576145bd8ed15920278e8a538afcc74d125eaca513dffa0ef",
"crates/horizon-world/src/movement_support.rs": "02d85cf572847f2e60b5a7f9d60b856888a67b3c1f4df03e81998c66fdf874be",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/object_open_map.rs": "b4934a9cc38df93ed206ab0bc3bbc4499acd8e40b41b7def7d47067b7170065b",
"crates/horizon-world/src/object_open_set.rs": "d3e0373bf1b652dd054345d5a8e25ec828e06dd7cad65aada35163c95df4e637",
"crates/horizon-world/src/piston_movement.rs": "7a3fd2549a582b5f3a5c21aa05d67d944d62ca1105856679e100ac5b44e9a52f",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/player_equipment.rs": "1fa8c53e67624c4641246249d79a800a28a4858c62482bd880b4e3b866b936ef",
"crates/horizon-world/src/player_food.rs": "f188dc110745bcc7acc15e6c521db943b06b404f69cd251bf74a345516070304",
"crates/horizon-world/src/player_health.rs": "79ecb6b4d7a044dc98e5552c53a5ac2724545b1c1cec4d797eb52576728e3480",
"crates/horizon-world/src/player_hurt.rs": "99c9bbd8587ec2dc287806049897b8034d2f5349ad47fc497b70d54148844a36",
"crates/horizon-world/src/player_inventory.rs": "f4f67d8312793f25930626c4ac06db688fcf2e2292d6675071d105fb1708d952",
"crates/horizon-world/src/player_travel.rs": "6841a677a900495eb6223031ef3ebe8d859bb98908dda0e2209e5f28839dc593",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/registry_collision_scan.rs": "97cc950a9a4ba387b78e368f36d595f8664ab7730d132900d220ce23b92826ea",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/registry_fluid.rs": "b8959c05850cfeaaad1e4de8ca7c7d0d6ac56da9b2c1de3ebefa5871a11ed35e",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/server_player_combat.rs": "a9743971581af86d926eeba42004d932caf83382c470dd98bf613cb9c417db58",
"crates/horizon-world/src/server_player_damage.rs": "828a4649fec3e9bda2dfe20aced8c95922c697321de2be4127bd4e5712ecbb7c",
"crates/horizon-world/src/simple_container.rs": "0fedbc7e974b1db79b88bd6aff977654189a5d553cf42852fe8bf0885cf90b30",
"crates/horizon-world/src/status_effect.rs": "588bfcf4d93f50be86cb89545bd5c431edbc71771f704ff55cb52906b1964c37",
"crates/horizon-world/src/stored_consume.rs": "621a52c9fba447c393e561f881a16cf1f97d336e3a0ce493725ef51e2db12ffd",
"crates/horizon-world/src/stored_effect_attributes.rs": "c79f6a52d3cfee1a5288225bf8fa91a7bf3ea8cd21faea9f6dc748ecefc6309a",
"crates/horizon-world/src/suffocation.rs": "bed219dd5bbab6263b98fbe3d0eb512cb96c52ae847210efe49514d05f22f11e",
"crates/horizon-world/src/swimming.rs": "49d2dae13c109b37ff832cde98a857944ff45247b864a527b9c4f03ecca7a7b7",
"crates/horizon-world/src/synced_floats.rs": "0152f2752bafaf68769d56dbc88494a976496a680c6b113d6b48a446158ba072",
"crates/horizon-world/src/synced_values.rs": "a1d4b53ae77d1899ba2b4ead67c9ec1e3c96615558e446f9d0760c1b4a520169",
"crates/horizon-world/src/teleport_consume.rs": "d6a53bbb6ac4dbbd4c0591d0646017898a95beb8ef093dc5d81b9833963be6c3",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/use_remainder.rs": "f555335afeca7970888131a6da2f5a614a73253b631185d1ba804593a349535e",
"crates/horizon-world/src/view_direction.rs": "e18120ae26dc5cf702b29fc4c8487088bab133c8ce5abce01226833fafb0d5a4",
"crates/horizon-world/src/water_splash.rs": "e0461ae1b2e8c851cca6e3251a188334293292201d7f80dc9e7d60fd1815f4d1",
"crates/horizon-world/src/world_movement.rs": "f8fe9e34f2395d2a04c839d1c8ba78e09ce493c26de6f6e4e237b9c19c061da5",
"crates/horizon-world/src/world_ray.rs": "879bdbbe12f56deb705cc183933431489e840b71eade40c33391eed5949c2e61",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "74e4110fb19c4c4047192fd65c38015b8afc7f9fc50404d75380b5063808148c",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f"
}
}
@@ -1,801 +0,0 @@
{
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"animated_sprites": 1,
"animation_uploads": 1,
"arch": "x86_64",
"camera_pitch": -0.3839724354387525,
"camera_position": [
25.0,
18.0,
25.0
],
"camera_yaw": -2.356194490192345,
"collision_camera": false,
"culled_model_faces": 59636,
"elapsed_seconds": 0.556021335,
"error": null,
"fall_damage_requests": 0,
"last_requested_fall_damage": null,
"merged_quads": 3169,
"mesh_revision": 0,
"model_blocks": 10919,
"model_gallery": [
{
"block": "minecraft:oak_stairs",
"models": [
{
"model": "minecraft:block/oak_stairs_inner",
"rotations": [
2,
3,
0
],
"uv_lock": true
}
],
"position": [
-7,
4,
14
],
"properties": {
"facing": "north",
"half": "top",
"shape": "inner_left",
"waterlogged": "false"
},
"state_id": 5466
},
{
"block": "minecraft:stone_slab",
"models": [
{
"model": "minecraft:block/stone_slab_top",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
14
],
"properties": {
"type": "top",
"waterlogged": "false"
},
"state_id": 15250
},
{
"block": "minecraft:anvil",
"models": [
{
"model": "minecraft:block/anvil",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
14
],
"properties": {
"facing": "east"
},
"state_id": 12965
},
{
"block": "minecraft:torch",
"models": [
{
"model": "minecraft:block/torch",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
14
],
"properties": {},
"state_id": 4926
},
{
"block": "minecraft:lantern",
"models": [
{
"model": "minecraft:block/lantern",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
18
],
"properties": {
"hanging": "false",
"waterlogged": "false"
},
"state_id": 24197
},
{
"block": "minecraft:oak_fence",
"models": [
{
"model": "minecraft:block/oak_fence_post",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
0,
0
],
"uv_lock": true
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
-3,
4,
18
],
"properties": {
"east": "true",
"north": "true",
"south": "false",
"waterlogged": "false",
"west": "false"
},
"state_id": 8642
},
{
"block": "minecraft:oak_fence_gate",
"models": [
{
"model": "minecraft:block/oak_fence_gate_open",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
1,
4,
18
],
"properties": {
"facing": "west",
"in_wall": "false",
"open": "true",
"powered": "false"
},
"state_id": 10401
},
{
"block": "minecraft:iron_bars",
"models": [
{
"model": "minecraft:block/iron_bars_post_ends",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side_alt",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
18
],
"properties": {
"east": "false",
"north": "true",
"south": "true",
"waterlogged": "false",
"west": "false"
},
"state_id": 9711
},
{
"block": "minecraft:cobweb",
"models": [
{
"model": "minecraft:block/cobweb",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
22
],
"properties": {},
"state_id": 2362
},
{
"block": "minecraft:grindstone",
"models": [
{
"model": "minecraft:block/grindstone",
"rotations": [
1,
3,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
22
],
"properties": {
"face": "wall",
"facing": "west"
},
"state_id": 24135
},
{
"block": "minecraft:ladder",
"models": [
{
"model": "minecraft:block/ladder",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
22
],
"properties": {
"facing": "west",
"waterlogged": "false"
},
"state_id": 7312
},
{
"block": "minecraft:amethyst_cluster",
"models": [
{
"model": "minecraft:block/amethyst_cluster",
"rotations": [
1,
1,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
22
],
"properties": {
"facing": "east",
"waterlogged": "false"
},
"state_id": 26764
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone_mirrored",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
26
],
"properties": {},
"state_id": 1
}
],
"model_quads": 179,
"movement_ticks": 0,
"os": "linux",
"player_absorption": null,
"player_dead": null,
"player_exhaustion": null,
"player_fall_distance": null,
"player_food": null,
"player_food_timer": null,
"player_health": null,
"player_hurt_cooldown": null,
"player_on_ground": null,
"player_position": null,
"player_saturation": null,
"player_velocity": null,
"presented_frames": 30,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native resident-scene renderer with inspection camera and optional fixed-rate dry walking test; full gameplay remains unfinished",
"sprite_layers": 18,
"visible_model_faces": 5991,
"walking": false,
"window_size": [
1280,
720
],
"world_revision": 0,
"native_scene_culling": {
"blocks": 10919,
"culled_faces": 59636,
"visible_faces": 5991
},
"native_selection": {
"matched_placements": 16,
"selected_parts": 20,
"client_jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "a2ff1c890d6f3a5292c3a9402f02ca5404a993dc117853b25cbe64ac92b76d30",
"scope": "Actual native registry states, blockstate dispatch, tagged root baking and legacy collection using state.getSeed(position). All 16 featured placements match model names/transforms. An independently constructed native scene also matches total occupied blocks and visible/culled model faces using native parent resolution, rotated culling directions and Block.shouldRenderFace. No shader/pixel parity claim."
},
"resource_files": {
"files": 5590,
"sha256": "62f859d4d21b82158ab73e26cfa4973d58ab5926ab63d71c70c7a4d173502b7b"
},
"executable_sha256": "ac49c3978800a25550c082b05c1a56fc73a8d806ee1bdb0e4825a02051bf802b",
"resource_manifest_sha256": "92a51de578be0e7c37d21e94caa3f22503f7d88b73827a5fce109b1b889e5d18",
"sources": {
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "6884c7209f007ab9ee742b9c3c73828cfa1c6753d35b5fe25a87cab5955b33f8",
"tools/test_native_client.py": "6c615fed67fd7bcf09b3184216e08a82012049880a0d4da7c89f86553090cbda",
"crates/horizon-client/Cargo.toml": "d56524457d761c2613c0699b20e21ad6977d93e009d59ef150bbd9fc20d7a025",
"crates/horizon-assets/Cargo.toml": "2f2cffacec0b4e22dd7cb032d594289bc51c94ae6cc4e985fee3e310f441d751",
"crates/horizon-client/src/assets.rs": "e595afa610e0425d0b3ad694218794bf9e680e46ae80f3925c278ef1a823c914",
"crates/horizon-client/src/camera.rs": "d386a56ca8fb3b37ba2b2ed9d09342f61b409a575bb21590e934120b4ccebfa6",
"crates/horizon-client/src/clock.rs": "4851ada3e8e65d935eda8c0b57d3b51233b34f74aab4f040fd53db0e0d40b8df",
"crates/horizon-client/src/collisions.rs": "112286b07c4cd11b36da8b6799e0e069e69dfddf9a8a3f9ce36dcb282c791d67",
"crates/horizon-client/src/health.rs": "b5e2d3cde4bd58d906e6f6d47cd756ed23aa6706c71b10c3aedde30c11806403",
"crates/horizon-client/src/hunger.rs": "01d8a35f570f2a0991ac17a078f2066a5a83037a728158585765723d208b4611",
"crates/horizon-client/src/input.rs": "55b259ca6425c502270e7abc4d3ae1b3838633e2bd77d3817c6e00d9143a2beb",
"crates/horizon-client/src/landing.rs": "b9d0ecc5ec60a09d75ab9fe778e0a2e5bbb36fd8364a7ce996405f3dc9cb3b9f",
"crates/horizon-client/src/lib.rs": "bc1d0a7e42c11a9090abfebc4ed1f595415dd8b72a6a04b63c765b0deba29f6f",
"crates/horizon-client/src/main.rs": "aeb6b5220f8b89a1c9e85bf23fa2bbbafbc876108e59a222d383ad6e6fa238a6",
"crates/horizon-client/src/mesh.rs": "4ac8d85b30f599b37a98b92adcc016b16434816b93c401bd39b8215f591f9330",
"crates/horizon-client/src/models/catalog.rs": "620103719167fc9ab76e730d68eeacb50014e95b7ad209ae7adf2cbbe69f70f7",
"crates/horizon-client/src/models/cube.rs": "1067229f9dd9b276950bf7ec0c5f67061ce3d40a21932dca8034b9748e7439a4",
"crates/horizon-client/src/models.rs": "98dd3b969947c2b297862a934e6235067ddc1fc8cda5adcc6276d19014d4b048",
"crates/horizon-client/src/motion.rs": "833d7e14ee37f82bef05094c1f0fa681b5ead3b3bcf4e915fbd5bc94e46dd7ad",
"crates/horizon-client/src/render.rs": "75cb40c257cf61e51009d292a06cd96532f59320b12ed7c3a509bbdbe1accdd4",
"crates/horizon-client/src/sprites.rs": "292f844a31f6e8884008df9630e2b8862db1acfbc4640cc07d526e25f21f0bc5",
"crates/horizon-client/src/world.rs": "0333ecf3e18ccc63117295feb2cf77661462ba13feb293eeec667c12811423b5",
"crates/horizon-client/src/world.wgsl": "972a58ccb34e9965515adbb30c47a93fceca5b742390db6d9f69cba1ec31f559",
"crates/horizon-assets/src/animation.rs": "ebbf7952146a0e66b41396174492f5702627170b03a57e6cd5a45c97a08c975e",
"crates/horizon-assets/src/bake/transform.rs": "a95e658fef85b21bcb2f9f7512f98f98d57022d62c1199885b7133beae35a09d",
"crates/horizon-assets/src/bake.rs": "f55dda6b6cee5ac6e65a8ee4837fdd2c6674437d59e59b4c45718f6324d4a4d5",
"crates/horizon-assets/src/blockstate/bind.rs": "6278962e55c9786bba8184bdf2939af9c6e3b9002b08c3022129964b49a60009",
"crates/horizon-assets/src/blockstate/choice.rs": "5a66c8b9833e2f19dd8b0773f3593d97ff5941d3c5b773896b98049efa1395ba",
"crates/horizon-assets/src/blockstate.rs": "a4299dfd7adaeb4173982ffaa8e9c9eda2925739ae579a714193c99da2e7ce56",
"crates/horizon-assets/src/json.rs": "99fe8af4fbf5d4eed408a92e829ac1a39597a0d92471a6bff73771fad9c830a8",
"crates/horizon-assets/src/lib.rs": "e39f21c59a2c3e1c53d977b29bd5e0638e5fc41d86ff0fcc1882a6d90fd961e4",
"crates/horizon-assets/src/model.rs": "57ddb3d65e88e7a8aa22c62bc298a2dae7f4e994326a873a31f06c0f36ed051b",
"crates/horizon-assets/src/resolve.rs": "3927ac926cdcbd7d334901cc32d0ecc1e498b1bec98f76a46bca6d4964c13541",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaGallerySelectionOracle.java": "dc5433f1ce1de629b30cb70f031a43a691fc1df1fb218ce23de89769c164d562",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCuboidModelOracle.java": "7526f20513c549483122ab0d5ad24b9e87f38dc2f6aae55addd701a91ac85e43",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
"tools/test_model_baking_parity.py": "392ffec44918fb91740ca4a1316d684480d39f14bd34d46175f7f44946d15bd7",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"tools/prepare_native_client.py": "159c12846058954a35ce86d415dc12fc89a6f11d46d21d1616ee686b7af4eee4",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/border.rs": "1386f8080521231d05ba3e84d94a3e1d5218d35ccb3d5e9fe2bbb05a8739e573",
"crates/horizon-core/src/geometry/mod.rs": "c650386f9860e44a96c55f18c8f1428ca715fcb0bc5c2434db5b1caa43df27fe",
"crates/horizon-core/src/geometry/movement.rs": "bcfb452752940ce53ae6dc267a3c4eb29459046a063c1f884684ab4f4bd0068f",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/Cargo.toml": "18bbad377a8047e4d4ecd0fc87d83d46d1c0f1ce2b8c47bbe64633e7b4420b57",
"crates/horizon-world/src/active_effect_tick.rs": "88f19cfc3532c47a58c646bb3e9d99ff239a900752302b6a444dda3013e95cbf",
"crates/horizon-world/src/active_effects.rs": "daaf352a69511a7d69fb329997f783b86585e486e0379c84ab0a55641771646c",
"crates/horizon-world/src/attribute_health.rs": "1420a80787d10dd2e2954a3ee6193ff313289d00c7c78ca26ece8bafa21f4380",
"crates/horizon-world/src/attribute_map.rs": "3d871cd530f5c035e0753f3ba065c2b9c5b49cdee75d4119f7dd584b22af67e6",
"crates/horizon-world/src/attribute_updates.rs": "4cb322d75a50d222298994607097ba7f7e6674021128fa02a98a74c057ad05f1",
"crates/horizon-world/src/attributes/entity.rs": "64ac99682a3aa06b1fb94b776b47794234c76b1cf70f1f54933d51e545e69279",
"crates/horizon-world/src/attributes/live.rs": "8198c45134f69135d48ef203e71b6e702529568fd1ed9174d0aa843570bbf9e7",
"crates/horizon-world/src/attributes/mod.rs": "5c2fcbbde58c19261874d227ea98332f00336c9fa53446da2e9adb6aa64a5e5a",
"crates/horizon-world/src/attributes/operation_map.rs": "fc5bc8921d78ea6721a2eaa915e67483e2a33683927467bdba24f0492356ad97",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "39207247f2f6dd3ddc77640229044246f91b32054563f88a435f1bd92ad2092c",
"crates/horizon-world/src/block_collision_scan.rs": "20802862364c110ff85eeaf48606596a8468b83768dda46b412d337958790b41",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_entity_push.rs": "12ee91bf604946234b24a0da4333f07d1830ab9743a422d41c8d0afac7d49cfd",
"crates/horizon-world/src/block_landing.rs": "33083fe39266fbefec1b3ea1a19f2afc609791d189da247c895e116ad6eb266a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/blocking_item_damage.rs": "afea3cb5761e8b82ee4d9bb4ef3c6fd10182a324dbaec99e6c9ebfac255dda09",
"crates/horizon-world/src/blocking_rules.rs": "83c5e2105cec56a90182ce582e1c67ade2b189be6de1a34d08035000cc07c492",
"crates/horizon-world/src/bundle_weight.rs": "a0e7b0587ab5d46cd55588f25d55a088b7a4725099c13ba6df146957be36014c",
"crates/horizon-world/src/chunk.rs": "795895284d6e615bcb2082fceacdfe7025c152fb2934bb43f598f17a00ab46f1",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/climbing.rs": "6cd2f919872ff0b726effddaa57eccb805b8eae43f9d01144716010853891879",
"crates/horizon-world/src/collision.rs": "a749794d5c27ccd6c0d964ad02f9dc31d49d9f4fe4b7366cd4bd8155e681b00b",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/combat_rules.rs": "01131f70d1acdd96a910e7f96deaa12e51a1e3bb9208085f04e3ec7b657d3cd4",
"crates/horizon-world/src/component_durability.rs": "37a46e184f95bc5027e2b9af72ff52f729ad03601d08e1827f181fca383a35af",
"crates/horizon-world/src/component_patch.rs": "f6f8992f241dfb25e012a06a7ba3fecab8d958686dddd096595a4806e56f0ab3",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/consumable.rs": "ba3575cb85866cb940f33a1ac86455d71cf0cc6395b848588a8ee1fe33f5c326",
"crates/horizon-world/src/consume_effect.rs": "03f2aac6879ce133347d42f6f6667d62c06d956ff9faac5dc14182a788b6a236",
"crates/horizon-world/src/damage_immunity.rs": "fd39c41124d694e755cf7faadcf93c636df4042c78ec345092a856b5f952dbcf",
"crates/horizon-world/src/damage_reduction.rs": "f5a599ab11e077f526237018aeda803ea3c420c5b35c78ae9d85e32267e23bf3",
"crates/horizon-world/src/damage_source.rs": "24945e397a926d34695652980923609e4723e02fe6b6e56d4aaf673e45d759f7",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/edge_backoff.rs": "5259d7aa44e64f88351d1556c44dd0edcad3b400a099c659755792efba7b5773",
"crates/horizon-world/src/effect_attribute_modifiers.rs": "0bc7ab63d0f3f34a7133fe20364cae0ec1fdbd3773cba90faa1f08e0d63a5646",
"crates/horizon-world/src/effect_notifications.rs": "ea66bfa010d6d44aee97b9672902f41cd99d0d80239f41c6d4eae5c9a9472d3d",
"crates/horizon-world/src/effect_particles.rs": "a42dc4ec55929dce1db0f22f8816ecf7621fdce1cd2ac0c90f6a57fea4e0afd2",
"crates/horizon-world/src/effect_sync.rs": "1388d4a69b42a14ff4cd474f5e36f0fad5a2874031e64fa2b19b2ea179deed2b",
"crates/horizon-world/src/entity_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"crates/horizon-world/src/entity_fluid.rs": "02991040ae879a8914f09913128a3506e9e7a1ca33ffc0a22b5729a168346600",
"crates/horizon-world/src/entity_fluid_tick.rs": "4f9e070b88a73c98a4e2e659360ddd6edee636bca29377f1ea9011fd5a556f64",
"crates/horizon-world/src/entity_move.rs": "a40a50d3e841625a75d4cfbb7c2630ab5a62a574456567e7234f401ae8441b32",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/extra_items.rs": "6eba0a0c795d5fd841d31471708e78324b4852adebb2e6ed700dcc0caab668cd",
"crates/horizon-world/src/fall_damage.rs": "8c28e2933493569fe05dea22332024287d28b0746b514dd465681040b003296b",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/fluid_box.rs": "b586af72b1c04a9354fe66205c28dc8b619e205ab9ea19a68232722e4b6e96c1",
"crates/horizon-world/src/fluid_flow.rs": "7c7e486b5c565df3602799648b37b879bcca51414337f607962d6c7951b86d05",
"crates/horizon-world/src/fluid_occupancy.rs": "26037579caeef6c8a5a2bde2c3d142d278558b76d77ebff401cee6e35f2ea961",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/food.rs": "3cf416fa632a5555a8116bb528a6e80bcb5b6b754b0748b4959ed310102418d3",
"crates/horizon-world/src/food_properties.rs": "0926fa3f3bc3d0608c45d02f564355825ca3c3526a82bf9c1375c7a191fa5e12",
"crates/horizon-world/src/food_storage.rs": "58c433801a285efcc973638c11d694a41f85dc96703a3a7ce8d3673f3eb31d52",
"crates/horizon-world/src/free_space.rs": "913536bf4c85ddeeb378d76d1b5110b4175f5688e1a749f32fe6a6d86fbb478e",
"crates/horizon-world/src/ground_support.rs": "3e371d74ecede4d30beef0a7e8a2ee33463584a5b1ed3d852b394efcce1ffbe0",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/identifier.rs": "37c921889c4f5d91f7c09ab2ee68d1a5e5a3c4fb1c49b4b189c987b4615fd2d6",
"crates/horizon-world/src/interaction_shapes.rs": "f321284ddab440a394372b6dedc8b5cc29a653c0745251a9e96c650f21c33dea",
"crates/horizon-world/src/inventory_pickup.rs": "ea830c7916e7f2d95c6db7ef48be1e876e6ebafcb438e47fc72f9a5bd7c37d07",
"crates/horizon-world/src/inventory_tick.rs": "293a3d57a1689337cfd58e5a73dcdbed4cb360f94d98ff5458f0df92de387365",
"crates/horizon-world/src/inventory_use.rs": "6a6c2ecc73c83dda4cd798c0304df12ace6096eb110d899f4f0c7ffd852bf001",
"crates/horizon-world/src/item_after_use.rs": "2b6598ce5b7b304dea2c8057b4a1eb6530264ac4d0546c3da0c76deed9609da5",
"crates/horizon-world/src/item_blocking.rs": "f6eee0d6d177cc3148960122327ba1b459a2f0e85241c1d9a3e40f0b8c169296",
"crates/horizon-world/src/item_cooldowns.rs": "7b625868509ab3c51e72db0ac714bb0e7ec5e2610d37271005a1a737f4d14431",
"crates/horizon-world/src/item_durability.rs": "9fdf835e5c7bd0e1dd63ef2ba0076b770cdd4d6d14cdcd11de27690f0702f94e",
"crates/horizon-world/src/item_particles.rs": "861b14f65adb9b14f8158fe9f0b7128beac3df8107b1337c31b8b9b49434ba3f",
"crates/horizon-world/src/item_stack_refs.rs": "18d3ca85cac0daf59200857513761359e5690f719cb3f7f64ae552f0c4169ea3",
"crates/horizon-world/src/item_stack_storage.rs": "b4dcb83dcaa346848c5484161feb3e2cf08e83f7793d7ed83be25b14b9d12884",
"crates/horizon-world/src/item_template.rs": "dc80025215d1867e656924ea2a9d273aacbcaea21293d986ba42d0004ee93b69",
"crates/horizon-world/src/item_use.rs": "b1c79428986efbf9dd5ede703a39eb387fb6dcc7d9950f0e49243a353a5b8070",
"crates/horizon-world/src/item_use_catalog.rs": "a9b53d2e816583239a75c3c61e78dacc5e3b27dee595be34b1c7fa169f17a571",
"crates/horizon-world/src/item_use_lifecycle.rs": "4639b70440cf811e79de09c48a3e035143fcb6be8a64c2f61b10ae55a2f133b7",
"crates/horizon-world/src/item_use_start.rs": "a84092dfb8b8f0a89d0928bb2f8ac252bd9bfd3f8d74fce1a7f7a5b3c3f4f50b",
"crates/horizon-world/src/java_hash_map.rs": "955502e696d7b0b33bae3ec485c8eb1453a8956116aad68226cf1fc67d60babc",
"crates/horizon-world/src/lib.rs": "e25b3543c07f31c2a9d23d811792de9a33290263c7c7445549a0682f6935d8a5",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/live_attribute_updates.rs": "778171faaaf7077deb0b62c4cc1db16351eba41adb8bb07656ba65e827056199",
"crates/horizon-world/src/living_air.rs": "b2de36bb50bed15e2808fe4a874fcef07f9fea0d2c96385b7b5e8ee9560d4442",
"crates/horizon-world/src/living_damage.rs": "2b448209629b9bf2e678d667ad0d6c7fa22146892dd106b169d96b31b0df12bb",
"crates/horizon-world/src/living_fall.rs": "da0f176f4731e1c86e08bfeee8167742fd1b86380ff0e9304c13c1ce3f1c67ab",
"crates/horizon-world/src/living_fluid.rs": "d7cd914cfb2a1f4876ce0ae95e999bf0ff1af732cce3ab4a3aa2d1ab881c7339",
"crates/horizon-world/src/living_health.rs": "221659f85552424e937d503bba6d8003006b106ced042b32d3a6f6cc23e12ed0",
"crates/horizon-world/src/living_hurt.rs": "844239ad7d15c39629bb3cfc06ebae6d1cff20b7627468f26e0ee8dff3abdcb8",
"crates/horizon-world/src/living_landing.rs": "8bca4eb7977abc2b14fb7174be4ea355352106ea1e76ff5f3ad8696969d9eefd",
"crates/horizon-world/src/living_motion.rs": "56f8c84cfbe205a7a69912d5f76b52ef1efca149c1b6801d4684e25fb179aeb9",
"crates/horizon-world/src/living_use_flags.rs": "826f4fdeba7e208368cbbf910fa408db0afbc6442d842d178a70fae53e0d0ea6",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/movement_emission.rs": "76e7d6f5b19c94676190f54389f9c4ce12cf89945ccfcb9c750de473223e7753",
"crates/horizon-world/src/movement_properties.rs": "6f01ab920b376a13f5ae12c3718f4dd067e1dff2b829585af00a8b2100f3775d",
"crates/horizon-world/src/movement_restitution.rs": "04b4fe0947e7e52576145bd8ed15920278e8a538afcc74d125eaca513dffa0ef",
"crates/horizon-world/src/movement_statistics.rs": "fe28061e29c41f8f399d29cce8c468a63854613702b5aa525c0f0fd98cb87f9a",
"crates/horizon-world/src/movement_support.rs": "02d85cf572847f2e60b5a7f9d60b856888a67b3c1f4df03e81998c66fdf874be",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/object_open_map.rs": "b4934a9cc38df93ed206ab0bc3bbc4499acd8e40b41b7def7d47067b7170065b",
"crates/horizon-world/src/object_open_set.rs": "d3e0373bf1b652dd054345d5a8e25ec828e06dd7cad65aada35163c95df4e637",
"crates/horizon-world/src/piston_movement.rs": "7a3fd2549a582b5f3a5c21aa05d67d944d62ca1105856679e100ac5b44e9a52f",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/player_equipment.rs": "1fa8c53e67624c4641246249d79a800a28a4858c62482bd880b4e3b866b936ef",
"crates/horizon-world/src/player_food.rs": "f188dc110745bcc7acc15e6c521db943b06b404f69cd251bf74a345516070304",
"crates/horizon-world/src/player_health.rs": "8155b315453c569db2fbe46228886c5881d1fd55eb095c5849e69bdb500ba2bd",
"crates/horizon-world/src/player_hurt.rs": "99c9bbd8587ec2dc287806049897b8034d2f5349ad47fc497b70d54148844a36",
"crates/horizon-world/src/player_inventory.rs": "f4f67d8312793f25930626c4ac06db688fcf2e2292d6675071d105fb1708d952",
"crates/horizon-world/src/player_travel.rs": "6841a677a900495eb6223031ef3ebe8d859bb98908dda0e2209e5f28839dc593",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/registry_collision_scan.rs": "97cc950a9a4ba387b78e368f36d595f8664ab7730d132900d220ce23b92826ea",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/registry_fluid.rs": "b8959c05850cfeaaad1e4de8ca7c7d0d6ac56da9b2c1de3ebefa5871a11ed35e",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/server_player_combat.rs": "0a94885c4b7a0d294ba7f4cee18b96ee59649b50112988250b53cc224059a979",
"crates/horizon-world/src/server_player_damage.rs": "29af22dec321fe01776cee5334f050c5bc3e27a688f99c8c3da4c0ad8bc8254e",
"crates/horizon-world/src/simple_container.rs": "0fedbc7e974b1db79b88bd6aff977654189a5d553cf42852fe8bf0885cf90b30",
"crates/horizon-world/src/status_effect.rs": "588bfcf4d93f50be86cb89545bd5c431edbc71771f704ff55cb52906b1964c37",
"crates/horizon-world/src/stored_consume.rs": "621a52c9fba447c393e561f881a16cf1f97d336e3a0ce493725ef51e2db12ffd",
"crates/horizon-world/src/stored_effect_attributes.rs": "c79f6a52d3cfee1a5288225bf8fa91a7bf3ea8cd21faea9f6dc748ecefc6309a",
"crates/horizon-world/src/suffocation.rs": "bed219dd5bbab6263b98fbe3d0eb512cb96c52ae847210efe49514d05f22f11e",
"crates/horizon-world/src/swimming.rs": "49d2dae13c109b37ff832cde98a857944ff45247b864a527b9c4f03ecca7a7b7",
"crates/horizon-world/src/synced_floats.rs": "0152f2752bafaf68769d56dbc88494a976496a680c6b113d6b48a446158ba072",
"crates/horizon-world/src/synced_values.rs": "a1d4b53ae77d1899ba2b4ead67c9ec1e3c96615558e446f9d0760c1b4a520169",
"crates/horizon-world/src/teleport_consume.rs": "d6a53bbb6ac4dbbd4c0591d0646017898a95beb8ef093dc5d81b9833963be6c3",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/use_remainder.rs": "f555335afeca7970888131a6da2f5a614a73253b631185d1ba804593a349535e",
"crates/horizon-world/src/view_direction.rs": "e18120ae26dc5cf702b29fc4c8487088bab133c8ce5abce01226833fafb0d5a4",
"crates/horizon-world/src/water_splash.rs": "e0461ae1b2e8c851cca6e3251a188334293292201d7f80dc9e7d60fd1815f4d1",
"crates/horizon-world/src/world_movement.rs": "f8fe9e34f2395d2a04c839d1c8ba78e09ce493c26de6f6e4e237b9c19c061da5",
"crates/horizon-world/src/world_ray.rs": "879bdbbe12f56deb705cc183933431489e840b71eade40c33391eed5949c2e61",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "74e4110fb19c4c4047192fd65c38015b8afc7f9fc50404d75380b5063808148c",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f"
}
}
@@ -1,807 +0,0 @@
{
"adapter": {
"backend": "Vulkan",
"device": 0,
"device_type": "Cpu",
"name": "llvmpipe (LLVM 21.1.8, 256 bits)",
"vendor": 65541
},
"animated_sprites": 1,
"animation_uploads": 1,
"arch": "x86_64",
"camera_pitch": -0.3839724354387525,
"camera_position": [
25.0,
18.0,
25.0
],
"camera_yaw": -2.356194490192345,
"collision_camera": false,
"culled_model_faces": 59636,
"elapsed_seconds": 0.545908777,
"error": null,
"fall_damage_requests": 0,
"last_requested_fall_damage": null,
"merged_quads": 3169,
"mesh_revision": 0,
"model_blocks": 10919,
"model_gallery": [
{
"block": "minecraft:oak_stairs",
"models": [
{
"model": "minecraft:block/oak_stairs_inner",
"rotations": [
2,
3,
0
],
"uv_lock": true
}
],
"position": [
-7,
4,
14
],
"properties": {
"facing": "north",
"half": "top",
"shape": "inner_left",
"waterlogged": "false"
},
"state_id": 5466
},
{
"block": "minecraft:stone_slab",
"models": [
{
"model": "minecraft:block/stone_slab_top",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
14
],
"properties": {
"type": "top",
"waterlogged": "false"
},
"state_id": 15250
},
{
"block": "minecraft:anvil",
"models": [
{
"model": "minecraft:block/anvil",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
14
],
"properties": {
"facing": "east"
},
"state_id": 12965
},
{
"block": "minecraft:torch",
"models": [
{
"model": "minecraft:block/torch",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
14
],
"properties": {},
"state_id": 4926
},
{
"block": "minecraft:lantern",
"models": [
{
"model": "minecraft:block/lantern",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
18
],
"properties": {
"hanging": "false",
"waterlogged": "false"
},
"state_id": 24197
},
{
"block": "minecraft:oak_fence",
"models": [
{
"model": "minecraft:block/oak_fence_post",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
0,
0
],
"uv_lock": true
},
{
"model": "minecraft:block/oak_fence_side",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
-3,
4,
18
],
"properties": {
"east": "true",
"north": "true",
"south": "false",
"waterlogged": "false",
"west": "false"
},
"state_id": 8642
},
{
"block": "minecraft:oak_fence_gate",
"models": [
{
"model": "minecraft:block/oak_fence_gate_open",
"rotations": [
0,
1,
0
],
"uv_lock": true
}
],
"position": [
1,
4,
18
],
"properties": {
"facing": "west",
"in_wall": "false",
"open": "true",
"powered": "false"
},
"state_id": 10401
},
{
"block": "minecraft:iron_bars",
"models": [
{
"model": "minecraft:block/iron_bars_post_ends",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side",
"rotations": [
0,
0,
0
],
"uv_lock": false
},
{
"model": "minecraft:block/iron_bars_side_alt",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
18
],
"properties": {
"east": "false",
"north": "true",
"south": "true",
"waterlogged": "false",
"west": "false"
},
"state_id": 9711
},
{
"block": "minecraft:cobweb",
"models": [
{
"model": "minecraft:block/cobweb",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
22
],
"properties": {},
"state_id": 2362
},
{
"block": "minecraft:grindstone",
"models": [
{
"model": "minecraft:block/grindstone",
"rotations": [
1,
3,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
22
],
"properties": {
"face": "wall",
"facing": "west"
},
"state_id": 24135
},
{
"block": "minecraft:ladder",
"models": [
{
"model": "minecraft:block/ladder",
"rotations": [
0,
3,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
22
],
"properties": {
"facing": "west",
"waterlogged": "false"
},
"state_id": 7312
},
{
"block": "minecraft:amethyst_cluster",
"models": [
{
"model": "minecraft:block/amethyst_cluster",
"rotations": [
1,
1,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
22
],
"properties": {
"facing": "east",
"waterlogged": "false"
},
"state_id": 26764
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-7,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone_mirrored",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
-3,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
0,
0
],
"uv_lock": false
}
],
"position": [
1,
4,
26
],
"properties": {},
"state_id": 1
},
{
"block": "minecraft:stone",
"models": [
{
"model": "minecraft:block/stone",
"rotations": [
0,
2,
0
],
"uv_lock": false
}
],
"position": [
5,
4,
26
],
"properties": {},
"state_id": 1
}
],
"model_quads": 179,
"movement_ticks": 0,
"os": "linux",
"player_absorption": null,
"player_dead": null,
"player_exhaustion": null,
"player_fall_distance": null,
"player_food": null,
"player_food_timer": null,
"player_health": null,
"player_hurt_cooldown": null,
"player_on_ground": null,
"player_position": null,
"player_saturation": null,
"player_sprint_trigger": null,
"player_sprinting": null,
"player_velocity": null,
"presented_frames": 30,
"project": "Horizon",
"resident_chunks": 9,
"schema": 1,
"scope": "Native resident-scene renderer with inspection camera and optional fixed-rate dry walking test; full gameplay remains unfinished",
"sprint_distance_cm": 0,
"sprint_ticks": 0,
"sprite_layers": 18,
"visible_model_faces": 5991,
"walk_distance_cm": 0,
"walking": false,
"window_size": [
1280,
720
],
"world_revision": 0,
"native_scene_culling": {
"blocks": 10919,
"culled_faces": 59636,
"visible_faces": 5991
},
"native_selection": {
"matched_placements": 16,
"selected_parts": 20,
"client_jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "a2ff1c890d6f3a5292c3a9402f02ca5404a993dc117853b25cbe64ac92b76d30",
"scope": "Actual native registry states, blockstate dispatch, tagged root baking and legacy collection using state.getSeed(position). All 16 featured placements match model names/transforms. An independently constructed native scene also matches total occupied blocks and visible/culled model faces using native parent resolution, rotated culling directions and Block.shouldRenderFace. No shader/pixel parity claim."
},
"resource_files": {
"files": 5590,
"sha256": "62f859d4d21b82158ab73e26cfa4973d58ab5926ab63d71c70c7a4d173502b7b"
},
"executable_sha256": "632eb61d13b3274d5c991f2f2daffd56891abf472b99085cf04f9237b5f21f28",
"resource_manifest_sha256": "92a51de578be0e7c37d21e94caa3f22503f7d88b73827a5fce109b1b889e5d18",
"sources": {
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "6884c7209f007ab9ee742b9c3c73828cfa1c6753d35b5fe25a87cab5955b33f8",
"tools/test_native_client.py": "6c615fed67fd7bcf09b3184216e08a82012049880a0d4da7c89f86553090cbda",
"crates/horizon-client/Cargo.toml": "d56524457d761c2613c0699b20e21ad6977d93e009d59ef150bbd9fc20d7a025",
"crates/horizon-assets/Cargo.toml": "2f2cffacec0b4e22dd7cb032d594289bc51c94ae6cc4e985fee3e310f441d751",
"crates/horizon-client/src/assets.rs": "e595afa610e0425d0b3ad694218794bf9e680e46ae80f3925c278ef1a823c914",
"crates/horizon-client/src/camera.rs": "d386a56ca8fb3b37ba2b2ed9d09342f61b409a575bb21590e934120b4ccebfa6",
"crates/horizon-client/src/clock.rs": "4851ada3e8e65d935eda8c0b57d3b51233b34f74aab4f040fd53db0e0d40b8df",
"crates/horizon-client/src/collisions.rs": "112286b07c4cd11b36da8b6799e0e069e69dfddf9a8a3f9ce36dcb282c791d67",
"crates/horizon-client/src/health.rs": "b5e2d3cde4bd58d906e6f6d47cd756ed23aa6706c71b10c3aedde30c11806403",
"crates/horizon-client/src/hunger.rs": "01d8a35f570f2a0991ac17a078f2066a5a83037a728158585765723d208b4611",
"crates/horizon-client/src/input.rs": "55b259ca6425c502270e7abc4d3ae1b3838633e2bd77d3817c6e00d9143a2beb",
"crates/horizon-client/src/landing.rs": "b9d0ecc5ec60a09d75ab9fe778e0a2e5bbb36fd8364a7ce996405f3dc9cb3b9f",
"crates/horizon-client/src/lib.rs": "d34c467ee87b869c6645052f286305e218c80ba258603317e9d951f1b4c5345d",
"crates/horizon-client/src/main.rs": "14a459150f8dcc0a9bda2d91138e7e232d1e33e7b5f15fa17af8228653cbca2a",
"crates/horizon-client/src/mesh.rs": "4ac8d85b30f599b37a98b92adcc016b16434816b93c401bd39b8215f591f9330",
"crates/horizon-client/src/models/catalog.rs": "620103719167fc9ab76e730d68eeacb50014e95b7ad209ae7adf2cbbe69f70f7",
"crates/horizon-client/src/models/cube.rs": "1067229f9dd9b276950bf7ec0c5f67061ce3d40a21932dca8034b9748e7439a4",
"crates/horizon-client/src/models.rs": "98dd3b969947c2b297862a934e6235067ddc1fc8cda5adcc6276d19014d4b048",
"crates/horizon-client/src/motion.rs": "1949f35da0e65ee71c52f53a2faf22601fbbb43387fbd411d6c9281b2221bc42",
"crates/horizon-client/src/render.rs": "75cb40c257cf61e51009d292a06cd96532f59320b12ed7c3a509bbdbe1accdd4",
"crates/horizon-client/src/sprint.rs": "6f5ba5ea8e9a19872b26c1d7b5073e29549f2d820a0fe46e5450c9e7446e98b2",
"crates/horizon-client/src/sprites.rs": "292f844a31f6e8884008df9630e2b8862db1acfbc4640cc07d526e25f21f0bc5",
"crates/horizon-client/src/world.rs": "0333ecf3e18ccc63117295feb2cf77661462ba13feb293eeec667c12811423b5",
"crates/horizon-client/src/world.wgsl": "972a58ccb34e9965515adbb30c47a93fceca5b742390db6d9f69cba1ec31f559",
"crates/horizon-assets/src/animation.rs": "ebbf7952146a0e66b41396174492f5702627170b03a57e6cd5a45c97a08c975e",
"crates/horizon-assets/src/bake/transform.rs": "a95e658fef85b21bcb2f9f7512f98f98d57022d62c1199885b7133beae35a09d",
"crates/horizon-assets/src/bake.rs": "f55dda6b6cee5ac6e65a8ee4837fdd2c6674437d59e59b4c45718f6324d4a4d5",
"crates/horizon-assets/src/blockstate/bind.rs": "6278962e55c9786bba8184bdf2939af9c6e3b9002b08c3022129964b49a60009",
"crates/horizon-assets/src/blockstate/choice.rs": "5a66c8b9833e2f19dd8b0773f3593d97ff5941d3c5b773896b98049efa1395ba",
"crates/horizon-assets/src/blockstate.rs": "a4299dfd7adaeb4173982ffaa8e9c9eda2925739ae579a714193c99da2e7ce56",
"crates/horizon-assets/src/json.rs": "99fe8af4fbf5d4eed408a92e829ac1a39597a0d92471a6bff73771fad9c830a8",
"crates/horizon-assets/src/lib.rs": "e39f21c59a2c3e1c53d977b29bd5e0638e5fc41d86ff0fcc1882a6d90fd961e4",
"crates/horizon-assets/src/model.rs": "57ddb3d65e88e7a8aa22c62bc298a2dae7f4e994326a873a31f06c0f36ed051b",
"crates/horizon-assets/src/resolve.rs": "3927ac926cdcbd7d334901cc32d0ecc1e498b1bec98f76a46bca6d4964c13541",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaGallerySelectionOracle.java": "dc5433f1ce1de629b30cb70f031a43a691fc1df1fb218ce23de89769c164d562",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCuboidModelOracle.java": "7526f20513c549483122ab0d5ad24b9e87f38dc2f6aae55addd701a91ac85e43",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
"tools/test_model_baking_parity.py": "392ffec44918fb91740ca4a1316d684480d39f14bd34d46175f7f44946d15bd7",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"tools/prepare_native_client.py": "159c12846058954a35ce86d415dc12fc89a6f11d46d21d1616ee686b7af4eee4",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/border.rs": "1386f8080521231d05ba3e84d94a3e1d5218d35ccb3d5e9fe2bbb05a8739e573",
"crates/horizon-core/src/geometry/mod.rs": "c650386f9860e44a96c55f18c8f1428ca715fcb0bc5c2434db5b1caa43df27fe",
"crates/horizon-core/src/geometry/movement.rs": "bcfb452752940ce53ae6dc267a3c4eb29459046a063c1f884684ab4f4bd0068f",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/Cargo.toml": "18bbad377a8047e4d4ecd0fc87d83d46d1c0f1ce2b8c47bbe64633e7b4420b57",
"crates/horizon-world/src/active_effect_tick.rs": "88f19cfc3532c47a58c646bb3e9d99ff239a900752302b6a444dda3013e95cbf",
"crates/horizon-world/src/active_effects.rs": "daaf352a69511a7d69fb329997f783b86585e486e0379c84ab0a55641771646c",
"crates/horizon-world/src/attribute_health.rs": "1420a80787d10dd2e2954a3ee6193ff313289d00c7c78ca26ece8bafa21f4380",
"crates/horizon-world/src/attribute_map.rs": "3d871cd530f5c035e0753f3ba065c2b9c5b49cdee75d4119f7dd584b22af67e6",
"crates/horizon-world/src/attribute_updates.rs": "4cb322d75a50d222298994607097ba7f7e6674021128fa02a98a74c057ad05f1",
"crates/horizon-world/src/attributes/entity.rs": "64ac99682a3aa06b1fb94b776b47794234c76b1cf70f1f54933d51e545e69279",
"crates/horizon-world/src/attributes/live.rs": "8198c45134f69135d48ef203e71b6e702529568fd1ed9174d0aa843570bbf9e7",
"crates/horizon-world/src/attributes/mod.rs": "5c2fcbbde58c19261874d227ea98332f00336c9fa53446da2e9adb6aa64a5e5a",
"crates/horizon-world/src/attributes/operation_map.rs": "fc5bc8921d78ea6721a2eaa915e67483e2a33683927467bdba24f0492356ad97",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "39207247f2f6dd3ddc77640229044246f91b32054563f88a435f1bd92ad2092c",
"crates/horizon-world/src/block_collision_scan.rs": "20802862364c110ff85eeaf48606596a8468b83768dda46b412d337958790b41",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_entity_push.rs": "12ee91bf604946234b24a0da4333f07d1830ab9743a422d41c8d0afac7d49cfd",
"crates/horizon-world/src/block_landing.rs": "33083fe39266fbefec1b3ea1a19f2afc609791d189da247c895e116ad6eb266a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/blocking_item_damage.rs": "afea3cb5761e8b82ee4d9bb4ef3c6fd10182a324dbaec99e6c9ebfac255dda09",
"crates/horizon-world/src/blocking_rules.rs": "83c5e2105cec56a90182ce582e1c67ade2b189be6de1a34d08035000cc07c492",
"crates/horizon-world/src/bundle_weight.rs": "a0e7b0587ab5d46cd55588f25d55a088b7a4725099c13ba6df146957be36014c",
"crates/horizon-world/src/chunk.rs": "795895284d6e615bcb2082fceacdfe7025c152fb2934bb43f598f17a00ab46f1",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/climbing.rs": "6cd2f919872ff0b726effddaa57eccb805b8eae43f9d01144716010853891879",
"crates/horizon-world/src/collision.rs": "a749794d5c27ccd6c0d964ad02f9dc31d49d9f4fe4b7366cd4bd8155e681b00b",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/combat_rules.rs": "01131f70d1acdd96a910e7f96deaa12e51a1e3bb9208085f04e3ec7b657d3cd4",
"crates/horizon-world/src/component_durability.rs": "37a46e184f95bc5027e2b9af72ff52f729ad03601d08e1827f181fca383a35af",
"crates/horizon-world/src/component_patch.rs": "f6f8992f241dfb25e012a06a7ba3fecab8d958686dddd096595a4806e56f0ab3",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/consumable.rs": "ba3575cb85866cb940f33a1ac86455d71cf0cc6395b848588a8ee1fe33f5c326",
"crates/horizon-world/src/consume_effect.rs": "03f2aac6879ce133347d42f6f6667d62c06d956ff9faac5dc14182a788b6a236",
"crates/horizon-world/src/damage_immunity.rs": "fd39c41124d694e755cf7faadcf93c636df4042c78ec345092a856b5f952dbcf",
"crates/horizon-world/src/damage_reduction.rs": "f5a599ab11e077f526237018aeda803ea3c420c5b35c78ae9d85e32267e23bf3",
"crates/horizon-world/src/damage_source.rs": "24945e397a926d34695652980923609e4723e02fe6b6e56d4aaf673e45d759f7",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/edge_backoff.rs": "5259d7aa44e64f88351d1556c44dd0edcad3b400a099c659755792efba7b5773",
"crates/horizon-world/src/effect_attribute_modifiers.rs": "0bc7ab63d0f3f34a7133fe20364cae0ec1fdbd3773cba90faa1f08e0d63a5646",
"crates/horizon-world/src/effect_notifications.rs": "ea66bfa010d6d44aee97b9672902f41cd99d0d80239f41c6d4eae5c9a9472d3d",
"crates/horizon-world/src/effect_particles.rs": "a42dc4ec55929dce1db0f22f8816ecf7621fdce1cd2ac0c90f6a57fea4e0afd2",
"crates/horizon-world/src/effect_sync.rs": "1388d4a69b42a14ff4cd474f5e36f0fad5a2874031e64fa2b19b2ea179deed2b",
"crates/horizon-world/src/entity_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"crates/horizon-world/src/entity_fluid.rs": "02991040ae879a8914f09913128a3506e9e7a1ca33ffc0a22b5729a168346600",
"crates/horizon-world/src/entity_fluid_tick.rs": "4f9e070b88a73c98a4e2e659360ddd6edee636bca29377f1ea9011fd5a556f64",
"crates/horizon-world/src/entity_move.rs": "a40a50d3e841625a75d4cfbb7c2630ab5a62a574456567e7234f401ae8441b32",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/extra_items.rs": "6eba0a0c795d5fd841d31471708e78324b4852adebb2e6ed700dcc0caab668cd",
"crates/horizon-world/src/fall_damage.rs": "8c28e2933493569fe05dea22332024287d28b0746b514dd465681040b003296b",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/fluid_box.rs": "b586af72b1c04a9354fe66205c28dc8b619e205ab9ea19a68232722e4b6e96c1",
"crates/horizon-world/src/fluid_flow.rs": "7c7e486b5c565df3602799648b37b879bcca51414337f607962d6c7951b86d05",
"crates/horizon-world/src/fluid_occupancy.rs": "26037579caeef6c8a5a2bde2c3d142d278558b76d77ebff401cee6e35f2ea961",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/food.rs": "3cf416fa632a5555a8116bb528a6e80bcb5b6b754b0748b4959ed310102418d3",
"crates/horizon-world/src/food_properties.rs": "0926fa3f3bc3d0608c45d02f564355825ca3c3526a82bf9c1375c7a191fa5e12",
"crates/horizon-world/src/food_storage.rs": "58c433801a285efcc973638c11d694a41f85dc96703a3a7ce8d3673f3eb31d52",
"crates/horizon-world/src/free_space.rs": "913536bf4c85ddeeb378d76d1b5110b4175f5688e1a749f32fe6a6d86fbb478e",
"crates/horizon-world/src/ground_support.rs": "3e371d74ecede4d30beef0a7e8a2ee33463584a5b1ed3d852b394efcce1ffbe0",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/identifier.rs": "37c921889c4f5d91f7c09ab2ee68d1a5e5a3c4fb1c49b4b189c987b4615fd2d6",
"crates/horizon-world/src/interaction_shapes.rs": "f321284ddab440a394372b6dedc8b5cc29a653c0745251a9e96c650f21c33dea",
"crates/horizon-world/src/inventory_pickup.rs": "ea830c7916e7f2d95c6db7ef48be1e876e6ebafcb438e47fc72f9a5bd7c37d07",
"crates/horizon-world/src/inventory_tick.rs": "293a3d57a1689337cfd58e5a73dcdbed4cb360f94d98ff5458f0df92de387365",
"crates/horizon-world/src/inventory_use.rs": "6a6c2ecc73c83dda4cd798c0304df12ace6096eb110d899f4f0c7ffd852bf001",
"crates/horizon-world/src/item_after_use.rs": "2b6598ce5b7b304dea2c8057b4a1eb6530264ac4d0546c3da0c76deed9609da5",
"crates/horizon-world/src/item_blocking.rs": "f6eee0d6d177cc3148960122327ba1b459a2f0e85241c1d9a3e40f0b8c169296",
"crates/horizon-world/src/item_cooldowns.rs": "7b625868509ab3c51e72db0ac714bb0e7ec5e2610d37271005a1a737f4d14431",
"crates/horizon-world/src/item_durability.rs": "9fdf835e5c7bd0e1dd63ef2ba0076b770cdd4d6d14cdcd11de27690f0702f94e",
"crates/horizon-world/src/item_particles.rs": "861b14f65adb9b14f8158fe9f0b7128beac3df8107b1337c31b8b9b49434ba3f",
"crates/horizon-world/src/item_stack_refs.rs": "18d3ca85cac0daf59200857513761359e5690f719cb3f7f64ae552f0c4169ea3",
"crates/horizon-world/src/item_stack_storage.rs": "b4dcb83dcaa346848c5484161feb3e2cf08e83f7793d7ed83be25b14b9d12884",
"crates/horizon-world/src/item_template.rs": "dc80025215d1867e656924ea2a9d273aacbcaea21293d986ba42d0004ee93b69",
"crates/horizon-world/src/item_use.rs": "b1c79428986efbf9dd5ede703a39eb387fb6dcc7d9950f0e49243a353a5b8070",
"crates/horizon-world/src/item_use_catalog.rs": "a9b53d2e816583239a75c3c61e78dacc5e3b27dee595be34b1c7fa169f17a571",
"crates/horizon-world/src/item_use_lifecycle.rs": "4639b70440cf811e79de09c48a3e035143fcb6be8a64c2f61b10ae55a2f133b7",
"crates/horizon-world/src/item_use_start.rs": "a84092dfb8b8f0a89d0928bb2f8ac252bd9bfd3f8d74fce1a7f7a5b3c3f4f50b",
"crates/horizon-world/src/java_hash_map.rs": "955502e696d7b0b33bae3ec485c8eb1453a8956116aad68226cf1fc67d60babc",
"crates/horizon-world/src/lib.rs": "e25b3543c07f31c2a9d23d811792de9a33290263c7c7445549a0682f6935d8a5",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/live_attribute_updates.rs": "778171faaaf7077deb0b62c4cc1db16351eba41adb8bb07656ba65e827056199",
"crates/horizon-world/src/living_air.rs": "b2de36bb50bed15e2808fe4a874fcef07f9fea0d2c96385b7b5e8ee9560d4442",
"crates/horizon-world/src/living_damage.rs": "2b448209629b9bf2e678d667ad0d6c7fa22146892dd106b169d96b31b0df12bb",
"crates/horizon-world/src/living_fall.rs": "da0f176f4731e1c86e08bfeee8167742fd1b86380ff0e9304c13c1ce3f1c67ab",
"crates/horizon-world/src/living_fluid.rs": "d7cd914cfb2a1f4876ce0ae95e999bf0ff1af732cce3ab4a3aa2d1ab881c7339",
"crates/horizon-world/src/living_health.rs": "221659f85552424e937d503bba6d8003006b106ced042b32d3a6f6cc23e12ed0",
"crates/horizon-world/src/living_hurt.rs": "844239ad7d15c39629bb3cfc06ebae6d1cff20b7627468f26e0ee8dff3abdcb8",
"crates/horizon-world/src/living_landing.rs": "8bca4eb7977abc2b14fb7174be4ea355352106ea1e76ff5f3ad8696969d9eefd",
"crates/horizon-world/src/living_motion.rs": "56f8c84cfbe205a7a69912d5f76b52ef1efca149c1b6801d4684e25fb179aeb9",
"crates/horizon-world/src/living_use_flags.rs": "826f4fdeba7e208368cbbf910fa408db0afbc6442d842d178a70fae53e0d0ea6",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/movement_emission.rs": "76e7d6f5b19c94676190f54389f9c4ce12cf89945ccfcb9c750de473223e7753",
"crates/horizon-world/src/movement_properties.rs": "6f01ab920b376a13f5ae12c3718f4dd067e1dff2b829585af00a8b2100f3775d",
"crates/horizon-world/src/movement_restitution.rs": "04b4fe0947e7e52576145bd8ed15920278e8a538afcc74d125eaca513dffa0ef",
"crates/horizon-world/src/movement_statistics.rs": "fe28061e29c41f8f399d29cce8c468a63854613702b5aa525c0f0fd98cb87f9a",
"crates/horizon-world/src/movement_support.rs": "02d85cf572847f2e60b5a7f9d60b856888a67b3c1f4df03e81998c66fdf874be",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/object_open_map.rs": "b4934a9cc38df93ed206ab0bc3bbc4499acd8e40b41b7def7d47067b7170065b",
"crates/horizon-world/src/object_open_set.rs": "d3e0373bf1b652dd054345d5a8e25ec828e06dd7cad65aada35163c95df4e637",
"crates/horizon-world/src/piston_movement.rs": "7a3fd2549a582b5f3a5c21aa05d67d944d62ca1105856679e100ac5b44e9a52f",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/player_equipment.rs": "1fa8c53e67624c4641246249d79a800a28a4858c62482bd880b4e3b866b936ef",
"crates/horizon-world/src/player_food.rs": "f188dc110745bcc7acc15e6c521db943b06b404f69cd251bf74a345516070304",
"crates/horizon-world/src/player_health.rs": "8155b315453c569db2fbe46228886c5881d1fd55eb095c5849e69bdb500ba2bd",
"crates/horizon-world/src/player_hurt.rs": "99c9bbd8587ec2dc287806049897b8034d2f5349ad47fc497b70d54148844a36",
"crates/horizon-world/src/player_inventory.rs": "f4f67d8312793f25930626c4ac06db688fcf2e2292d6675071d105fb1708d952",
"crates/horizon-world/src/player_travel.rs": "6841a677a900495eb6223031ef3ebe8d859bb98908dda0e2209e5f28839dc593",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/registry_collision_scan.rs": "97cc950a9a4ba387b78e368f36d595f8664ab7730d132900d220ce23b92826ea",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/registry_fluid.rs": "b8959c05850cfeaaad1e4de8ca7c7d0d6ac56da9b2c1de3ebefa5871a11ed35e",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/server_player_combat.rs": "0a94885c4b7a0d294ba7f4cee18b96ee59649b50112988250b53cc224059a979",
"crates/horizon-world/src/server_player_damage.rs": "29af22dec321fe01776cee5334f050c5bc3e27a688f99c8c3da4c0ad8bc8254e",
"crates/horizon-world/src/simple_container.rs": "0fedbc7e974b1db79b88bd6aff977654189a5d553cf42852fe8bf0885cf90b30",
"crates/horizon-world/src/status_effect.rs": "588bfcf4d93f50be86cb89545bd5c431edbc71771f704ff55cb52906b1964c37",
"crates/horizon-world/src/stored_consume.rs": "621a52c9fba447c393e561f881a16cf1f97d336e3a0ce493725ef51e2db12ffd",
"crates/horizon-world/src/stored_effect_attributes.rs": "c79f6a52d3cfee1a5288225bf8fa91a7bf3ea8cd21faea9f6dc748ecefc6309a",
"crates/horizon-world/src/suffocation.rs": "bed219dd5bbab6263b98fbe3d0eb512cb96c52ae847210efe49514d05f22f11e",
"crates/horizon-world/src/swimming.rs": "49d2dae13c109b37ff832cde98a857944ff45247b864a527b9c4f03ecca7a7b7",
"crates/horizon-world/src/synced_floats.rs": "0152f2752bafaf68769d56dbc88494a976496a680c6b113d6b48a446158ba072",
"crates/horizon-world/src/synced_values.rs": "a1d4b53ae77d1899ba2b4ead67c9ec1e3c96615558e446f9d0760c1b4a520169",
"crates/horizon-world/src/teleport_consume.rs": "d6a53bbb6ac4dbbd4c0591d0646017898a95beb8ef093dc5d81b9833963be6c3",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/use_remainder.rs": "f555335afeca7970888131a6da2f5a614a73253b631185d1ba804593a349535e",
"crates/horizon-world/src/view_direction.rs": "e18120ae26dc5cf702b29fc4c8487088bab133c8ce5abce01226833fafb0d5a4",
"crates/horizon-world/src/water_splash.rs": "e0461ae1b2e8c851cca6e3251a188334293292201d7f80dc9e7d60fd1815f4d1",
"crates/horizon-world/src/world_movement.rs": "f8fe9e34f2395d2a04c839d1c8ba78e09ce493c26de6f6e4e237b9c19c061da5",
"crates/horizon-world/src/world_ray.rs": "879bdbbe12f56deb705cc183933431489e840b71eade40c33391eed5949c2e61",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "74e4110fb19c4c4047192fd65c38015b8afc7f9fc50404d75380b5063808148c",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f"
}
}
@@ -1,203 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 8338,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "b9c34e7f7a7c14001e03373cbbd468a228c5301eb639460b4ce465d14e946113",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "a40c9d7a4e0a734c124dc856e31359fd4d8de3d1bfc79c86787afa8e8e05e480",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "f0997b21c8083de75f4f8883e8855e1d2d9f1876a2053a8a97b081deed5b0bcd",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/collision_context_fixture.rs": "b7bf0f48f7dc0129c1ebe43c11cb4cad00194b501c2bcbb3220bc8779e695ba4"
},
"fixtures_sha256": {
".local/rust-collision-context-parity/inputs.txt": "60b49e91a7a4999cfb8eb6ac3fbc6ec0a931d68cd53f9737959a2bd2b42be7a5"
},
"rust_output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"matched_output_lines": 225126
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"matched_output_lines": 225126
}
],
"scope": "Actual CollisionContext factories and EntityCollisionContext/Empty/PositionCollisionContext queries on controlled player and marker snapshots. Checks entity identity, captured descending and placement flags, fluid collision flags, empty-stack AIR identity, height thresholds including f32 epsilon, null factories, callback arguments/order/failures and all five fluid type pairs. Entity lifecycle, inventory mutations after capture, experimental minecart contexts, contextual block shape dispatch and live movement integration remain pending."
}
@@ -1,205 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 58344,
"block_states": 32,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "b9c34e7f7a7c14001e03373cbbd468a228c5301eb639460b4ce465d14e946113",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2",
"tools/test_liquid_collision_parity.py": "dd77dfef7d3a66e81d92b66680d9626b6d69c54fc742bf5122674f05342fe788",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "a40c9d7a4e0a734c124dc856e31359fd4d8de3d1bfc79c86787afa8e8e05e480",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "f0997b21c8083de75f4f8883e8855e1d2d9f1876a2053a8a97b081deed5b0bcd",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/collision_context_fixture.rs": "b7bf0f48f7dc0129c1ebe43c11cb4cad00194b501c2bcbb3220bc8779e695ba4"
},
"fixtures_sha256": {
".local/rust-liquid-collision-parity/inputs.txt": "564e80e9a55a186cd70c21a1db14abf59849be90bc5493346e9e64ff9d3c9d8b"
},
"rust_output_sha256": "d845ce538e9ce157f6455b32e73e03e9d7df86ebc5c9ab80ebf94705500748ab",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "d845ce538e9ce157f6455b32e73e03e9d7df86ebc5c9ab80ebf94705500748ab",
"matched_output_lines": 571179
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "d845ce538e9ce157f6455b32e73e03e9d7df86ebc5c9ab80ebf94705500748ab",
"matched_output_lines": 571179
}
],
"scope": "Native contextual LiquidBlock collision dispatch for all 32 water/lava states. Checks the always-fluid bypass, source-only selection, living-entity gating, supplied entity standing shapes, exact height boundaries, all 33 above-block fluid states, callback order and failure propagation, null/placement contexts and wrapping above-block coordinates. Full selected shape data and callback traces are compared. Entity-specific standing shape implementations, liquid simulation and live movement remain pending."
}
@@ -1,205 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 56448,
"block_states": 32,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "b9c34e7f7a7c14001e03373cbbd468a228c5301eb639460b4ce465d14e946113",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2",
"tools/test_scaffolding_collision_parity.py": "bab75e2cad68a3193035a87497eaa372466c405293cc547e39dbd7bd4450d69d",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "a40c9d7a4e0a734c124dc856e31359fd4d8de3d1bfc79c86787afa8e8e05e480",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "f0997b21c8083de75f4f8883e8855e1d2d9f1876a2053a8a97b081deed5b0bcd",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/collision_context_fixture.rs": "b7bf0f48f7dc0129c1ebe43c11cb4cad00194b501c2bcbb3220bc8779e695ba4"
},
"fixtures_sha256": {
".local/rust-scaffolding-collision-parity/inputs.txt": "5945054e86700237a7b6de6b362a37a98bdc8afaa67004e8aaa92da1421b552c"
},
"rust_output_sha256": "33a33cd612c999ab21f1acbbdee522f2ec2b3f877d62f922c665715e3012e207",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "33a33cd612c999ab21f1acbbdee522f2ec2b3f877d62f922c665715e3012e207",
"matched_output_lines": 524300
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "33a33cd612c999ab21f1acbbdee522f2ec2b3f877d62f922c665715e3012e207",
"matched_output_lines": 524300
}
],
"scope": "Actual CollisionContext.getCollisionShape dispatch and native scaffolding behavior for all 32 scaffolding states, nine context variants, descending flags, integer Y extremes, nonfinite positions and adjacent double values around the top/bottom float-epsilon thresholds. Full shape coordinates, extrema, box ordering and cube metadata match. A rejecting world proxy verifies selection performs no world reads. Scaffolding placement/update/falling behavior and live movement remain pending."
}
@@ -1,201 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 8338,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "ee1525cc998c8b49fbc5318efffcec7b98cc8be3e4755d3bfc8458ac3c5e64c2",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "a40c9d7a4e0a734c124dc856e31359fd4d8de3d1bfc79c86787afa8e8e05e480",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/collision_context.rs": "3053db15dff5776571a2c919634362fe43100978867f9e3ac46b2299563a6d4d",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "8f77b4a1c5e25ecf9336477c12e3141fafc0cd8884f3b198f2ec93b0eb47ae49",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/collision_context_fixture.rs": "c4df3b01bf9d7e58076c848fbb41f93677ea4f0fdaab768a131d9e77c7bee5cd"
},
"fixtures_sha256": {
".local/rust-collision-context-parity/inputs.txt": "60b49e91a7a4999cfb8eb6ac3fbc6ec0a931d68cd53f9737959a2bd2b42be7a5"
},
"rust_output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"matched_output_lines": 225126
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64",
"matched_output_lines": 225126
}
],
"scope": "Actual CollisionContext factories and EntityCollisionContext/Empty/PositionCollisionContext queries on controlled player and marker snapshots. Checks entity identity, captured descending and placement flags, fluid collision flags, empty-stack AIR identity, height thresholds including f32 epsilon, null factories, callback arguments/order/failures and all five fluid type pairs. Entity lifecycle, inventory mutations after capture, experimental minecart contexts, contextual block shape dispatch and live movement integration remain pending."
}
@@ -1,307 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"commands": 16770,
"command_counts": {
"noise": 2111,
"quantize": 4116,
"index": 229,
"climate_parameter": 25,
"climate_point": 183,
"noise_settings": 217,
"settings_create": 182,
"aquifer": 9136,
"noise_aquifer": 379,
"registry": 24,
"router": 168
},
"noise_aquifer_injected_failures": {
"0": 3,
"1": 3,
"2": 3,
"3": 3,
"4": 3,
"5": 3
},
"noise_aquifer_outcomes": {
"1 false": 5800,
"0 false": 9995,
"default_solid false": 12655,
"2 false": 35365,
"0 true": 1114,
"2 true": 2021,
"1 true": 43,
"5 false": 443,
"5 true": 5,
"6 false": 295,
"6 true": 8,
"7 false": 49,
"7 true": 1,
"4 false": 51,
"4 true": 4,
"error false": 17,
"3 false": 81,
"error true": 2
},
"noise_registry_entries": 64,
"density_registry_entries": 55,
"noise_settings_entries": 7,
"biome_parameter_entries": {
"minecraft:nether": 5,
"minecraft:overworld": 7594
},
"biome_tables_sha256": {
"minecraft:nether": "09e477f851380a6e726ea85fee39cd1d41c7f160fe424f58cb3f0056b5c11218",
"minecraft:overworld": "6bc45ce2eed04b6afecdfaf2cf89273e83dad071aeb45638e181d33fe5180f57"
},
"fixtures_sha256": {
".local/rust-worldgen-parity/registries.json": "c6868228cc1002755dab31d947e953cc4be785a1b6ae82697755817a238b7de9",
".local/rust-worldgen-parity/inputs.txt": "4afb482c8aa6e654ef47b9696f76c16fa862414248202c9bf748941bfc8d0877",
".local/rust-worldgen-parity/biome-presets-client.json": "b03e2fbe85c191a22f333bc989bd2a73c66f0f9fbcd9ddb54774f17c247832e9",
".local/rust-worldgen-parity/biome-presets-server.json": "b03e2fbe85c191a22f333bc989bd2a73c66f0f9fbcd9ddb54774f17c247832e9"
},
"noise_resources_sha256": {
"data/minecraft/worldgen/noise/aquifer_barrier.json": "864a9d66a03b081adc8d4bf51a6d0cd5fdd94a0ebf1cecadec2aed9e549db7e4",
"data/minecraft/worldgen/noise/aquifer_fluid_level_floodedness.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/aquifer_fluid_level_spread.json": "6afc3f09b6616f799d739b5b114c4436059dcc60308af55fe96a8594de815214",
"data/minecraft/worldgen/noise/aquifer_lava.json": "96e1c4e411ffe302c5541cd2ee8462e1992f0290d623c560f353c39981737346",
"data/minecraft/worldgen/noise/badlands_pillar.json": "79c0d0628db949d3b83bbca145da427bcdc3ff585b0ad736f7cb20e4c593c9a2",
"data/minecraft/worldgen/noise/badlands_pillar_roof.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/badlands_surface.json": "79365a5c2017e93878d989a176520ba9cbdf8685cff8b3cb148730d949d98b09",
"data/minecraft/worldgen/noise/calcite.json": "331259d84572c32b4b268d069e0132da9e6623ba614080e34b815472c7f4ee0c",
"data/minecraft/worldgen/noise/cave_cheese.json": "24c6846b7fc1f7c652bf185797fe98b943146b6aaf8766d1bff2066c59b7ed24",
"data/minecraft/worldgen/noise/cave_entrance.json": "f75146a7b1a033998edd3c77319f78243fe933bdcda2067b78658940f145cac6",
"data/minecraft/worldgen/noise/cave_layer.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/clay_bands_offset.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/continentalness.json": "b7ce5ac29a2c7a7cfbfaa1e1eeca9ba8f4a52139e59318850fa2407242c69ba8",
"data/minecraft/worldgen/noise/continentalness_large.json": "76834cff0227d52b19b5932142925f4fc639e713c2180e489f813701ca45f53e",
"data/minecraft/worldgen/noise/erosion.json": "af8a7a0f16ff3e568ad646df9cbc28e04a31b16dad4f162705c0f7c747da6983",
"data/minecraft/worldgen/noise/erosion_large.json": "d20c2c6ec805a366b105924b3cee29ac5b84cc06d636b539ae0047aac413b60a",
"data/minecraft/worldgen/noise/gravel.json": "87d627634161e51a79512f3d3f42f990d2a185e35198eb5e2161939d866751e0",
"data/minecraft/worldgen/noise/gravel_layer.json": "a4b45bdb6efef2509b053b970f6e84250d7b16d54f3906bc7fcf2665ada2a692",
"data/minecraft/worldgen/noise/ice.json": "85d03cc06d6bc552dc399dcc90ca9749c2625ddf0049dc0f95684631a7c6e66e",
"data/minecraft/worldgen/noise/iceberg_pillar.json": "98816326f84a21ce29421a9cba3ad85e5a26069312c9819aaf5662691e777fd5",
"data/minecraft/worldgen/noise/iceberg_pillar_roof.json": "864a9d66a03b081adc8d4bf51a6d0cd5fdd94a0ebf1cecadec2aed9e549db7e4",
"data/minecraft/worldgen/noise/iceberg_surface.json": "79365a5c2017e93878d989a176520ba9cbdf8685cff8b3cb148730d949d98b09",
"data/minecraft/worldgen/noise/jagged.json": "d64347f4f9acb984075e3b4945b4699907ec6d893588388dd8f738f29f75f4d1",
"data/minecraft/worldgen/noise/nether/temperature.json": "5a67fbc28b5c2578b4ca5f6abdd115c715ea2ef1be3e1a7a8eb1a0de4c3a8f7c",
"data/minecraft/worldgen/noise/nether/vegetation.json": "5a67fbc28b5c2578b4ca5f6abdd115c715ea2ef1be3e1a7a8eb1a0de4c3a8f7c",
"data/minecraft/worldgen/noise/nether_state_selector.json": "116c8bf1d676fd3a3dea3908e074a4f4b7ee55d3263e93abf5889b41bfc77f5b",
"data/minecraft/worldgen/noise/nether_wart.json": "4518b186ffe4b65394a35276c8708037c6f3f73c7cb95ef6d41a5cd4b8d234f6",
"data/minecraft/worldgen/noise/netherrack.json": "cef60938a0304eec78a6bdebd24b80a45c5d1bad894c6c012e3413ecc485a81a",
"data/minecraft/worldgen/noise/noodle.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/noodle_ridge_a.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/noodle_ridge_b.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/noodle_thickness.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/offset.json": "45f51565587e2dc055271648037c0ec3466815e82f0d762e0198c16285fc8ae7",
"data/minecraft/worldgen/noise/ore_gap.json": "6afc3f09b6616f799d739b5b114c4436059dcc60308af55fe96a8594de815214",
"data/minecraft/worldgen/noise/ore_vein_a.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/ore_vein_b.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/ore_veininess.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/packed_ice.json": "0f51993727dcb0aa7c6cb9288e462443e711e9980c12927435126a3c45922786",
"data/minecraft/worldgen/noise/patch.json": "83a0052d4220c67c5513bce689d681e3af3325c18fec612cdd4941fc738f4be0",
"data/minecraft/worldgen/noise/pillar.json": "5a67fbc28b5c2578b4ca5f6abdd115c715ea2ef1be3e1a7a8eb1a0de4c3a8f7c",
"data/minecraft/worldgen/noise/pillar_rareness.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/pillar_thickness.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/powder_snow.json": "98816326f84a21ce29421a9cba3ad85e5a26069312c9819aaf5662691e777fd5",
"data/minecraft/worldgen/noise/ridge.json": "e05d077746b27d662a8c981807819df3e3bb1f1779d2245dd911c8193e03bbf8",
"data/minecraft/worldgen/noise/small_patch.json": "9ecc836feb68b42d717217e028f2a72112179f1097f5bd156b1d3f1db637732e",
"data/minecraft/worldgen/noise/soul_sand_layer.json": "a4b45bdb6efef2509b053b970f6e84250d7b16d54f3906bc7fcf2665ada2a692",
"data/minecraft/worldgen/noise/spaghetti_2d.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/spaghetti_2d_elevation.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/spaghetti_2d_modulator.json": "d210211c0c76c53f15908f0b004a7e98e9d753ed996cd5468f2068f2e23932d1",
"data/minecraft/worldgen/noise/spaghetti_2d_thickness.json": "d210211c0c76c53f15908f0b004a7e98e9d753ed996cd5468f2068f2e23932d1",
"data/minecraft/worldgen/noise/spaghetti_3d_1.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/spaghetti_3d_2.json": "e755b926628bc49edf48a3bd3b1e1bc3e2895b774f5e2e81f1d4340782a9fc56",
"data/minecraft/worldgen/noise/spaghetti_3d_rarity.json": "d210211c0c76c53f15908f0b004a7e98e9d753ed996cd5468f2068f2e23932d1",
"data/minecraft/worldgen/noise/spaghetti_3d_thickness.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/spaghetti_roughness.json": "6afc3f09b6616f799d739b5b114c4436059dcc60308af55fe96a8594de815214",
"data/minecraft/worldgen/noise/spaghetti_roughness_modulator.json": "7f137a0382721b8c7b3227e65dc32a3f6d9c3d5893458b03e892797ae31d85d7",
"data/minecraft/worldgen/noise/sulfur_cave_gradient.json": "4900ffd885ce33b220a673ba0a248504c78f9f2cdfce824106a237d9ad18a6a7",
"data/minecraft/worldgen/noise/surface.json": "79365a5c2017e93878d989a176520ba9cbdf8685cff8b3cb148730d949d98b09",
"data/minecraft/worldgen/noise/surface_secondary.json": "ae23cb210db7b64b66b327dbbf1e7b2acb5c15cb6fe5df0455eb29910d9312eb",
"data/minecraft/worldgen/noise/surface_swamp.json": "19e08e0d1dff257cf748d3cef79e939e8f25cc5e7226653c789008171f40695b",
"data/minecraft/worldgen/noise/temperature.json": "9b1d5a87d575abf2891882ec3e1544b964cd15fedc84ad14d2abbd3b48ee2e4b",
"data/minecraft/worldgen/noise/temperature_large.json": "4fe64b952b751eb7e45b4d1e274add508b504ee8bbc54cad417ce3a3b068d42e",
"data/minecraft/worldgen/noise/vegetation.json": "ff4c10776eb2822f9f66dec4e9878a1bc797aca711480bf8430f851ff9af77dc",
"data/minecraft/worldgen/noise/vegetation_large.json": "20f4a255e3f9452f4cf983b3efed71ead184d04f4070283f355ad4d97993d133"
},
"density_resources_sha256": {
"data/minecraft/worldgen/density_function/end/base_3d_noise.json": "38db7d590abc3144e3357a79562d649d9880bc2c62ddc99480d93f4b6401c9a6",
"data/minecraft/worldgen/density_function/end/islands.json": "6e4f02929580ecc34bfb059855b4e88d080dc7ca6c9984f216bdaa32e6b47700",
"data/minecraft/worldgen/density_function/end/sloped_cheese.json": "5dee072865321e57e5e231e60a57bfcd1919454f93da33b3c1651b3712f2cfb2",
"data/minecraft/worldgen/density_function/nether/base_3d_noise.json": "76cfd16e6fc2b1ce8bdb5f5ee277d431c167bc01afc2462bffff09eb5f0bd582",
"data/minecraft/worldgen/density_function/overworld/base_3d_noise.json": "2791a1e6c5c730eac1bd35aaea9a7ab22855872fdb92349192d045330fd4614f",
"data/minecraft/worldgen/density_function/overworld/caves/entrances.json": "63a1b8351e6dea212501c36f515f32e5a0e960228b5b5ccf0dc5b43855cbc1ab",
"data/minecraft/worldgen/density_function/overworld/caves/noodle.json": "3bce7453470fd37e3bfc11dc8584494aab094f9fd820038dc5592cb47e825a69",
"data/minecraft/worldgen/density_function/overworld/caves/pillars.json": "069d35fbdaed7d74521fc3e9355a94e778450b52a05f1efbd470ce3917b8a207",
"data/minecraft/worldgen/density_function/overworld/caves/spaghetti_2d.json": "a99c68ac415596788c84e93e81c96c9786e31db21a81157459a13272cda4cb1f",
"data/minecraft/worldgen/density_function/overworld/caves/spaghetti_2d_thickness_modulator.json": "4f987a0b9e8c0adb02df47034fa8b3cebfbfb2c8e607123614ef009a16bfaf6c",
"data/minecraft/worldgen/density_function/overworld/caves/spaghetti_roughness_function.json": "03bd1b405e53aeb75b6a3440d97975c25b6f11c7fc07149471b86c80fbdb6ea4",
"data/minecraft/worldgen/density_function/overworld/chunk_surface_level.json": "93a4e26ce4a1144c42040f52ca375f0dec94648c70ccdcc52db4a7f55ca526a5",
"data/minecraft/worldgen/density_function/overworld/continents.json": "0f2ff487c0556391ae2d56b7cab6990d45766ade2503236fe2669f83a64517be",
"data/minecraft/worldgen/density_function/overworld/depth.json": "9fcd7c8badcae4dc8e86303b0f72b05b5fd998d5bb7ac637729dd7e688688069",
"data/minecraft/worldgen/density_function/overworld/erosion.json": "8173a3df61a3c5cfe352fb4a8fa64e99840836e42f2f4b0ddf8035f4d28f97a5",
"data/minecraft/worldgen/density_function/overworld/factor.json": "f7cd1629f1a034504bd74fd38af5ea75a59257c565b5d919a6212e2e08778e30",
"data/minecraft/worldgen/density_function/overworld/final_density.json": "a7e6b9f4618e27cb08ec37a294d8ca2a96747128a8d65d788dc418fda372cfb1",
"data/minecraft/worldgen/density_function/overworld/jaggedness.json": "5e8acc680409ae0b56596be02954eb5b49a72069d004e5dcf9a92c5e106ccdb2",
"data/minecraft/worldgen/density_function/overworld/offset.json": "da6b4e686d8eb16c19443a1126168b6f2719712c02b690b9d7384ce53badf995",
"data/minecraft/worldgen/density_function/overworld/ore_vein/copper_density.json": "3b16d3a4499981f40bfd2b33786a99046bbca0c958f8f41692ffcbf44ae927d7",
"data/minecraft/worldgen/density_function/overworld/ore_vein/gap.json": "89ccfa58c6b8ae3e3954d2ff2dbcc42a8a3ae24a7b07437dbfb85fdced55945a",
"data/minecraft/worldgen/density_function/overworld/ore_vein/iron_density.json": "8de70a31c97e2a8299679770d53c8e366ace1aa8585e8d840375d25f85b72f8f",
"data/minecraft/worldgen/density_function/overworld/ore_vein/mask.json": "7f92df0b19e7d29fef01abc7025fea2bdae7a57453e186785cde2fc7d08aa5bc",
"data/minecraft/worldgen/density_function/overworld/ore_vein/richness.json": "3eb0183e295a5f9c54aab936b706b4b9d570ddf56c983ae89b91151e6e38fb9d",
"data/minecraft/worldgen/density_function/overworld/ore_vein/toggle.json": "49b9db48740578911d0f8a2de40f02eced3ae742f03ebb05fee381af579cc9ed",
"data/minecraft/worldgen/density_function/overworld/preliminary_surface_level.json": "4b6ce4c38ede0bec7485d4c029b9fcc7ceb5b26977c2c391a650fe8f3a3272b6",
"data/minecraft/worldgen/density_function/overworld/ridges.json": "bf66a03bd8474d09dad4da23f4b7e76816b83e23df9f53d9c0b7c529c25ed9c1",
"data/minecraft/worldgen/density_function/overworld/ridges_folded.json": "c8a4343b56273a476648a84fbbe07d8c473c1dd3769749260db6340ba5b37f9a",
"data/minecraft/worldgen/density_function/overworld/sloped_cheese.json": "5e2e7756881a4f2acf2e8c8dc826a04681939ff1dc7508ce868e865e92a069d7",
"data/minecraft/worldgen/density_function/overworld/temperature.json": "3c2f498cbf4636cd1fa7f555c14220a733c9d07fb5a1563f11c6144a27f31ce8",
"data/minecraft/worldgen/density_function/overworld/vegetation.json": "c902ef045f63a568ef4c3d834716c67b5835f0994997ee45756837de111a806c",
"data/minecraft/worldgen/density_function/overworld_amplified/chunk_surface_level.json": "378eef8542e7ee3adffeaf746e0c776d1e00ff75cf030d9244292acd796739f6",
"data/minecraft/worldgen/density_function/overworld_amplified/depth.json": "35bbe18bc8eaec3bc8d81f1b3130018874d6cc8fa516c1e8380bdb8caf68c803",
"data/minecraft/worldgen/density_function/overworld_amplified/factor.json": "b42bc13d4d3c1cbeb7c6dfa2e16f4ef532ad0cff3a92d20bace01711fee6edd4",
"data/minecraft/worldgen/density_function/overworld_amplified/final_density.json": "cde96d8a5efa63cd20cea615dd1172e5e6f2626e9275d359fa2864e77083ac4f",
"data/minecraft/worldgen/density_function/overworld_amplified/jaggedness.json": "9f9a8993ce50cd2f0736ef98c3f8ff55db02d47b2a3e4f6aacae7c45a3c95bcc",
"data/minecraft/worldgen/density_function/overworld_amplified/offset.json": "0bb9ae6088ea4dbfdf79f6f2b2eed789c68e9a4e919a31bf912f91ddeda28e8b",
"data/minecraft/worldgen/density_function/overworld_amplified/preliminary_surface_level.json": "e8a82a9dfe183f4e624ea7a268efa2c54376caf99139596a26ad1dd27e887e5f",
"data/minecraft/worldgen/density_function/overworld_amplified/sloped_cheese.json": "d8609154b76d0eefcfbc3746fa84f32cb04c5817a2fd1b80e72ee0ae9d88e96c",
"data/minecraft/worldgen/density_function/overworld_large_biomes/chunk_surface_level.json": "72f29b5fa9c01afa296d3679e6be662ee1b0bfdc1ba40cc2092ea74380be5c47",
"data/minecraft/worldgen/density_function/overworld_large_biomes/continents.json": "cfab013269cff17cfdf95497f87e70591378e7a39da44a241199fb64b304d411",
"data/minecraft/worldgen/density_function/overworld_large_biomes/depth.json": "9ec8ced85b58494f5400d4a5f6a27f1d4d44271d7a87adb8c5d842319eb5997f",
"data/minecraft/worldgen/density_function/overworld_large_biomes/erosion.json": "773d626db8e356d92a321270895ce085287d2befcb4504842371c38fd10102ac",
"data/minecraft/worldgen/density_function/overworld_large_biomes/factor.json": "0e7aa57eca20ebd6d2f089a9a4a34502efe902295812650f71b2ff087bb8b15f",
"data/minecraft/worldgen/density_function/overworld_large_biomes/final_density.json": "6f644644293c5489c499dc57663f2c12de60fc720bc4f1120efd343246eb159e",
"data/minecraft/worldgen/density_function/overworld_large_biomes/jaggedness.json": "30090703d4d9e493d40d60e06ee12f1310a608e20b73aeb8f86efa8e31b11453",
"data/minecraft/worldgen/density_function/overworld_large_biomes/offset.json": "75517306420732023e2dfeeb253439d8f0edcde9bb8b10ee7870d1bdb072ec22",
"data/minecraft/worldgen/density_function/overworld_large_biomes/preliminary_surface_level.json": "ece7767faac91980f5349ddfdc6040dc4ebbfce71a9f4d5842fa1b7bb169db3b",
"data/minecraft/worldgen/density_function/overworld_large_biomes/sloped_cheese.json": "347e160b5f951137b5f82a39c18572f8851c5a22484d11f31d1f90f5e5f6ac99",
"data/minecraft/worldgen/density_function/overworld_large_biomes/temperature.json": "051138f2c2f0ca4050b92f7320ddea461dca2038a49eb6f9931ecbf39129f4ef",
"data/minecraft/worldgen/density_function/overworld_large_biomes/vegetation.json": "187b08814a3831cd0ff2f405c6683e7213a79dc7eeec44cd46136e350b0718b7",
"data/minecraft/worldgen/density_function/shift_x.json": "0db6e5f781089feede9d8d2936d7564024752e34006b8bc9f2a138749f91e3e7",
"data/minecraft/worldgen/density_function/shift_z.json": "0b561cdfafa9e82f431a8051576eb2ddc386d01459df571d7040021b0debb762",
"data/minecraft/worldgen/density_function/y.json": "e7766e59792605f5c3d8e05ff6263db1dc6c91343c736b3ab7a58ddee9771282",
"data/minecraft/worldgen/density_function/zero.json": "8aed642bf5118b9d3c859bd4be35ecac75b6e873cce34e7b6f554b06f75550d7"
},
"noise_settings_resources_sha256": {
"data/minecraft/worldgen/noise_settings/amplified.json": "07fbadd0fd71e16e5497c575d3c86d997166087ccfaaba70a589a440b915024e",
"data/minecraft/worldgen/noise_settings/caves.json": "29a378b845f7bff27a8badecba7ecf2bb22d0d4224b751ab6d91677c83bc6a6a",
"data/minecraft/worldgen/noise_settings/end.json": "d0fd92ddd39081f1779ce5482041a837fb4a03841ea4d843556f17b557e31f4b",
"data/minecraft/worldgen/noise_settings/floating_islands.json": "54923e55bfad4274bea513eccb42e1eb3625fb47ae00905537e0d3d68f82045d",
"data/minecraft/worldgen/noise_settings/large_biomes.json": "dcb29a9e3fb630f2b76a52d759c6925b40e67cd13bc7f9ae93976f0633cc2c05",
"data/minecraft/worldgen/noise_settings/nether.json": "e6d7856fe4523e4c3fa4dce756b6b1e211bfc263c5e417fb6294d032b8f53e9b",
"data/minecraft/worldgen/noise_settings/overworld.json": "d093895d50edd79d53555b33b62d767115399764e32a4f9ae2687739f785d4b9"
},
"inputs_sha256": "4afb482c8aa6e654ef47b9696f76c16fa862414248202c9bf748941bfc8d0877",
"rust_output_sha256": "c39201a8d64b2ec12dc08d8eddcb962d336885a749200a0a33c0fefd7910c193",
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaWorldgenOracle.java": "272b7e7c90dfc1344f6964033b61ee27ac867da7b375e406586b88de08d02b08",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBiomeExport.java": "f9a773713cf21b69bfa10018b76f27b953bda140ede9934f43d3aa3091101cf5",
"tools/test_worldgen_parity.py": "699826ef3d3f1ac5419b91153539bf0857e931fd128a39fc47d8c8071cc03268",
"tools/test_rust_parity.py": "7efa699a38c5820424f5fc8992ee601dbfe26d6482da9d2dab2c17c41fe8f12a",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "69f89566a78456c29caaa39dacedfe711ca59e49b78f64e68b0414fb6a73d8fc",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "de22acd7430df3f69ef3632d427c57dffe57f3bdb78950bc75eac7e179ccf9df",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "3968e2a337a6a23226c485057c79359e66df16683f00fb4ebc9fabb03910a015",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random.rs": "92135a94c79111cc810b4b071dbd76043ee47c2585fd431e7486ea381f19e5db",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "84852599dde78687d782f115a5b4b3ef6856c1f9cc92917255167e89c72ab01e",
"crates/horizon-core/tests/density_world_fields.rs": "e193e45080817ef92547828a8d106482a376b9f788e39d4d3831f44e9d693148",
"crates/horizon-world/examples/collision_fixture.rs": "ee754b5b42e0a51fe0a305b3f4bb56522ff3fffae564180aab8087b1b9e44afc",
"crates/horizon-world/examples/tick_fixture.rs": "df267c307e0491a238b2d93edf0384514f38f8ee3252e315b989de56c6e17990",
"crates/horizon-world/examples/world_fixture.rs": "a3c4c0f5131ae051b24662eff0ed11ed797c6fd5069fbfdf819f0e3fcdfb2cf4",
"crates/horizon-world/src/bin/worldgen_parity.rs": "5af97baa6681bc7aa04d981ec5c07c38cb27f28213abf34b1e83270828dd2980",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/collision.rs": "6c40ab491efd0332bd4e65a1a112f3598f9eb0ea2f32f9c8cc7e81278d003251",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/lib.rs": "a6376d79c90ebdee539f4b460a9dd18d75e0c049c24f028d00c9c45c85ebf668",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry.rs": "f46065659e60eb5e84ad69b9f3b5e94dc87ee19de16408817e26f23d16b6c7e7",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/biome.rs": "b3b73091aa5ec989d916206567c5e4b0e997b007a5bb9c0ca5c53ada9d5fe81f",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen.rs": "24f440a4be7546e79b4f462dd18aad9031e94dc87c5f1d32b78912650f7dd162",
"crates/horizon-world/tests/biome_data.rs": "d4de462ccc3e6ad5760490330e0f0cd8a45734077708a2eca95ca06e65f779b0",
"crates/horizon-world/tests/collision_data.rs": "45f3d33b36efe720e99ebf75b9f4fbddd777cebea4618bba245ca106b3443391",
"crates/horizon-world/tests/tick_data.rs": "ab345209367db6963b987797992c4a06433bd2039e6021bd834f6305324c04d7",
"crates/horizon-world/tests/world_io.rs": "4a42630c99ce89b27cc2be1a1b961ad880f62762ab661f9e92ef9bcf7f3e76e0",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"Cargo.toml": "dc370d5fdde37238c3e4820046f11c3201020406a4edfa1308257c13edbdcda4",
"Cargo.lock": "7307d0c887364db36d327685ecf0671b75305e31e5ba5fbdcdbb15eaf156d20e"
},
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "c39201a8d64b2ec12dc08d8eddcb962d336885a749200a0a33c0fefd7910c193",
"matched_output_lines": 922238,
"biome_export_sha256": "b03e2fbe85c191a22f333bc989bd2a73c66f0f9fbcd9ddb54774f17c247832e9"
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "c39201a8d64b2ec12dc08d8eddcb962d336885a749200a0a33c0fefd7910c193",
"matched_output_lines": 922238,
"biome_export_sha256": "b03e2fbe85c191a22f333bc989bd2a73c66f0f9fbcd9ddb54774f17c247832e9"
}
],
"scope": "Direct normal-noise JSON decoding using the actual pinned vanilla CODEC. Every bundled noise registry resource, explicit/default parameters, empty and full amplitude modifiers, normalization modes, inclusive field bounds with signed-zero comparator ordering, malformed types, null fields, duplicate and ignored keys, decimal/exponent integer truncation and wrapping, signed zero, seeded modern/legacy and Nether construction, octave metadata, range and normalization bits, scalar noise values and parent random state. JSON resource contents stay private. Strict JSON parsing; no claim for Gson's permissive non-JSON syntax. Bundled density registries are also decoded with actual vanilla registry-aware CODECs: named forward references, all bundled function kinds, declared range/axes, raw compilation errors, seeded optimized roots, cache allocation, scalar values, strided bulk values, repeated cache hits and surface-volume errors are compared using RandomState's actual compile context. All seven bundled noise-setting resources contribute their actual eight-field NoiseRouter.CODEC objects to RandomState. Router fields are compiled in declaration order with a shared compiler/context; cache allocation, raw/optimized scalar and repeated strided volume values, successful single-layer surface volumes and invalid surface-volume shapes are compared. Actual RandomState climate sampler binding and quart-to-block coordinate wrapping are checked at ordinary and extreme positions. Float-to-long climate quantization and long-to-float conversion include subnormals, signed zeros, NaNs, infinities, cast saturation and seeded random bit patterns. Actual vanilla Climate.Parameter and ParameterPoint JSON codecs compare scalar, two-element list and min/max object intervals, float endpoint bounds/ordering, required coordinate/offset fields, negative zero, precision-sensitive float parsing, malformed types and duplicate keys. Climate parameter distances, wrapping squared fitness, stable search-tree leaf order and nearest lookup are compared across every supported branching value 2..32, sizes around branch powers, the 65536-entry API bound, duplicates, warm ties, fresh lookups, brute-force lookup and extreme signed-long endpoints/targets. The Rust tree is immutable with per-worker search state instead of hidden thread locals; invalid or degenerate searches return typed errors. Inline arbitrary distance metrics and behavior outside the bounded API are not covered. Built-in Overworld and Nether quantized biome parameter tables are exported independently by each authenticated JAR and required to agree before Rust consumes them. The Rust multi-noise resolver and actual vanilla MultiNoiseBiomeSource compare biome identities through scalar climate queries and prepared bulk quart volumes, including forward/reverse/repeated query order, wrapped extreme origins and shared previous-result state. Biome holder keys in the reference are registration placeholders; no biome property or gameplay behavior is evaluated. The Rust loader reads a Horizon quantized table format, not the vanilla biome codec, and the preset builders themselves have not been ported. Source and private fixture mutations during validation invalidate the report. The two-field 26.3 NoiseSettings codec, create helper and LevelHeightAccessor clamping are also compared across bundled noise members, dimension/alignment bounds, zero/negative runtime heights, disjoint ranges, wrapped integer arithmetic and decimal/exponent integer conversion. Global fluid cutoff selection and the actual disabled Aquifer implementation are compared with original default block-state identities, extreme sea levels/coordinates, signed-zero/subnormal/nonfinite density and counted picker calls; developer fluid-disable behavior is outside the regular-mode corpus. The actual noise-based Aquifer.Config codec and runtime are compared across bundled aquifer settings, modern/legacy world-seeded aquifer factories, synthetic density roots, nondefault water/lava states, cave/void air, nonfinite sampler overrides, strided volume extents, wrapped coordinates, repeated and reversed queries, counted picker calls, sampler call order/values, injected failures and retry state, scheduling flags, populated location/status caches and sorted surface-cache entries. Oversized or wrapped-invalid grid allocations and developer fluid-disable behavior are outside the bounded regular-mode API. Terrain filling is not yet validated. Router, vertical noise and optional aquifer members are decoded from each noise-setting resource; complete NoiseGeneratorSettings, material rules, nonempty world fields, biome registry/codecs and complete chunk biome assignment, generated chunks, gameplay and rendering remain pending. Inline noise holders and general codec behavior beyond the covered fixtures remain pending."
}
@@ -1,342 +0,0 @@
{
"schema": 1,
"measurement": "Shader world activation/startup probes; not FPS or physical M2 measurements",
"release": "0.20.0",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"local_source_commit": "99d6aae5e06a3fc9a9a69c433f48f32729776861",
"linux_opengl": {
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"results": [
{
"observed_mode": "world",
"title_screen_observed": false,
"world_loaded": true,
"ready_client_ticks": 40,
"window_active": true,
"overlay_present": false,
"overlay_wait_ticks": 79,
"heap_max_bytes": 6442450944,
"iris_capture_status": "available",
"iris_shaders_enabled": true,
"shader_required": true,
"iris_expected_pack_matches": true,
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 3777,
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "OpenGL",
"graphics_driver": "4.5 (Core Profile) Mesa 26.0.8-1ubuntu0.3",
"private_png_sha256": "1a221bb9bedb21770f08ffcde593539c02d4e7cad48516bf7fad4215d7b14cde",
"profile": "cinematic",
"preferred_backend": "opengl",
"launcher_exit_code": 0,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
]
}
],
"limits": [
"Short scene startup and nonuniform framebuffer readback only.",
"World mode uses the ordinary limited demo; world files remain private.",
"No exhaustive gameplay, visual-correctness, FPS or M2 Pro performance claim.",
"Vulkan preference can fall back; inspect the observed backend.",
"PNG images, assets and full logs remain in the private runtime directory."
]
},
"linux_vulkan_failure": {
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.awt.AWTError",
"java.lang.NullPointerException",
"java.lang.RuntimeException",
"net.minecraft.ReportedException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "Vulkan",
"graphics_driver": "1.4.335 llvmpipe Mesa 26.0.8-1ubuntu0.3 (LLVM 21.1.8)"
}
],
"client_initializer_reached": true,
"readback_requested": false,
"readback_callback_received": false,
"readback_inspections": [],
"probe_failure_categories": [],
"vulkan_error_codes": [],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.renderer.Lightmap.handler$zzk000$distanthorizons$render",
"net.minecraft.client.renderer.Lightmap.render",
"net.minecraft.client.renderer.GameRenderer.render"
],
"profile": "cinematic",
"preferred_backend": "vulkan"
},
"linux_vulkan_without_dh": {
"private_dh_jar_removed": true,
"new_demo_world": true,
"exit_code": 1,
"result_count": 0,
"original_mod_sha256": "e651ef49bc97486e8dacfd4b640465c442525cd645e2dba71ddea9fb64347dd8",
"failure": {
"exit_code": 1,
"result_count": 0,
"java_exception_types": [
"java.lang.AssertionError",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "llvmpipe (LLVM 21.1.8, 256 bits)",
"graphics_backend": "Vulkan",
"graphics_driver": "1.4.335 llvmpipe Mesa 26.0.8-1ubuntu0.3 (LLVM 21.1.8)"
}
],
"client_initializer_reached": true,
"readback_requested": true,
"readback_callback_received": true,
"readback_inspections": [
{
"framebuffer_width": 1280,
"framebuffer_height": 800,
"sampled_pixels": 4288,
"distinct_sampled_rgb": 1804
}
],
"probe_failure_categories": [
"shader_inactive"
],
"vulkan_error_codes": [],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.Screenshot.lambda$takeScreenshot$1",
"com.mojang.renderpearl.backend.vulkan.DestructionQueue.rotate",
"com.mojang.renderpearl.backend.vulkan.VulkanCommandEncoder.submit",
"com.mojang.renderpearl.frontend.FrontendCommandEncoder.submit"
]
}
},
"mac_source_commit": "857c5a4aa553f83799631ad48340e43a13c78549",
"mac_run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37198566508",
"mac_cases": [
{
"case": [
"--profile",
"cinematic",
"--backend",
"opengl",
"--world",
"--shaders"
],
"exit_code": 1,
"failure": [
{
"fixture": "client-graphics",
"profile": "cinematic",
"completed": false
}
]
},
{
"case": [
"--profile",
"cinematic",
"--backend",
"vulkan",
"--world",
"--shaders"
],
"exit_code": 1,
"failure": [
{
"fixture": "client-graphics",
"profile": "cinematic",
"completed": false
}
]
}
],
"limits": [
"Linux llvmpipe software renderer; no physical M2 shader performance or native GPU test.",
"OpenGL requires actual pinned shader activation and matching runtime pack identity, with nonuniform readback, focused gameplay, saved data and clean exit.",
"Linux Vulkan plus DH fails before readback; selected stack locations alone do not establish the root cause.",
"Removing DH privately produces an ordinary Vulkan world readback but Iris reports shaders inactive; the required-activation assertion rejects it.",
"Both hosted Mac cases hit the 240-second private fixture timeout; earlier diagnostics do not retain stages or waiting state. They do not establish shader compatibility or incompatibility.",
"Full logs, raw PNGs, world data, assets and shader ZIPs remain private.",
"Diagnostic repeat: OpenGL loads a world but retains a screen before readback; Vulkan initializes its device but records no waiting-state snapshot. Both time out; screen identity and root causes are unknown."
],
"mac_diagnostic_repeat": {
"source_commit": "ed416c91cf980f136b7431314bccea7f266fe049",
"run_url": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37199837867",
"cases": [
{
"case": [
"--profile",
"cinematic",
"--backend",
"opengl",
"--world",
"--shaders"
],
"exit_code": 1,
"failure": [
{
"exit_code": -15,
"result_count": 0,
"java_exception_types": [
"java.lang.IllegalStateException",
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "OpenGL",
"operation": "load_library",
"result": "success"
},
{
"backend": "OpenGL",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Software Renderer",
"graphics_backend": "OpenGL",
"graphics_driver": "4.1 APPLE-23.1.1"
}
],
"client_initializer_reached": true,
"readback_requested": false,
"readback_callback_received": false,
"readback_inspections": [],
"last_waiting_state": {
"world_loaded": true,
"player_present": true,
"overlay_present": false,
"screen_present": true,
"window_active": true,
"paused": false,
"ready_client_ticks": 0
},
"probe_failure_categories": [],
"vulkan_error_codes": [],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [
"net.minecraft.client.renderer.LevelRenderer.mixinextras$bridge$renderGroup$135",
"net.minecraft.client.renderer.LevelRenderer.wrapOperation$bio000$iris$beginTerrainLayer",
"net.minecraft.client.renderer.LevelRenderer.executeSolid",
"net.minecraft.client.renderer.LevelRenderer.lambda$addMainPass$0",
"com.mojang.blaze3d.framegraph.FrameGraphBuilder.execute",
"net.minecraft.client.renderer.LevelRenderer.render",
"net.minecraft.client.renderer.GameRenderer.mixinextras$bridge$render$86",
"net.minecraft.client.renderer.GameRenderer.wrapOperation$bjf000$iris$renderLevel"
],
"fixture": "client-graphics",
"profile": "cinematic",
"completed": false,
"timed_out": true,
"timeout_seconds": 240
}
]
},
{
"case": [
"--profile",
"cinematic",
"--backend",
"vulkan",
"--world",
"--shaders"
],
"exit_code": 1,
"failure": [
{
"exit_code": -15,
"result_count": 0,
"java_exception_types": [
"java.lang.RuntimeException"
],
"expected_demo_authentication_errors_observed": true,
"backend_attempts": [
{
"backend": "Vulkan",
"operation": "load_library",
"result": "success"
},
{
"backend": "Vulkan",
"operation": "create_device",
"result": "success"
}
],
"created_devices": [
{
"gpu": "Apple Paravirtual device",
"graphics_backend": "Vulkan",
"graphics_driver": "1.2.350 MoltenVK 1.4.2"
}
],
"client_initializer_reached": true,
"readback_requested": false,
"readback_callback_received": false,
"readback_inspections": [],
"last_waiting_state": null,
"probe_failure_categories": [],
"vulkan_error_codes": [],
"fatal_jvm_error": false,
"observed_graphics_stack_methods": [],
"fixture": "client-graphics",
"profile": "cinematic",
"completed": false,
"timed_out": true,
"timeout_seconds": 240
}
]
}
]
}
}
@@ -1,160 +0,0 @@
{
"schema": 1,
"purpose": "Functional software identity capture, not a performance comparison",
"minecraft": "26.3",
"platform": "Linux x86_64 software OpenGL",
"source_commit": "110c75d712ed4827ae5e72c613f834bcc4e97da2",
"original_mod_sha256": "98f8db7ca8962a71625eef835f57d25c8afb802f2cf1b7c4c832fc070757e011",
"results": [
{
"kind": "frames",
"elapsed_seconds": 15.335704769,
"java_vendor": "Ubuntu",
"java_vm_name": "OpenJDK 64-Bit Server VM",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"mods": [
"[email protected]",
"[email protected]",
"[email protected]+38c7a2d55d",
"[email protected]+fcdff87f02",
"[email protected]+3434d6d902",
"[email protected]+26.3",
"[email protected]+74ed1ea502",
"[email protected]+0ae6f91102",
"[email protected]+3434d6d902",
"[email protected]+4be74c3f02",
"[email protected]+fcdff87f02",
"[email protected]+74ed1ea55d",
"[email protected]+6b5b47fd5d",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+3434d6d902",
"[email protected]+427eab975d",
"[email protected]+3434d6d902",
"[email protected]+47f74c9802",
"[email protected]+3434d6d902",
"[email protected]+3434d6d902",
"[email protected]+3434d6d902",
"[email protected]+cf6bc2db5d",
"[email protected]+3434d6d902",
"[email protected]+ffef5f6702",
"[email protected]+4068fd645d",
"[email protected]+ed66f0a35d",
"[email protected]+3434d6d902",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f02",
"[email protected]+3434d6d902",
"[email protected]+3434d6d902",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+79385d0b5d",
"[email protected]+b9d63e335d",
"[email protected]+3434d6d902",
"[email protected]+901a437c02",
"[email protected]+3434d6d902",
"[email protected]+4fc5413f02",
"[email protected]+fcdff87f02",
"[email protected]+48607d035d",
"[email protected]+74ed1ea502",
"[email protected]+3434d6d902",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+52268a0e02",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]+26.3",
"java@25",
"[email protected]+mc26.3",
"[email protected]",
"[email protected]",
"[email protected]+mc26.3",
"[email protected]",
"[email protected]"
],
"excluded_frames": 0,
"dropped_samples": 0,
"samples": 38,
"csv_count_matched": true
},
{
"kind": "ticks",
"elapsed_seconds": 15.009787535,
"java_vendor": "Ubuntu",
"java_vm_name": "OpenJDK 64-Bit Server VM",
"java_runtime_version": "25.0.4.1+1-1-26.04.4-Ubuntu",
"mods": [
"[email protected]",
"[email protected]",
"[email protected]+38c7a2d55d",
"[email protected]+fcdff87f02",
"[email protected]+3434d6d902",
"[email protected]+26.3",
"[email protected]+74ed1ea502",
"[email protected]+0ae6f91102",
"[email protected]+3434d6d902",
"[email protected]+4be74c3f02",
"[email protected]+fcdff87f02",
"[email protected]+74ed1ea55d",
"[email protected]+6b5b47fd5d",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+3434d6d902",
"[email protected]+427eab975d",
"[email protected]+3434d6d902",
"[email protected]+47f74c9802",
"[email protected]+3434d6d902",
"[email protected]+3434d6d902",
"[email protected]+3434d6d902",
"[email protected]+cf6bc2db5d",
"[email protected]+3434d6d902",
"[email protected]+ffef5f6702",
"[email protected]+4068fd645d",
"[email protected]+ed66f0a35d",
"[email protected]+3434d6d902",
"[email protected]+fcdff87f5d",
"[email protected]+fcdff87f02",
"[email protected]+3434d6d902",
"[email protected]+3434d6d902",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+79385d0b5d",
"[email protected]+b9d63e335d",
"[email protected]+3434d6d902",
"[email protected]+901a437c02",
"[email protected]+3434d6d902",
"[email protected]+4fc5413f02",
"[email protected]+fcdff87f02",
"[email protected]+48607d035d",
"[email protected]+74ed1ea502",
"[email protected]+3434d6d902",
"[email protected]+fcdff87f02",
"[email protected]+fcdff87f02",
"[email protected]+52268a0e02",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]+26.3",
"java@25",
"[email protected]+mc26.3",
"[email protected]",
"[email protected]",
"[email protected]+mc26.3",
"[email protected]",
"[email protected]"
],
"excluded_frames": 0,
"dropped_samples": 0,
"samples": 301,
"csv_count_matched": true
}
],
"notes": [
"Actual frame and integrated-server tick reports contain identical Java identity and 59 loaded mod versions, captured before each recording starts.",
"The short 15-second recording validates metadata and file output only; it is not a valid performance comparison or a Mac result.",
"The actual old/new report pair loads in the offline viewer with matching CSV timelines, an explicit Horizon mod-version difference and unknown legacy Java implementation warnings.",
"Synthetic changed versions, reordered mod lists, missing legacy identity, escaped mod names and expanded lists at 390px pass offline checks."
]
}
@@ -1,274 +0,0 @@
{
"schema": 1,
"original_mod_sha256": "7e0ffb16fbda2117ce3cfe9fc6249ff3c06c63be764207963ba331871ed6fabd",
"groups": [
{
"label": "initial",
"initial_warmup_checks": 1000000,
"per_observation_warmup_checks": 0,
"observations": 1,
"compiler_diagnostics": false,
"compilation_waits": false,
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 2000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 120024838,
"wall_ns": 161908976
},
{
"enabled": true,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 2000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 225290712,
"wall_ns": 296105327
}
]
},
{
"label": "compiler-diagnostic",
"initial_warmup_checks": 1000000,
"per_observation_warmup_checks": 4000000,
"observations": 3,
"compiler_diagnostics": true,
"compilation_waits": false,
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 338028221,
"wall_ns": 414836219,
"observations": [
{
"cpu_ns": 116948835,
"wall_ns": 177862175,
"allocated_bytes": 400
},
{
"cpu_ns": 118223124,
"wall_ns": 134092410,
"allocated_bytes": 0
},
{
"cpu_ns": 102856262,
"wall_ns": 102881634,
"allocated_bytes": 0
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 277210100,
"wall_ns": 346114782,
"observations": [
{
"cpu_ns": 98829230,
"wall_ns": 109874899,
"allocated_bytes": 400
},
{
"cpu_ns": 99766363,
"wall_ns": 120221997,
"allocated_bytes": 0
},
{
"cpu_ns": 78614507,
"wall_ns": 116017886,
"allocated_bytes": 0
}
]
}
]
},
{
"label": "normal-early",
"initial_warmup_checks": 1000000,
"per_observation_warmup_checks": 4000000,
"observations": 3,
"compiler_diagnostics": false,
"compilation_waits": false,
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 250273130,
"wall_ns": 250904773,
"observations": [
{
"cpu_ns": 96863757,
"wall_ns": 97499670,
"allocated_bytes": 400
},
{
"cpu_ns": 76736599,
"wall_ns": 76731887,
"allocated_bytes": 0
},
{
"cpu_ns": 76672774,
"wall_ns": 76673216,
"allocated_bytes": 0
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 260828228,
"wall_ns": 292619474,
"observations": [
{
"cpu_ns": 100375163,
"wall_ns": 120697389,
"allocated_bytes": 400
},
{
"cpu_ns": 97211084,
"wall_ns": 108680199,
"allocated_bytes": 0
},
{
"cpu_ns": 63241981,
"wall_ns": 63241886,
"allocated_bytes": 0
}
]
}
]
},
{
"label": "normal-long-warmup",
"initial_warmup_checks": 10000000,
"per_observation_warmup_checks": 4000000,
"observations": 3,
"compiler_diagnostics": false,
"compilation_waits": true,
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 331478729,
"wall_ns": 331596880,
"observations": [
{
"cpu_ns": 111403835,
"wall_ns": 111532068,
"allocated_bytes": 400
},
{
"cpu_ns": 108573471,
"wall_ns": 108571667,
"allocated_bytes": 0
},
{
"cpu_ns": 111501423,
"wall_ns": 111493145,
"allocated_bytes": 0
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 260347437,
"wall_ns": 260362090,
"observations": [
{
"cpu_ns": 74253874,
"wall_ns": 74284701,
"allocated_bytes": 400
},
{
"cpu_ns": 96313457,
"wall_ns": 96305444,
"allocated_bytes": 0
},
{
"cpu_ns": 89780106,
"wall_ns": 89771945,
"allocated_bytes": 0
}
]
}
]
}
],
"notes": [
"Exploratory fixed-order single forks. Earlier fixture protocols were not committed; warmup and diagnostics differ between groups.",
"Current production arithmetic is the same binary in all groups. Only the final protocol is reproducible from source commit c6ec0b5.",
"Retains favorable and unfavorable observations; do not combine different protocols into a statistical speedup estimate.",
"Not game FPS/RAM, Mac GPU, retained-memory or cross-hardware performance evidence."
]
}
@@ -1,88 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "7e0ffb16fbda2117ce3cfe9fc6249ff3c06c63be764207963ba331871ed6fabd",
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 164904484,
"wall_ns": 164901169,
"observations": [
{
"cpu_ns": 59683623,
"wall_ns": 59686627,
"allocated_bytes": 400
},
{
"cpu_ns": 52733305,
"wall_ns": 52727455,
"allocated_bytes": 0
},
{
"cpu_ns": 52487556,
"wall_ns": 52487087,
"allocated_bytes": 0
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 151660192,
"wall_ns": 151647654,
"observations": [
{
"cpu_ns": 56070222,
"wall_ns": 56068070,
"allocated_bytes": 400
},
{
"cpu_ns": 47850398,
"wall_ns": 47843978,
"allocated_bytes": 0
},
{
"cpu_ns": 47739572,
"wall_ns": 47735606,
"allocated_bytes": 0
}
]
}
],
"notes": [
"Actual public full-data lookup inside Fabric with generated numeric column data.",
"Thirty owners span positive/negative origins and six detail levels; output digests and source fingerprints match.",
"The actual redirect method is checked in each mode; source column data remains unchanged.",
"Three sequential warmed caller-loop observations are not independent forks; JIT compilation can vary.",
"Not whole-game FPS/RAM, rendered-pixel equivalence or a Mac GPU benchmark."
],
"provenance": {
"source_commit": "c6ec0b5e14d2ea3546fb8858be4a655634a93387",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37171062262",
"job": "portable-mod (ubuntu-latest)",
"artifact": "horizon-ubuntu-latest",
"command": "python tools/test_terrain_position.py"
}
}
@@ -1,126 +0,0 @@
{
"schema": 1,
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "7e0ffb16fbda2117ce3cfe9fc6249ff3c06c63be764207963ba331871ed6fabd",
"platform": "Linux x86_64",
"graphics": "llvmpipe software OpenGL",
"settings": {
"heap_bytes": 3221225472,
"gc": "G1",
"compact_headers": true,
"render_distance": 12,
"simulation_distance": 12,
"lod_radius_chunks": 128,
"lod_quality": "MEDIUM/MEDIUM/BLOCK",
"terrain_workers": 2,
"runtime_ratio": 0.5,
"world_difficulty": "PEACEFUL"
},
"results": [
{
"profile": "m2-balanced",
"position_enabled": false,
"elapsed_seconds": 120.557552272,
"frame_samples": 221,
"tick_samples": 2401,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"frame_stats": {
"count": 221,
"meanMs": 539.3068458597285,
"p50Ms": 512.140615,
"p95Ms": 731.515105,
"p99Ms": 811.750394,
"maxMs": 995.181191,
"meanRate": 1.8542319788391781,
"lowOnePercentRate": 1.1163478251626853,
"over16Ms": 221,
"over33Ms": 221,
"over50Ms": 221,
"over100Ms": 221
},
"tick_stats": {
"count": 2401,
"meanMs": 9.190547997917534,
"p50Ms": 8.84372,
"p95Ms": 16.100883,
"p99Ms": 21.297713,
"maxMs": 50.24744,
"meanRate": 108.8074400162632,
"lowOnePercentRate": 34.084420672139515,
"over16Ms": 99,
"over33Ms": 6,
"over50Ms": 1,
"over100Ms": 0
},
"process_rss_peak_sampled_bytes": 2961256448,
"launcher_exit_code": 0
},
{
"profile": "terrain-position",
"position_enabled": true,
"elapsed_seconds": 120.41545128,
"frame_samples": 219,
"tick_samples": 2401,
"excluded_frames": 0,
"dropped_samples": 0,
"visual_settings_changed": [],
"frame_stats": {
"count": 219,
"meanMs": 543.8858950547946,
"p50Ms": 511.34048,
"p95Ms": 780.127415,
"p99Ms": 989.910492,
"maxMs": 1062.14914,
"meanRate": 1.8386209480561242,
"lowOnePercentRate": 0.9801615082035254,
"over16Ms": 219,
"over33Ms": 219,
"over50Ms": 219,
"over100Ms": 219
},
"tick_stats": {
"count": 2401,
"meanMs": 9.594661623490213,
"p50Ms": 9.152511,
"p95Ms": 17.227297,
"p99Ms": 25.78339,
"maxMs": 56.681493,
"meanRate": 104.22462398796237,
"lowOnePercentRate": 30.354925598948153,
"over16Ms": 143,
"over33Ms": 9,
"over50Ms": 1,
"over100Ms": 0
},
"process_rss_peak_sampled_bytes": 2989678592,
"launcher_exit_code": 0
}
],
"provenance": {
"source_commit": "c6ec0b5e14d2ea3546fb8858be4a655634a93387",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37171062262",
"runtime_mod_matches_linux_ci": true,
"initial_player_snapshot_sha256": "b4d11dbd6443625415a1e32aa242d0e2d09cd77ddb1becfde5d35cb6ab8d278a",
"initial_level_snapshot_sha256": "86a3c75ea993e50c4428da4dbadc5856688a9367f035c41b8bb49863a9aeb644",
"first_saved_player_position": [
-56.5,
69.0,
55.5
],
"first_saved_player_rotation": [
141.5,
16.950002670288086
]
},
"notes": [
"Fixed-order candidate then control single pair, separate copies of the same private world; approximately 307 seconds from demo-popup dismissal to capture for each. Initial player camera and both first saved camera positions matched.",
"Stationary view includes LOD terrain; both recordings have zero paused/unfocused exclusions and matching captured settings apart from the isolated hook. No statistical speed estimate is established.",
"Preceding 60-second JFR captures ran separately before the frame recording; JIT/cache/profiling effects are not eliminated.",
"Candidate saved, reloaded, saved again and quit; control saved and quit. Both foreground launchers returned 0, with no crash reports or remaining game processes.",
"Scene differs from earlier release captures, so comparisons across releases are not valid. Private test-world camera preparation is not included in the mod or release packs.",
"No FPS improvement is established. Software rendering dominates this machine; these are functional observations, not Mac, GPU or unified-memory performance results. RSS is process resident memory, not complete GPU/unified RAM."
]
}
@@ -1,98 +0,0 @@
{
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "7e0ffb16fbda2117ce3cfe9fc6249ff3c06c63be764207963ba331871ed6fabd",
"results": [
{
"enabled": false,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 331478729,
"wall_ns": 331596880,
"observations": [
{
"cpu_ns": 111403835,
"wall_ns": 111532068,
"allocated_bytes": 400
},
{
"cpu_ns": 108573471,
"wall_ns": 108571667,
"allocated_bytes": 0
},
{
"cpu_ns": 111501423,
"wall_ns": 111493145,
"allocated_bytes": 0
}
]
},
{
"enabled": true,
"applied_hook_checked": true,
"owners": 30,
"queries": 491520,
"nonzero": 327049,
"lookup_digest": "c9745cc2e7cf6c486a92f87635c87590db61127063970c8a8c7bfb2ef5282cca",
"data_fingerprint": -5590987990034711991,
"data_unchanged": true,
"measured_checks": 6000000,
"checksum": 274877907204874744,
"allocated_bytes": 400,
"cpu_ns": 260347437,
"wall_ns": 260362090,
"observations": [
{
"cpu_ns": 74253874,
"wall_ns": 74284701,
"allocated_bytes": 400
},
{
"cpu_ns": 96313457,
"wall_ns": 96305444,
"allocated_bytes": 0
},
{
"cpu_ns": 89780106,
"wall_ns": 89771945,
"allocated_bytes": 0
}
]
}
],
"notes": [
"Actual public full-data lookup inside Fabric with generated numeric column data.",
"Thirty owners span positive/negative origins and six detail levels; output digests and source fingerprints match.",
"The actual redirect method is checked in each mode; source column data remains unchanged.",
"Three sequential warmed caller-loop observations are not independent forks; JIT compilation can vary.",
"Not whole-game FPS/RAM, rendered-pixel equivalence or a Mac GPU benchmark."
],
"provenance": {
"source_commit": "c6ec0b5e14d2ea3546fb8858be4a655634a93387",
"command": "python tools/test_terrain_position.py",
"protocol": {
"initial_warmup_checks": 10000000,
"initial_compilation_wait_ms": 1000,
"observation_count": 3,
"per_observation_warmup_checks": 4000000,
"per_observation_compilation_wait_ms": 200,
"per_observation_measured_checks": 2000000,
"run_order": [
false,
true
],
"compiler_diagnostics": false
}
}
}
@@ -1,43 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "c506982631880604513de8ef85e3b4461fbb898702e60b4a6f74ca3b3d4a687f",
"results": [
{
"enabled": false,
"applied_io_worker_checked": true,
"ordinary_join_checked": true,
"shared_future_preserved": true,
"exception_identity_checked": true,
"completed_interrupt_checked": true,
"cancelled_completion_checked": true,
"preinterrupted_pending_checked": true
},
{
"enabled": true,
"applied_io_worker_checked": true,
"ordinary_join_checked": true,
"shared_future_preserved": true,
"exception_identity_checked": true,
"completed_interrupt_checked": true,
"cancelled_completion_checked": true,
"preinterrupted_pending_checked": true
}
],
"notes": [
"Actual game IOWorker under Fabric, with controlled cached blending-read futures.",
"DH worker interruption releases only its waiter; the shared future remains consumable.",
"Ordinary callers retain join behavior; completed values, cancellation and exception identity are checked.",
"This is a shutdown correctness fixture, not an FPS or world-generation throughput benchmark."
],
"provenance": {
"source_commit": "9a1b22aa56f58a3ee39a3564be859a662d2beedc",
"workflow_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37166150119",
"job": "portable-mod (ubuntu-latest)",
"artifact": "horizon-ubuntu-latest",
"command": "python tools/test_terrain_read.py"
}
}
@@ -1,41 +0,0 @@
{
"schema": 1,
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"original_mod_sha256": "c506982631880604513de8ef85e3b4461fbb898702e60b4a6f74ca3b3d4a687f",
"results": [
{
"enabled": false,
"applied_io_worker_checked": true,
"ordinary_join_checked": true,
"shared_future_preserved": true,
"exception_identity_checked": true,
"completed_interrupt_checked": true,
"cancelled_completion_checked": true,
"preinterrupted_pending_checked": true
},
{
"enabled": true,
"applied_io_worker_checked": true,
"ordinary_join_checked": true,
"shared_future_preserved": true,
"exception_identity_checked": true,
"completed_interrupt_checked": true,
"cancelled_completion_checked": true,
"preinterrupted_pending_checked": true
}
],
"notes": [
"Actual game IOWorker under Fabric, with controlled cached blending-read futures.",
"DH worker interruption releases only its waiter; the shared future remains consumable.",
"Ordinary callers retain join behavior; completed values, cancellation and exception identity are checked.",
"This is a shutdown correctness fixture, not an FPS or world-generation throughput benchmark."
],
"provenance": {
"source_commit": "9a1b22aa56f58a3ee39a3564be859a662d2beedc",
"environment": "local Linux x64 software graphics; actual Fabric fixture",
"command": "python tools/test_terrain_read.py"
}
}
@@ -1,41 +0,0 @@
{
"schema": 1,
"platform": "Linux-6.17.0-1022-azure-x86_64-with-glibc2.39",
"architecture": "x86_64",
"minecraft": "26.3",
"distant_horizons": "3.3.4",
"results": [
{
"enabled": false,
"allocated_bytes": 245760208,
"cpu_ns": 423649902,
"wall_ns": 481491629,
"nodes_per_tick": 512,
"measured_ticks": 20000,
"verified_transitions": 6000,
"checksum": 10240000
},
{
"enabled": true,
"allocated_bytes": 208,
"cpu_ns": 185922780,
"wall_ns": 192151484,
"nodes_per_tick": 512,
"measured_ticks": 20000,
"verified_transitions": 6000,
"checksum": 10240000
}
],
"notes": [
"Actual publisher tick holder under Fabric, warmed with preallocated nodes and a reused action list.",
"Checks duplicate/null membership, enable/disable precedence, published iteration order and clear boundaries.",
"Only private membership checks change; action collections and traversal remain upstream.",
"CPU and allocation measure the calling thread in one isolated loop; no statistical speed claim.",
"Not a game FPS, visible terrain completion, whole-game RAM or Mac GPU benchmark."
],
"provenance": {
"source_commit": "e091816ce06686d64d0f7a181a42701aa67e5bf7",
"ci_run": "https://github.com/ludovic111/minecraft-optimization-lab/actions/runs/37162939262",
"artifact": "horizon-ubuntu-latest"
}
}
@@ -1,14 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Darwin 25.6.0 arm64; logical CPUs 3
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.346; 1643.771 ms; worker allocation 1403064 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.514; 1061.526 ms; worker allocation 15456 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.466; 1238.603 ms; worker allocation 1449704 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.063; 11385.730 ms; worker allocation 204024 bytes
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.703; 785.293 ms; worker allocation 1417064 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.509; 1097.416 ms; worker allocation 14496 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.431; 1293.360 ms; worker allocation 1529184 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.065; 10727.658 ms; worker allocation 198104 bytes
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.620; 896.747 ms; worker allocation 1490864 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.518; 1062.565 ms; worker allocation 13096 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.605; 975.086 ms; worker allocation 1450064 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.060; 11976.557 ms; worker allocation 196840 bytes
@@ -1,14 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Linux 6.17.0-1022-azure x86_64; logical CPUs 4
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 1.000; 578.014 ms; worker allocation 1450616 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.525; 1041.454 ms; worker allocation 64976 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.976; 591.683 ms; worker allocation 1451744 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.076; 10349.493 ms; worker allocation 145264 bytes
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 1.000; 577.632 ms; worker allocation 1451096 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.523; 1043.863 ms; worker allocation 65120 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.977; 591.337 ms; worker allocation 1410264 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.076; 10334.845 ms; worker allocation 124264 bytes
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.987; 583.777 ms; worker allocation 1490096 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.524; 1038.102 ms; worker allocation 64656 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.952; 606.495 ms; worker allocation 1408464 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.076; 10346.209 ms; worker allocation 165856 bytes
@@ -1,14 +0,0 @@
Java openjdk 25.0.4.1 2026-08-18 LTS
Platform Windows 2025Server AMD64; logical CPUs 4
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.952; 557.784 ms; worker allocation 1491496 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.556; 1038.982 ms; worker allocation 17776 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.852; 623.419 ms; worker allocation 1410384 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.078; 10247.387 ms; worker allocation 214896 bytes
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.998; 548.088 ms; worker allocation 1489616 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.574; 1034.032 ms; worker allocation 15096 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.867; 630.903 ms; worker allocation 1449664 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.078; 10266.232 ms; worker allocation 214904 bytes
upstream requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.996; 549.301 ms; worker allocation 1448456 bytes
precise requested ratio 0.500; 50000 tasks of 10000 ns; worker CPU/wall 0.452; 1036.321 ms; worker allocation 13776 bytes
upstream requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.971; 563.129 ms; worker allocation 1409664 bytes
precise requested ratio 0.050; 50000 tasks of 10000 ns; worker CPU/wall 0.100; 10276.324 ms; worker allocation 214744 bytes
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "horizon-bench"
version = "0.1.0"
edition = "2021"
license = "MIT"
description = "The benchmark report format (docs/benchmark-report.md), shared by the game, the launcher and the upload"
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
+259
View File
@@ -0,0 +1,259 @@
//! The machine a report was measured on. CPU, RAM and OS are detected here; the GPU and the display
//! come from the program that rendered (the game knows its adapter, the launcher its window).
use std::process::Command;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Hardware {
/// `macos`, `linux`, `windows`.
pub os: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub os_version: Option<String>,
pub arch: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cpu: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cpu_threads: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ram_mb: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gpu: Option<Gpu>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub display: Option<Display>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Gpu {
pub name: String,
pub vendor: String,
pub driver: String,
/// `metal`, `vulkan`, `dx12`, `gl`.
pub backend: String,
/// `integrated`, `discrete`, `virtual`, `cpu`, `other`.
pub kind: String,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Display {
/// Physical pixels.
pub width: u32,
pub height: u32,
pub scale: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub refresh_hz: Option<u32>,
}
impl Hardware {
pub fn detect() -> Hardware {
Hardware {
os: std::env::consts::OS.to_owned(),
os_version: os_version(),
arch: std::env::consts::ARCH.to_owned(),
cpu: cpu(),
cpu_threads: std::thread::available_parallelism().ok().map(|n| n.get()),
ram_mb: ram_bytes().map(|b| b >> 20),
gpu: None,
display: None,
}
}
}
/// The one-minute load average: above about the number of threads the machine was busy.
pub fn load_average() -> Option<f64> {
if cfg!(target_os = "macos") {
// "{ 1.23 1.10 1.00 }"
output("sysctl", &["-n", "vm.loadavg"])?
.trim_start_matches('{')
.split_whitespace()
.next()?
.parse()
.ok()
} else {
std::fs::read_to_string("/proc/loadavg")
.ok()?
.split_whitespace()
.next()?
.parse()
.ok()
}
}
/// `ac` or `battery`; `None` where it can't be read (and on machines without a battery on Linux).
pub fn power_source() -> Option<&'static str> {
if cfg!(target_os = "macos") {
let batt = output("pmset", &["-g", "batt"])?;
return Some(if batt.contains("'Battery Power'") {
"battery"
} else {
"ac"
});
}
let mut on_battery = None;
for entry in std::fs::read_dir("/sys/class/power_supply").ok()?.flatten() {
let read =
|name: &str| std::fs::read_to_string(entry.path().join(name)).unwrap_or_default();
match read("type").trim() {
"Mains" if read("online").trim() == "1" => return Some("ac"),
"Battery" => on_battery = Some("battery"),
_ => {}
}
}
on_battery
}
/// Resident memory of a process, in bytes (macOS, Linux).
pub fn rss_bytes(pid: u32) -> Option<u64> {
if cfg!(target_os = "macos") {
return output("ps", &["-o", "rss=", "-p", &pid.to_string()])?
.parse::<u64>()
.ok()
.map(|kb| kb * 1024);
}
let status = std::fs::read_to_string(format!("/proc/{pid}/status")).ok()?;
let line = status.lines().find(|l| l.starts_with("VmRSS:"))?;
line.split_whitespace()
.nth(1)?
.parse::<u64>()
.ok()
.map(|kb| kb * 1024)
}
/// CPU time a process has used, user and system, in seconds (macOS, Linux).
pub fn cpu_seconds(pid: u32) -> Option<f64> {
if cfg!(target_os = "macos") {
// "[[dd-]hh:]mm:ss.cc"
let time = output("ps", &["-o", "time=", "-p", &pid.to_string()])?;
let (rest, days) = match time.split_once('-') {
Some((d, rest)) => (rest.to_owned(), d.parse::<f64>().ok()?),
None => (time, 0.0),
};
let seconds = rest.split(':').try_fold(0.0, |acc, part| {
part.parse::<f64>().ok().map(|v| acc * 60.0 + v)
})?;
return Some(days * 86_400.0 + seconds);
}
// utime and stime, fields 14 and 15, in clock ticks (100 per second on Linux).
let stat = std::fs::read_to_string(format!("/proc/{pid}/stat")).ok()?;
let fields: Vec<&str> = stat.rsplit_once(')')?.1.split_whitespace().collect();
let ticks: f64 = fields.get(11)?.parse::<f64>().ok()? + fields.get(12)?.parse::<f64>().ok()?;
Some(ticks / 100.0)
}
fn output(program: &str, args: &[&str]) -> Option<String> {
let out = Command::new(program).args(args).output().ok()?;
let text = String::from_utf8(out.stdout).ok()?.trim().to_owned();
(out.status.success() && !text.is_empty()).then_some(text)
}
#[cfg(target_os = "macos")]
fn os_version() -> Option<String> {
output("sw_vers", &["-productVersion"])
}
#[cfg(target_os = "macos")]
fn cpu() -> Option<String> {
output("sysctl", &["-n", "machdep.cpu.brand_string"])
}
#[cfg(target_os = "macos")]
fn ram_bytes() -> Option<u64> {
output("sysctl", &["-n", "hw.memsize"])?.parse().ok()
}
#[cfg(target_os = "linux")]
fn os_version() -> Option<String> {
let release = std::fs::read_to_string("/etc/os-release").ok()?;
let name = key_value(&release, "PRETTY_NAME", '=')?
.trim_matches('"')
.to_owned();
Some(match output("uname", &["-r"]) {
Some(kernel) => format!("{name} (kernel {kernel})"),
None => name,
})
}
#[cfg(target_os = "linux")]
fn cpu() -> Option<String> {
let info = std::fs::read_to_string("/proc/cpuinfo").ok()?;
// x86 names the CPU per core; ARM boards name the machine once.
key_value(&info, "model name", ':')
.or_else(|| key_value(&info, "Model", ':'))
.map(str::to_owned)
}
#[cfg(target_os = "linux")]
fn ram_bytes() -> Option<u64> {
let info = std::fs::read_to_string("/proc/meminfo").ok()?;
let kb = key_value(&info, "MemTotal", ':')?
.trim_end_matches("kB")
.trim();
kb.parse::<u64>().ok().map(|kb| kb * 1024)
}
#[cfg(target_os = "linux")]
fn key_value<'a>(text: &'a str, key: &str, sep: char) -> Option<&'a str> {
text.lines().find_map(|line| {
let (k, v) = line.split_once(sep)?;
(k.trim() == key).then(|| v.trim())
})
}
#[cfg(target_os = "windows")]
fn os_version() -> Option<String> {
output("cmd", &["/C", "ver"])
}
#[cfg(target_os = "windows")]
fn cpu() -> Option<String> {
std::env::var("PROCESSOR_IDENTIFIER").ok()
}
#[cfg(target_os = "windows")]
fn ram_bytes() -> Option<u64> {
let out = output(
"powershell",
&[
"-NoProfile",
"-Command",
"(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory",
],
)?;
out.parse().ok()
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn os_version() -> Option<String> {
None
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn cpu() -> Option<String> {
None
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
fn ram_bytes() -> Option<u64> {
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn detects_this_machine() {
let hw = Hardware::detect();
assert_eq!(hw.os, std::env::consts::OS);
assert!(hw.cpu_threads.unwrap() >= 1);
if cfg!(any(target_os = "macos", target_os = "linux")) {
assert!(hw.cpu.is_some(), "{hw:?}");
assert!(hw.ram_mb.unwrap() > 256, "{hw:?}");
assert!(hw.os_version.is_some(), "{hw:?}");
assert!(load_average().is_some());
assert!(rss_bytes(std::process::id()).unwrap() > 1 << 20);
assert!(cpu_seconds(std::process::id()).unwrap() >= 0.0);
}
}
}
+457
View File
@@ -0,0 +1,457 @@
//! The benchmark report format, version 1 (docs/benchmark-report.md).
//!
//! One JSON file per run, the same for the game, the launcher and `tools/perf_bench.py`: the local log
//! a player can attach, and, with consent, what the telemetry upload sends ([`Report::for_upload`]).
//! It holds summaries and fixed-edge histogram counts, never raw frame streams.
use std::collections::BTreeMap;
use std::io;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
use serde::{Deserialize, Serialize};
mod hardware;
pub use hardware::{cpu_seconds, load_average, power_source, rss_bytes, Display, Gpu, Hardware};
pub const FORMAT: &str = "horizon-benchmark-report";
pub const VERSION: u32 = 1;
/// Lower edges of the frame-time histogram buckets, in milliseconds; the last bucket is 1000 ms and
/// over. Fixed by the format version so histograms from any number of reports add up.
pub const HISTOGRAM_EDGES_MS: [f64; 24] = [
0.0, 1.0, 2.0, 3.0, 4.17, 5.0, 6.0, 7.0, 8.33, 10.0, 12.0, 14.0, 16.67, 20.0, 25.0, 33.33,
40.0, 50.0, 66.67, 100.0, 150.0, 250.0, 500.0, 1000.0,
];
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Kind {
Game,
Launcher,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct App {
pub name: String,
pub version: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub commit: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub mods: Vec<Mod>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Mod {
pub name: String,
pub version: String,
}
/// What has to match for two reports to be compared. Every field is optional.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Conditions {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub scenario: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub seed: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub render_distance: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub simulation_distance: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub window: Option<[u32; 2]>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vsync: Option<bool>,
/// Absent: unlimited.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fps_cap: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub offscreen: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub repeats: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub warmup_s: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub power: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub load_avg_1m: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub backend: Option<String>,
}
/// A measurement over a run's repeats.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Summary {
pub n: usize,
pub mean: f64,
/// Sample standard deviation; `None` for a single value.
pub stdev: Option<f64>,
pub min: f64,
pub max: f64,
/// Half-width of the 95% confidence interval of the mean (Student's t); `None` for a single value.
pub ci95: Option<f64>,
}
impl Summary {
/// `None` for no values.
pub fn of(values: &[f64]) -> Option<Summary> {
let n = values.len();
if n == 0 {
return None;
}
let mean = values.iter().sum::<f64>() / n as f64;
let (stdev, ci95) = if n > 1 {
let var = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / (n - 1) as f64;
let sd = var.sqrt();
(Some(sd), Some(t95(n - 1) * sd / (n as f64).sqrt()))
} else {
(None, None)
};
Some(Summary {
n,
mean: round(mean),
stdev: stdev.map(round),
min: round(values.iter().copied().fold(f64::INFINITY, f64::min)),
max: round(values.iter().copied().fold(f64::NEG_INFINITY, f64::max)),
ci95: ci95.map(round),
})
}
}
/// Two-sided 95% critical value of Student's t for `df` degrees of freedom.
fn t95(df: usize) -> f64 {
const TABLE: [f64; 30] = [
12.706, 4.303, 3.182, 2.776, 2.571, 2.447, 2.365, 2.306, 2.262, 2.228, 2.201, 2.179, 2.160,
2.145, 2.131, 2.120, 2.110, 2.101, 2.093, 2.086, 2.080, 2.074, 2.069, 2.064, 2.060, 2.056,
2.052, 2.048, 2.045, 2.042,
];
TABLE.get(df.wrapping_sub(1)).copied().unwrap_or(1.96)
}
/// One measured phase of one repeat.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Frames {
pub phase: String,
pub repeat: u32,
pub frames: usize,
pub seconds: f64,
pub avg_fps: f64,
pub low_1pct_fps: f64,
pub low_01pct_fps: f64,
pub p50_ms: f64,
pub p95_ms: f64,
pub p99_ms: f64,
pub p999_ms: f64,
pub max_ms: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cpu_p50_ms: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gpu_p50_ms: Option<f64>,
/// Frame counts per bucket of [`HISTOGRAM_EDGES_MS`].
pub histogram: Vec<u64>,
}
impl Frames {
/// The figures of a phase from its frame times in milliseconds (time between the starts of
/// consecutive frames); `None` for no frames. CPU and GPU times are per frame too, when measured.
pub fn of(
phase: &str,
repeat: u32,
frame_ms: &[f32],
cpu_ms: &[f32],
gpu_ms: &[f32],
) -> Option<Frames> {
let times = sorted(frame_ms);
let n = times.len();
if n == 0 {
return None;
}
let total: f64 = times.iter().sum();
// The average frame time of the slowest `share` of frames, as frames per second.
let low = |share: f64| {
let slowest = &times[n - ((n as f64 * share).ceil() as usize).max(1)..];
1000.0 * slowest.len() as f64 / slowest.iter().sum::<f64>()
};
let mut histogram = vec![0; HISTOGRAM_EDGES_MS.len()];
for &t in &times {
histogram[HISTOGRAM_EDGES_MS.partition_point(|&edge| edge <= t).max(1) - 1] += 1;
}
Some(Frames {
phase: phase.to_owned(),
repeat,
frames: n,
seconds: round(total / 1000.0),
avg_fps: round(n as f64 * 1000.0 / total),
low_1pct_fps: round(low(0.01)),
low_01pct_fps: round(low(0.001)),
p50_ms: round(percentile(&times, 0.5)),
p95_ms: round(percentile(&times, 0.95)),
p99_ms: round(percentile(&times, 0.99)),
p999_ms: round(percentile(&times, 0.999)),
max_ms: round(times[n - 1]),
cpu_p50_ms: (!cpu_ms.is_empty()).then(|| round(percentile(&sorted(cpu_ms), 0.5))),
gpu_p50_ms: (!gpu_ms.is_empty()).then(|| round(percentile(&sorted(gpu_ms), 0.5))),
histogram,
})
}
}
fn sorted(ms: &[f32]) -> Vec<f64> {
let mut v: Vec<f64> = ms
.iter()
.map(|&m| f64::from(m))
.filter(|m| m.is_finite())
.collect();
v.sort_by(f64::total_cmp);
v
}
/// Three decimals: plenty for milliseconds and FPS, short in JSON, and parsed back exactly.
fn round(v: f64) -> f64 {
(v * 1000.0).round() / 1000.0
}
/// Nearest-rank percentile of sorted, non-empty values.
fn percentile(sorted: &[f64], p: f64) -> f64 {
let n = sorted.len();
sorted[((n as f64 * p).ceil() as usize).clamp(1, n) - 1]
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Report {
pub format: String,
pub version: u32,
pub kind: Kind,
/// When the run ended, UTC, `YYYY-MM-DDTHH:MM:SSZ`.
pub created: String,
pub app: App,
pub hardware: Hardware,
#[serde(default)]
pub conditions: Conditions,
/// Scalar measurements by name; the unit is the name's suffix (`_ms`, `_mb`...).
#[serde(default)]
pub metrics: BTreeMap<String, Summary>,
#[serde(default)]
pub frames: Vec<Frames>,
/// Local only: a name the person running it chose.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
/// Local only: logs the run wrote next to the report.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub local: Vec<PathBuf>,
}
impl Report {
/// An empty report for this machine, created now.
pub fn new(kind: Kind, app: App) -> Report {
Report {
format: FORMAT.to_owned(),
version: VERSION,
kind,
created: utc_now(),
app,
hardware: Hardware::detect(),
conditions: Conditions::default(),
metrics: BTreeMap::new(),
frames: Vec::new(),
label: None,
local: Vec::new(),
}
}
/// Records a measurement over the repeats; no values records nothing.
pub fn metric(&mut self, name: &str, values: &[f64]) {
if let Some(summary) = Summary::of(values) {
self.metrics.insert(name.to_owned(), summary);
}
}
/// Reads a report, rejecting other formats and newer versions.
pub fn parse(json: &str) -> Result<Report, String> {
let report: Report = serde_json::from_str(json).map_err(|e| e.to_string())?;
if report.format != FORMAT {
return Err(format!(
"not a benchmark report: format {:?}",
report.format
));
}
if report.version > VERSION {
return Err(format!(
"report version {} is newer than {VERSION}",
report.version
));
}
Ok(report)
}
/// The report without its local-only fields, dated to the day: what an upload sends.
pub fn for_upload(&self) -> Report {
let day = self.created.get(..10).unwrap_or_default();
Report {
label: None,
local: Vec::new(),
created: format!("{day}T00:00:00Z"),
..self.clone()
}
}
pub fn to_json(&self) -> String {
serde_json::to_string_pretty(self).expect("a report always serializes")
}
/// Writes `<dir>/<kind>-<created>-<scenario>.json` and returns its path.
pub fn write_to(&self, dir: &Path) -> io::Result<PathBuf> {
std::fs::create_dir_all(dir)?;
let kind = match self.kind {
Kind::Game => "game",
Kind::Launcher => "launcher",
};
let stamp: String = self.created.chars().filter(char::is_ascii_digit).collect();
let scenario: String = self
.conditions
.scenario
.as_deref()
.unwrap_or("run")
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || c == '-' {
c
} else {
'_'
}
})
.collect();
let path = dir.join(format!("{kind}-{stamp}-{scenario}.json"));
std::fs::write(&path, self.to_json() + "\n")?;
Ok(path)
}
}
/// The current time, UTC, `YYYY-MM-DDTHH:MM:SSZ`.
pub fn utc_now() -> String {
let secs = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |d| d.as_secs());
utc(secs)
}
fn utc(secs: u64) -> String {
let (days, rem) = (secs / 86_400, secs % 86_400);
// Civil date from days since 1970-01-01 (Howard Hinnant's algorithm).
let z = days as i64 + 719_468;
let era = z.div_euclid(146_097);
let doe = z - era * 146_097;
let yoe = (doe - doe / 1460 + doe / 36_524 - doe / 146_096) / 365;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let day = doy - (153 * mp + 2) / 5 + 1;
let month = if mp < 10 { mp + 3 } else { mp - 9 };
let year = yoe + era * 400 + i64::from(month <= 2);
format!(
"{year:04}-{month:02}-{day:02}T{:02}:{:02}:{:02}Z",
rem / 3600,
rem / 60 % 60,
rem % 60
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn utc_dates() {
assert_eq!(utc(0), "1970-01-01T00:00:00Z");
assert_eq!(utc(951_782_400), "2000-02-29T00:00:00Z");
assert_eq!(utc(1_791_983_007), "2026-10-14T13:03:27Z");
}
#[test]
fn summary_of_repeats() {
assert_eq!(Summary::of(&[]), None);
let one = Summary::of(&[5.0]).unwrap();
assert_eq!((one.n, one.mean, one.stdev, one.ci95), (1, 5.0, None, None));
let s = Summary::of(&[2.0, 4.0, 6.0]).unwrap();
assert_eq!((s.mean, s.min, s.max), (4.0, 2.0, 6.0));
assert_eq!(s.stdev, Some(2.0));
assert_eq!(s.ci95, Some(4.969), "4.303 * 2 / sqrt(3)");
}
#[test]
fn frame_figures_and_histogram() {
// 998 frames of 2 ms, one of 20 ms, one of 1500 ms.
let mut ms = vec![2.0f32; 998];
ms.extend([20.0, 1500.0]);
let f = Frames::of("flight", 0, &ms, &[], &[]).unwrap();
assert_eq!(f.frames, 1000);
assert_eq!(f.seconds, 3.516);
assert_eq!((f.p50_ms, f.p999_ms, f.max_ms), (2.0, 20.0, 1500.0));
// Slowest 1% = 10 frames: 8 of 2 ms, 20 ms, 1500 ms.
assert_eq!(f.low_1pct_fps, 6.51, "1000 * 10 / 1536");
// Slowest 0.1% = the 1500 ms frame.
assert_eq!(f.low_01pct_fps, 0.667);
assert_eq!(f.histogram.len(), HISTOGRAM_EDGES_MS.len());
assert_eq!(f.histogram[2], 998, "2 ms falls in [2, 3)");
assert_eq!(f.histogram[13], 1, "20 ms falls in [20, 25)");
assert_eq!(f.histogram[23], 1, "1500 ms falls in [1000, inf)");
assert_eq!(f.histogram.iter().sum::<u64>(), 1000);
assert_eq!((f.cpu_p50_ms, f.gpu_p50_ms), (None, None));
assert_eq!(Frames::of("x", 0, &[], &[], &[]), None);
}
#[test]
fn round_trip_and_upload_strips_local_fields() {
let mut r = Report::new(
Kind::Game,
App {
name: "horizon-client".into(),
version: "0.1.0".into(),
..App::default()
},
);
r.conditions.scenario = Some("flight".into());
r.metric("startup.title_ms", &[800.0, 820.0]);
r.frames
.extend(Frames::of("village", 0, &[2.0, 3.0], &[1.0], &[]));
r.label = Some("my run".into());
r.local.push("/home/someone/logs/latest.log".into());
let back = Report::parse(&r.to_json()).unwrap();
assert_eq!(back, r);
r.created = "2026-10-15T14:03:27Z".into();
let upload = r.for_upload();
assert_eq!(upload.created, "2026-10-15T00:00:00Z", "the day only");
let upload = upload.to_json();
assert!(
!upload.contains("my run") && !upload.contains("someone"),
"{upload}"
);
}
#[test]
fn rejects_other_formats_and_newer_versions() {
let r = Report::new(Kind::Launcher, App::default());
let newer = r.to_json().replace("\"version\": 1", "\"version\": 2");
assert!(Report::parse(&newer).unwrap_err().contains("newer"));
let other = r.to_json().replace(FORMAT, "something-else");
assert!(Report::parse(&other).is_err());
}
#[test]
fn writes_into_a_folder() {
let dir = std::env::temp_dir().join(format!("horizon-bench-test-{}", std::process::id()));
let mut r = Report::new(Kind::Launcher, App::default());
r.created = "2026-10-15T14:03:27Z".into();
r.conditions.scenario = Some("cold start".into());
let path = r.write_to(&dir).unwrap();
assert_eq!(
path.file_name().unwrap(),
"launcher-20261015140327-cold_start.json"
);
assert_eq!(
Report::parse(&std::fs::read_to_string(&path).unwrap()).unwrap(),
r
);
std::fs::remove_dir_all(dir).unwrap();
}
}
+25
View File
@@ -12,16 +12,37 @@ horizon-assets = { path = "../horizon-assets" }
horizon-core = { path = "../horizon-core" }
horizon-world = { path = "../horizon-world" }
horizon-protocol = { path = "../horizon-protocol" }
horizon-friends = { path = "../horizon-friends" }
wgpu = { version = "30.0.1", default-features = false, features = ["std", "parking_lot", "vulkan", "metal", "wgsl"] }
winit = "0.30.13"
pollster = "0.4"
bytemuck = { version = "1.24", features = ["derive"] }
glam = "0.30"
png = "0.18"
sha2 = "0.10.9"
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1.0.151", features = ["raw_value"] }
cpal = "0.16"
symphonia = { version = "0.5", default-features = false, features = ["ogg", "vorbis"] }
miniz_oxide = "0.8"
ab_glyph = "0.2.32"
log = "0.4"
chrono = { version = "0.4.42", default-features = false, features = ["clock", "std"] }
flate2 = { version = "1.1.10", default-features = false, features = ["rust_backend"] }
horizon-theme = { path = "../horizon-theme" }
# Opt-in data collection: the game keeps, the launcher sends (docs/telemetry.md).
horizon-telemetry = { path = "../horizon-telemetry", default-features = false }
horizon-bench = { path = "../horizon-bench" }
arboard = { version = "3.6.1", default-features = false, features = ["wayland-data-control"] }
zip = { version = "2", default-features = false, features = ["deflate"] }
# Controllers (evdev + libudev on Linux, IOKit on macOS, Windows.Gaming.Input).
gilrs = "0.11"
# HTTPS to the Minecraft services (online-mode session join).
ureq = { version = "2", default-features = false, features = ["tls"] }
[target.'cfg(windows)'.build-dependencies]
# The icon resource in the .exe (build.rs).
winresource = "0.1"
[features]
# Records the call sites of mob random draws (`mob_ai_probe` traces).
@@ -29,3 +50,7 @@ rng-trace = ["horizon-core/rng-trace"]
[lints]
workspace = true
[dev-dependencies]
# Parses and validates the composed entity shader (already built for wgpu).
naga = { version = "30.0.1", features = ["wgsl-in"] }
+15
View File
@@ -0,0 +1,15 @@
//! Embeds Horizon's icon (`packaging/icons/horizon.ico`) in the Windows executables, as icon
//! resource 1: Explorer and the task bar show it, and the window takes it as its icon.
fn main() {
let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_default();
let ico = format!("{dir}/../../packaging/icons/horizon.ico");
println!("cargo:rerun-if-changed={ico}");
#[cfg(windows)]
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
let mut resource = winresource::WindowsResource::new();
resource.set_icon(&ico);
if let Err(e) = resource.compile() {
panic!("embedding {ico}: {e}");
}
}
}
@@ -0,0 +1,313 @@
//! Arrows over the client's resident scene (`arrows::tick`), for
//! tools/test_arrow_parity.py: one line of state and one of events per operation.
#![forbid(unsafe_code)]
use horizon_client::{
Result,
arrows::{
self, ArrowEvent, ArrowParticle, ArrowScene, ArrowSound, BlockReaction, Pickup, Touch,
},
assets::Assets,
blocks::BlockFacts,
collisions,
items::ItemStack,
mobs::Who,
motion::{LAVA, MotionResources, WATER},
projectiles::{Projectile, ProjectileKind},
world::World,
};
use horizon_core::{
geometry::Vec3,
random::{LegacyRandom, RandomSource},
};
use serde_json::Value;
use std::{
fs,
io::{BufRead, Write},
path::PathBuf,
};
fn number(v: &Value) -> f64 {
f64::from_bits(u64::from_str_radix(v.as_str().unwrap(), 16).unwrap())
}
fn vector(v: &Value) -> Vec3 {
Vec3::new(number(&v[0]), number(&v[1]), number(&v[2]))
}
fn bits(v: Vec3) -> String {
format!(
"{:016x},{:016x},{:016x}",
v.x.to_bits(),
v.y.to_bits(),
v.z.to_bits()
)
}
fn seed(v: &Value) -> i64 {
v.as_str().unwrap().parse().unwrap()
}
fn particle(k: ArrowParticle) -> &'static str {
match k {
ArrowParticle::Bubble => "bubble",
ArrowParticle::Crit => "crit",
ArrowParticle::Splash => "splash",
}
}
fn main() -> Result<()> {
let args: Vec<_> = std::env::args().skip(1).collect();
if args.len() != 3 {
return Err("usage: arrow_probe RESOURCES FIXTURE_DIRECTORY --describe|REFERENCE".into());
}
let root = PathBuf::from(&args[0]);
let dir = PathBuf::from(&args[1]);
let assets = Assets::load(&root)?;
let mut scene = World::test_scene(&assets, 1)?;
fs::write(
dir.join("scene.json"),
serde_json::to_vec(
&serde_json::json!({"radius":1,"resident_chunks":scene.chunks.len(),"model_gallery":assets.model_gallery}),
)?,
)?;
if args[2] == "--describe" {
return Ok(());
}
let binding = collisions::load(&root, assets.registry)?;
let motion = MotionResources::load(&root, &assets)?;
let facts = BlockFacts::load(&root, assets.registry)?;
let side = &args[2];
let mut out = std::io::BufWriter::new(fs::File::create(dir.join(format!("rust-{side}.txt")))?);
let mut level_random = LegacyRandom::new(0);
for line in std::io::BufReader::new(fs::File::open(dir.join("inputs.txt"))?).lines() {
let f: Value = serde_json::from_str(&line?)?;
let kind = ProjectileKind::Arrow {
base_damage: 2.0,
critical: f["crit"].as_bool().unwrap(),
effect: None,
};
let mut arrow = Projectile::new(kind, vector(&f["position"]), None)
.with_arrow_random(LegacyRandom::new(seed(&f["seed"])));
arrow.velocity = vector(&f["velocity"]);
arrow.arrow.as_mut().unwrap().no_physics = f["no_physics"].as_bool().unwrap();
// ProjectileWeaponItem.useAmmo's stack, intangible when no ammo was used.
arrow.arrow.as_mut().unwrap().set_item(&arrows::drawn_ammo(
&ItemStack::new("minecraft:arrow", 1),
f["intangible"].as_bool().unwrap(),
));
for op in f["ops"].as_array().unwrap() {
let mut events = Vec::new();
let mut touched = "-".to_string();
match op["mode"].as_str().unwrap() {
"tick" => {
if !arrow.arrow.as_ref().unwrap().removed {
let no_rain = |_| false;
let view = ArrowScene {
world: &scene,
registry: assets.registry,
facts: &facts,
collision: &binding,
fluids: &motion.fluids,
raining: &no_rain,
mob_griefing: true,
tnt_explodes: true,
};
arrows::tick(&mut arrow, &view, &[]);
}
for event in arrow.arrow.as_mut().unwrap().events.drain(..) {
match event {
ArrowEvent::Particle {
kind,
position,
velocity,
} => events.push(format!(
"particle {} {} {}",
particle(kind),
bits(position),
bits(velocity)
)),
ArrowEvent::Sound {
sound,
volume,
pitch,
} => events.push(format!(
"sound {} {:08x} {:08x}",
match sound {
ArrowSound::HitGround => "hit",
ArrowSound::Splash => "splash",
ArrowSound::Extinguish => "extinguish",
},
volume.to_bits(),
pitch.to_bits()
)),
ArrowEvent::BubbleColumnParticles { pos } => {
for _ in 0..2 {
let x = f64::from(pos.x) + level_random.next_double();
let z = f64::from(pos.z) + level_random.next_double();
let at = Vec3::new(x, f64::from(pos.y + 1), z);
events.push(format!(
"sent splash {} {} {:016x}",
bits(at),
bits(Vec3::ZERO),
1.0f64.to_bits()
));
let x = f64::from(pos.x) + level_random.next_double();
let z = f64::from(pos.z) + level_random.next_double();
let at = Vec3::new(x, f64::from(pos.y + 1), z);
events.push(format!(
"sent bubble {} {} {:016x}",
bits(at),
bits(Vec3::new(0.0, 0.01, 0.0)),
0.2f64.to_bits()
));
}
}
ArrowEvent::Block { pos, reaction } => match reaction {
BlockReaction::PrimeTnt => {
// TntBlock.prime: PrimedTnt draws its push from the
// level random, then removeBlock(pos, false).
let _ = level_random.next_double();
let at = Vec3::new(
f64::from(pos.x) + 0.5,
f64::from(pos.y),
f64::from(pos.z) + 0.5,
);
events.push(format!("spawn tnt {} 80", bits(at)));
events.push(format!(
"sound tnt_primed {:08x} {:08x}",
1.0f32.to_bits(),
1.0f32.to_bits()
));
events.push("prime-event".into());
let air =
assets.registry.default_state("minecraft:air").unwrap();
scene.set(pos.x, pos.y, pos.z, air)?;
events.push(format!(
"write {},{},{} {} 3",
pos.x, pos.y, pos.z, air.0
));
}
BlockReaction::Light(lit) => {
scene.set(pos.x, pos.y, pos.z, lit)?;
events.push(format!(
"write {},{},{} {} 11",
pos.x, pos.y, pos.z, lit.0
));
}
},
ArrowEvent::SplashEvent => events.push("splash-event".into()),
ArrowEvent::ShootEvent => events.push("shoot-event".into()),
}
}
}
"block" => {
let p = &op["position"];
let mut state = assets
.registry
.default_state(op["name"].as_str().unwrap())
.ok_or("missing fixture block")?;
if let Some(properties) = op["properties"].as_object() {
let mut definition = assets.registry.state(state).unwrap().clone();
for (name, value) in properties {
definition
.properties
.insert(name.clone(), value.as_str().unwrap().into());
}
state = assets
.registry
.id(&definition)
.ok_or("missing fixture state")?;
}
scene.set(
p[0].as_i64().unwrap() as i32,
p[1].as_i64().unwrap() as i32,
p[2].as_i64().unwrap() as i32,
state,
)?;
}
"velocity" => arrow.velocity = vector(&op["value"]),
"ignite" => arrow
.arrow
.as_mut()
.unwrap()
.ignite_for_seconds(f32::from_bits(
u32::from_str_radix(op["value"].as_str().unwrap(), 16).unwrap(),
)),
"level_seed" => level_random.set_seed(seed(&op["value"])),
"owner" => arrow
.arrow
.as_mut()
.unwrap()
.set_owner(match op["value"].as_str() {
Some("player") => Some(Who::Player),
Some("mob") => Some(Who::Mob(1)),
_ => None,
}),
"pickup" => {
arrow.arrow.as_mut().unwrap().pickup =
Pickup::from_byte(op["value"].as_i64().unwrap())
}
// The game's touch: the inventory takes the arrow unless full,
// and a creative player takes it anyway.
"touch" => {
let creative = op["creative"].as_bool().unwrap();
let full = op["inventory"] == "full";
let a = arrow.arrow.as_mut().unwrap();
let (taken, arrows) = match a.player_touch(creative) {
Touch::Ignore => (false, 0),
Touch::Take => (true, 0),
Touch::Give(_) => (!full || creative, u32::from(!full)),
};
if taken {
a.removed = true;
}
touched = format!("{taken} {arrows}");
}
other => return Err(format!("unknown operation {other}").into()),
}
let a = arrow.arrow.as_ref().unwrap();
writeln!(
out,
"arrow {} {} {:08x} {:08x} {} {} {} {} {} {} {} {} {} {:016x} {:016x} {} {} {:016x} {}",
bits(arrow.position),
bits(arrow.velocity),
arrow.pitch.to_bits(),
arrow.yaw.to_bits(),
a.in_ground,
a.in_ground_time,
a.life,
a.shake,
a.last_state.map_or("none".into(), |s| s.0.to_string()),
a.fire_ticks,
a.was_touching_water,
a.was_eye_in_water,
a.first_tick,
a.fluids.fluid_height(&Tags, WATER).to_bits(),
a.fluids.fluid_height(&Tags, LAVA).to_bits(),
a.removed,
arrow.critical(),
a.fall_distance.to_bits(),
bits(arrow.previous)
)?;
writeln!(out, "events {}", events.join(" | "))?;
let a = arrow.arrow.as_ref().unwrap();
let intangible = a
.pickup_item
.data()
.and_then(|d| d.other(arrows::INTANGIBLE))
.is_some();
writeln!(out, "pickup {} {intangible} {touched}", a.pickup.byte())?;
}
writeln!(out, "end")?;
}
Ok(())
}
struct Tags;
impl horizon_world::entity_fluid::FluidMembership for Tags {
fn fluid_in_tag(
&self,
kind: horizon_world::fluid::FluidKind,
tag: horizon_world::entity_fluid::FluidTagId,
) -> bool {
use horizon_world::fluid::FluidKind;
if tag == WATER {
matches!(kind, FluidKind::Water | FluidKind::FlowingWater)
} else {
matches!(kind, FluidKind::Lava | FluidKind::FlowingLava)
}
}
}
@@ -8,9 +8,10 @@ use horizon_client::{
assets::Assets,
block_entity_anim::{
Bell, BellEntity, BlockEntityAnims, ChestLid, Conduit, ConduitTarget, DIRECTIONS,
PotWobble, Shulker, ShulkerStatus, Skull, WobbleStyle, chest_lid_x_rot, direction_index,
EndGateway, PotWobble, Shulker, ShulkerStatus, Skull, WobbleStyle, chest_lid_x_rot,
direction_index,
},
block_entity_render::BlockEntityRenderer,
block_entity_render::{BlockEntityRenderer, gateway_beam},
blocks::{BlockFacts, Fluid},
items::Items,
};
@@ -188,6 +189,14 @@ fn main() -> Result<()> {
let facing = prop(&block, "facing")
.and_then(direction_index)
.unwrap_or(1);
// End gateways: the saved age, the level's height range and the
// integrated server's copy.
let initial = EndGateway {
age: case["age"].as_i64().unwrap_or(0),
teleport_cooldown: 0,
};
let max_y = int(&case["level"][0]) + int(&case["level"][1]) - 1;
let mut server = initial;
let mut text = String::new();
for step in case["steps"].as_array().into_iter().flatten() {
let time = step["time"].as_i64().unwrap_or(0);
@@ -445,6 +454,36 @@ fn main() -> Result<()> {
f(progress),
style
);
} else if name == "minecraft:end_gateway" {
let client = anims.gateways.entry(pos).or_insert(initial);
if step["enter"].as_bool() == Some(true) && server.enter() {
log.push_str(" blockEvent 1 0");
client.trigger_event(1, 0);
}
if server.portal_tick() {
log.push_str(" blockEvent 1 0");
client.trigger_event(1, 0);
}
if let Some((e0, e1)) = event {
let handled = client.trigger_event(e0, e1);
let _ = write!(log, " event {handled}");
}
client.tick();
let g = *client;
let a = anims.block_anim(pos, time, partial, Default::default());
let b = gateway_beam(a.gateway, partial, max_y, time);
let _ = write!(
text,
"{} {} server {} {} render {} {} {:x} {}",
g.age,
g.teleport_cooldown,
server.age,
server.teleport_cooldown,
b.height,
f(b.scale),
b.color,
f(b.animation_time)
);
} else {
text = format!("unsupported {block}");
}
@@ -13,6 +13,7 @@ use horizon_client::{
},
chunk::{Chunk, Light},
hud::{HudAtlas, Rect},
item_render::{ItemRenderer, gui},
signs::{DYE_TEXT, SignData, SignText},
world::World,
};
@@ -119,6 +120,7 @@ fn main() -> Result<()> {
let renderer = BlockEntityRenderer::load(root, registry)?;
let atlas = HudAtlas::build(root)?;
let banners = Banners::load(root);
let items = ItemRenderer::load(root)?;
let (sprites, names, grid) = fake_sprites(textures)?;
let air = registry.default_state("minecraft:air").ok_or("no air")?;
let mut out = BufWriter::new(fs::File::create(output)?);
@@ -128,6 +130,43 @@ fn main() -> Result<()> {
{
let case: Value = serde_json::from_str(line)?;
let block = case["block"].as_str().unwrap_or_default();
if let Some(loom) = case.get("loom") {
// The loom's result preview, as LoomScreen draws it at (0, 0).
let layers: Vec<(String, String)> = loom["patterns"]
.as_array()
.into_iter()
.flatten()
.map(|p| {
(
banners.banner_texture(p[0].as_str().unwrap_or_default()),
p[1].as_str().unwrap_or_default().to_owned(),
)
})
.collect();
let base = loom["base"].as_str().unwrap_or_default();
let flat = gui::items_flat_lights();
let quads: Vec<Value> =
gui::banner_result_quads(&items, &sprites, 0.0, 0.0, base, &layers)
.iter()
.map(|q| {
let (cu, cv) = ((q.uv[0][0] / 2.0).floor(), (q.uv[0][1] / 2.0).floor());
let texture = names
.get(cu as usize + cv as usize * grid)
.cloned()
.unwrap_or_default();
let v: Vec<Value> = (0..4)
.map(|k| {
let p = q.pos[k];
json!([p.x, p.y, p.z, q.uv[k][0] - cu * 2.0, q.uv[k][1] - cv * 2.0])
})
.collect();
// Full bright (15728880).
json!({"texture": texture, "v": v, "color": gui::lit_color(q, flat), "light": 0xF0F0})
})
.collect();
writeln!(out, "{}", json!({"quads": quads, "texts": []}))?;
continue;
}
if block == "minecraft:beacon" {
// BeaconRenderer: the beam sections from the case, as Horizon's beacon keeps them.
let int = |v: &Value| v.as_i64().unwrap_or(0);
@@ -0,0 +1,61 @@
//! Transport for ClientLevel shape-aware terrain-particle placement.
use horizon_client::{assets::Assets, blocks::BlockFacts, mesher::MeshTables, models, particles};
use horizon_core::random::{LegacyRandom, RandomSource};
use horizon_world::registry::BlockStateId;
use serde_json::{Value, json};
use std::{
fs,
io::{BufRead, BufReader, BufWriter, Write},
path::Path,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<_> = std::env::args().collect();
let root = Path::new(&args[1]);
let assets = Assets::load(root)?;
let facts = BlockFacts::load(root, assets.registry)?;
let tables = MeshTables::new(
&assets,
&facts,
models::load_visibility(root, assets.registry)?,
)?;
let mut output = BufWriter::new(fs::File::create(&args[3])?);
for line in BufReader::new(fs::File::open(&args[2])?).lines() {
let row: Value = serde_json::from_str(&line?)?;
let state = BlockStateId(row["state"].as_u64().unwrap() as u32);
let pos: [i32; 3] = serde_json::from_value(row["pos"].clone())?;
let offset = if facts.get(state).outline_offset {
tables.offset(state, pos[0], pos[2]).unwrap_or([0.0; 3])
} else {
[0.0; 3]
};
let boxes: Vec<[f64; 6]> = facts
.get(state)
.outline
.iter()
.map(|b| std::array::from_fn(|i| b[i] + offset[i % 3]))
.collect();
let mut hits = Vec::new();
let mut next = Vec::new();
for face in [
[0, -1, 0],
[0, 1, 0],
[0, 0, -1],
[0, 0, 1],
[-1, 0, 0],
[1, 0, 0],
] {
let mut random = LegacyRandom::new(row["seed"].as_i64().unwrap());
hits.push(particles::breaking_position(&mut random, pos, face, &boxes));
next.push(random.next_long());
}
let mut destroy = Vec::new();
particles::destroy_positions(pos, &boxes, |p, _| destroy.push(p));
serde_json::to_writer(
&mut output,
&json!({"case":row["case"],"hits":hits,"next":next,"destroy":destroy}),
)?;
output.write_all(&[10])?;
}
output.flush()?;
Ok(())
}
@@ -0,0 +1,74 @@
//! Headless transport for real model-shaped breaking overlays.
use horizon_client::{
assets::Assets,
blocks::{BlockFacts, RenderShape},
breaking,
mesher::MeshTables,
models,
};
use horizon_core::position::BlockPos;
use horizon_world::registry::BlockStateId;
use serde_json::{Value, json};
use std::{
fs,
io::{BufRead, BufReader, BufWriter, Write},
path::Path,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<_> = std::env::args().collect();
let root = Path::new(&args[1]);
let assets = Assets::load(root)?;
let facts = BlockFacts::load(root, assets.registry)?;
let tables = MeshTables::new(
&assets,
&facts,
models::load_visibility(root, assets.registry)?,
)?;
let mut output = BufWriter::new(fs::File::create(&args[3])?);
for line in BufReader::new(fs::File::open(&args[2])?).lines() {
let row: Value = serde_json::from_str(&line?)?;
let state = BlockStateId(row["state"].as_u64().unwrap() as u32);
let p: [i32; 3] = serde_json::from_value(row["pos"].clone())?;
let camera: [f64; 3] = serde_json::from_value(row["camera"].clone())?;
let mut vertices = Vec::new();
let mut translucent = false;
if facts.get(state).render_shape == RenderShape::Model {
let models = assets
.model_catalog
.collect(state, BlockPos::new(p[0], p[1], p[2]))?;
let offset = tables.offset(state, p[0], p[2]).unwrap_or([0.0; 3]);
let origin = (glam::DVec3::new(f64::from(p[0]), f64::from(p[1]), f64::from(p[2]))
- glam::DVec3::from(camera))
.as_vec3()
+ glam::DVec3::from(offset).as_vec3();
translucent = models
.iter()
.any(|(_, m)| m.faces.iter().any(|f| f.translucent));
for (_, m) in models {
breaking::geometry(m, origin, translucent, &mut vertices);
}
}
let quads: Vec<_> = vertices
.as_chunks::<4>()
.0
.iter()
.map(|q| {
q.iter()
.map(|v| {
assert_eq!(v.color, 0xffff_ffff);
assert_eq!(v.light, 240 | (240 << 8));
assert_eq!(v.layer, if translucent { 12 } else { 11 });
[v.pos[0], v.pos[1], v.pos[2], v.uv[0], v.uv[1]]
})
.collect::<Vec<_>>()
})
.collect();
serde_json::to_writer(
&mut output,
&json!({"case":row["case"],"translucent":translucent,"quads":quads}),
)?;
output.write_all(&[10])?;
}
output.flush()?;
Ok(())
}
+10 -1
View File
@@ -5,7 +5,7 @@ use horizon_client::{
Result,
camera::{
AvatarBob, BobState, Camera, CameraEntity, CameraFluid, CameraType, FovPlayer, HurtBob,
LivingCamera, UseItem, bob_matrix, field_of_view_modifier,
LivingCamera, UseItem, bob_matrix, field_of_view_modifier, perspective,
},
};
use horizon_core::{
@@ -258,6 +258,15 @@ fn camera(c: &Value, out: &mut impl Write) -> Result<()> {
fb(fov),
fb(hud)
)?;
let (w, h, far) = (fl(&op[4]), fl(&op[5]), fl(&op[6]));
let matrix =
|m: [f32; 16]| m.iter().map(|&x| format!(" {}", fb(x))).collect::<String>();
writeln!(
out,
"projection{}{}",
matrix(perspective(fov, w, h, far, 0.05, true)),
matrix(perspective(hud, w, h, far, 0.05, true))
)?;
}
other => panic!("{other}"),
}
@@ -80,10 +80,14 @@ fn main() -> horizon_client::Result<()> {
let items = Items::catalog(root)?;
let recipes = Recipes::load(root, &items)?;
let brewing = horizon_client::brewing::Brewing::load(root, &items);
// The inventory menu never reads banner patterns.
let banners = horizon_client::banner::Banners::default();
let env = Env {
items: &items,
recipes: &recipes,
brewing: &brewing,
banners: &banners,
trade: None,
};
let mut out = String::new();
for line in input.lines() {
@@ -0,0 +1,132 @@
//! The chat screen's input for tools/test_chat_screen_parity.py: reads one
//! JSON case per line (GUI size, history, options, typed text, keys,
//! clicks, mouse), runs `horizon_client::chat::ChatScreen` on the vanilla
//! command tree and writes the input's state and the screen's GUI calls in
//! the oracle's JSON form.
//!
//! usage: chat_screen_fixture RESOURCES REGISTRIES CASES OUTPUT
use horizon_client::{
chat::{ChatAction, ChatScreen, Commands},
command::vanilla,
hud::HudAtlas,
lang,
screen_draw::Measure,
};
use serde_json::{Value, json};
use std::{fmt::Write as _, fs, path::PathBuf};
use winit::keyboard::KeyCode as K;
#[path = "pack_screen_fixture.rs"]
#[allow(dead_code)]
mod pack_screen_fixture;
#[path = "chat_screen_fixture/registries.rs"]
mod registries;
fn main() -> horizon_client::Result<()> {
let args: Vec<PathBuf> = std::env::args_os().skip(1).map(PathBuf::from).collect();
let [root, registries, inputs, output] = args.as_slice() else {
return Err("usage: chat_screen_fixture RESOURCES REGISTRIES CASES OUTPUT".into());
};
let atlas = HudAtlas::build(root)?;
lang::set(lang::Language::load(&[root], lang::DEFAULT));
let m = Measure(&atlas.font);
let reg = registries::registries(&serde_json::from_slice(&fs::read(registries)?)?, 4);
let c = Commands {
dispatcher: vanilla::release_dispatcher(),
registries: &reg,
};
let mut out = String::new();
for line in fs::read_to_string(inputs)?
.lines()
.filter(|l| !l.is_empty())
{
let case: Value = serde_json::from_str(line)?;
let int = |v: &Value| v.as_i64().unwrap_or(0) as i32;
let history: Vec<String> = case["history"]
.as_array()
.into_iter()
.flatten()
.filter_map(|s| s.as_str().map(str::to_owned))
.collect();
let (w, h) = (int(&case["width"]), int(&case["height"]));
let mut screen = ChatScreen::new(
&m,
&c,
case["initial"].as_str().unwrap_or(""),
history.len(),
w,
h,
);
screen.auto_suggestions = case["autoSuggest"] == true;
let mut closed = false;
for a in case["actions"].as_array().into_iter().flatten() {
match a["type"].as_str().unwrap_or_default() {
"type" => screen.type_text(&m, &c, a["text"].as_str().unwrap_or_default()),
"click" => {
screen.click(
&m,
&c,
a["x"].as_f64().unwrap_or(0.0),
a["y"].as_f64().unwrap_or(0.0),
);
}
"key" => {
let mut name = a["key"].as_str().unwrap_or_default();
let (mut shift, mut ctrl) = (false, false);
loop {
if let Some(n) = name.strip_prefix("shift+") {
shift = true;
name = n;
} else if let Some(n) = name.strip_prefix("ctrl+") {
ctrl = true;
name = n;
} else {
break;
}
}
let key = match name {
"backspace" => K::Backspace,
"delete" => K::Delete,
"home" => K::Home,
"end" => K::End,
"right" => K::ArrowRight,
"left" => K::ArrowLeft,
"down" => K::ArrowDown,
"up" => K::ArrowUp,
"tab" => K::Tab,
"escape" => K::Escape,
_ => K::KeyA,
};
// InputQuirks.EDIT_SHORTCUT_KEY_MODIFIER: Cmd, not Ctrl, on macOS.
let ctrl = ctrl && !cfg!(target_os = "macos");
if screen.key(&m, &c, &history, key, shift, ctrl) != ChatAction::None {
closed = true;
break;
}
}
_ => {}
}
}
if closed {
writeln!(out, "{}", json!({"closed": true}))?;
continue;
}
// Options.getBackgroundColor(Integer.MIN_VALUE).
let background = if case["chatOnly"] == true {
i32::MIN
} else {
let a = (case["opacity"].as_f64().unwrap_or(0.0) as f32 * 255.0).floor() as i32;
a << 24
};
let mouse = (int(&case["mouse"][0]), int(&case["mouse"][1]));
let draws = screen.draw(&m, mouse, case["blink"].as_u64().unwrap_or(0), background);
let input = &screen.input;
writeln!(
out,
"{}",
json!({"value": input.value, "cursor": input.cursor, "highlight": input.highlight, "display": input.display,
"draws": pack_screen_fixture::encode(&draws)})
)?;
}
fs::write(output, out)?;
Ok(())
}
@@ -0,0 +1,85 @@
//! The registries VanillaCommandParseOracle exports (`registries` mode), as
//! the command dispatcher reads them; shared by the command fixtures.
use horizon_client::command::{Registries, args::RegistryIds};
use serde_json::Value;
fn strings(v: &Value) -> Vec<String> {
v.as_array()
.map(|a| {
a.iter()
.filter_map(|x| x.as_str().map(str::to_owned))
.collect()
})
.unwrap_or_default()
}
pub fn registries(r: &Value, permission: u8) -> Registries {
let mut reg = Registries {
permission,
..Registries::default()
};
reg.items = strings(&r["items"]);
reg.item_tags = strings(&r["item_tags"]);
reg.block_tags = strings(&r["block_tags"]);
for (id, props) in r["blocks"].as_object().into_iter().flatten() {
let props = props
.as_array()
.into_iter()
.flatten()
.map(|p| (p[0].as_str().unwrap_or("").to_owned(), strings(&p[1])))
.collect();
reg.blocks.insert(id.clone(), props);
}
reg.summonable = strings(&r["summonable"]);
reg.entity_types = strings(&r["entity_types"]);
reg.effects = strings(&r["effects"]);
reg.attributes = strings(&r["attributes"]);
reg.sounds = strings(&r["sounds"]);
reg.enchantments = strings(&r["enchantments"]);
reg.structures = strings(&r["structures"]);
reg.biomes = strings(&r["biomes"]);
reg.damage_types = strings(&r["damage_types"]);
reg.clocks = strings(&r["clocks"]);
reg.timelines = strings(&r["timelines"]);
reg.dimensions = strings(&r["dimensions"]);
reg.players = strings(&r["players"]);
reg.teams = strings(&r["teams"]);
reg.objectives = strings(&r["objectives"]);
reg.tracked = strings(&r["tracked"]);
for (name, entry) in r["by_registry"].as_object().into_iter().flatten() {
reg.by_registry.insert(
name.clone(),
RegistryIds {
ids: strings(&entry["ids"]),
tags: strings(&entry["tags"]),
},
);
}
reg.block_entities = strings(&r["block_entities"]).into_iter().collect();
for (tag, members) in r["block_tag_members"].as_object().into_iter().flatten() {
reg.block_tag_members.insert(tag.clone(), strings(members));
}
reg.templates = strings(&r["templates"]);
reg.persistent_components = strings(&r["persistent_components"]);
reg.learnable_recipes = strings(&r["learnable_recipes"]);
for (clock, markers) in r["clock_time_markers"].as_object().into_iter().flatten() {
reg.clock_time_markers
.insert(clock.clone(), strings(markers));
}
for (id, criteria) in r["advancement_criteria"].as_object().into_iter().flatten() {
reg.advancement_criteria
.insert(id.clone(), strings(criteria));
}
reg.datapacks_enabled = strings(&r["datapacks_selected"]);
let enabled = reg.datapacks_enabled.clone();
reg.datapacks_disabled = strings(&r["datapacks_enableable"])
.into_iter()
.filter(|p| !enabled.contains(p))
.collect();
reg.advancements = reg.ids("minecraft:advancement").to_vec();
reg.recipes = reg.ids("minecraft:recipe").to_vec();
reg.loot_tables = reg.ids("minecraft:loot_table").to_vec();
reg.predicates = reg.ids("minecraft:predicate").to_vec();
reg.item_modifiers = reg.ids("minecraft:item_modifier").to_vec();
reg
}
@@ -9,7 +9,7 @@ use horizon_client::{
biome::Biomes,
blocks::BlockFacts,
chunk::{Chunk, MIN_Y, SECTIONS},
light::{LightTables, light_chunk},
light::{LightTables, apply_lighting, light_chunk},
mesher::{MeshTables, Mesher},
models,
streaming::{ChunkGenerator, Proto},
@@ -105,7 +105,7 @@ fn main() -> Result<()> {
);
let mut chunks: Vec<Chunk> = chunks.iter().map(|c| (**c).clone()).collect();
for ((x, z), sections) in lit {
chunks[((z - 1) * inner + x - 1) as usize].sections = sections;
apply_lighting(&mut chunks[((z - 1) * inner + x - 1) as usize], sections);
}
let chunks: Vec<Arc<Chunk>> = chunks.into_iter().map(Arc::new).collect();
let at = |x: i32, z: i32| chunks[((z - 1) * inner + x - 1) as usize].clone();
@@ -0,0 +1,39 @@
//! CloudRenderer face selection and mesh traversal, without a GPU.
use horizon_client::clouds;
use std::{fmt::Write, fs};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<_> = std::env::args().collect();
let mut output = String::new();
for (case, line) in fs::read_to_string(&args[1])?.lines().enumerate() {
let values: Vec<i32> = line
.split_whitespace()
.map(|v| v.parse().unwrap())
.collect();
let [kind, x, z, bottom, neighbors] = values.as_slice() else {
panic!("invalid case")
};
write!(output, "{case}")?;
let mut cell = |x, z, neighbors| {
let empty = std::array::from_fn(|i| neighbors & (1 << i) != 0);
for (direction, inside) in clouds::faces(clouds::face_mask(x, z, *bottom as f32, empty))
{
write!(output, " {x},{z},{direction},{}", u8::from(inside)).unwrap();
}
};
let radius = if *kind == 2 {
clouds::radius_cells(*x)
} else {
*x
};
if *kind == 0 {
cell(*x, *z, *neighbors);
} else {
for (x, z) in clouds::cells(radius) {
cell(x, z, 0);
}
}
output.push('\n');
}
fs::write(&args[2], output)?;
Ok(())
}
@@ -61,6 +61,7 @@ fn parser_id(ty: &ArgType) -> String {
_ => "minecraft:template_rotation".into(),
},
ArgType::HexColor => "minecraft:hex_color".into(),
ArgType::ResourceSelector(_) => "minecraft:resource_selector".into(),
ArgType::Uuid => "minecraft:uuid".into(),
ArgType::GameProfile => "minecraft:game_profile".into(),
ArgType::Style => "minecraft:style".into(),
@@ -120,7 +121,8 @@ fn tree(d: &Dispatcher, node: usize) -> Value {
}
children.insert(child.name().to_owned(), v);
}
let mut v = json!({"children": children});
let order: Vec<&str> = n.children.iter().map(|&c| d.nodes[c].name()).collect();
let mut v = json!({"children": children, "order": order});
if n.command.is_some() {
v["executable"] = json!(true);
}
@@ -0,0 +1,86 @@
#![forbid(unsafe_code)]
//! Runs tools/test_container_screen_parity.py's screens and mouse events
//! through `horizon_client::container_screen`.
use horizon_client::{
Result,
container_screen::{Book, Button, Clicks, Image, Release, Target, clicked_outside},
menu::Input,
};
use serde_json::Value;
use std::{
fs::File,
io::{BufRead, BufReader, BufWriter, Write},
};
fn input_name(input: Input) -> &'static str {
match input {
Input::Pickup => "PICKUP",
Input::QuickMove => "QUICK_MOVE",
Input::Swap => "SWAP",
Input::Clone => "CLONE",
Input::Throw => "THROW",
Input::QuickCraft => "QUICK_CRAFT",
Input::PickupAll => "PICKUP_ALL",
}
}
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let input = BufReader::new(File::open(&args[1])?);
let mut out = BufWriter::new(File::create(&args[2])?);
for (n, line) in input.lines().enumerate() {
let c: Value = serde_json::from_str(&line?)?;
writeln!(out, "== {n}")?;
let int = |v: &Value| v.as_i64().unwrap() as i32;
let image = Image {
left: int(&c["image"][0]),
top: int(&c["image"][1]),
width: int(&c["image"][2]),
height: int(&c["image"][3]),
};
let book = c.get("book").map(|b| Book {
visible: b[0].as_bool().unwrap(),
selected_tab_hovered: b[1].as_bool().unwrap(),
});
let mut clicks = Clicks::default();
for ev in c["events"].as_array().unwrap() {
let name = ev[0].as_str().unwrap();
let (x, y) = (ev[1].as_f64().unwrap(), ev[2].as_f64().unwrap());
let outside = clicked_outside(x, y, image, book);
let mut line = format!("{name} {outside}");
if name != "point" {
// The case says whether the event is over the menu's slot (7).
let on_slot = ev[6].as_bool().unwrap();
line += &format!(" {on_slot}");
let target = Target::of(on_slot.then_some(7), outside);
let button = match ev[3].as_i64().unwrap() {
1 => Button::Left,
3 => Button::Right,
_ => Button::Middle,
};
let shift = ev[4].as_i64().unwrap() & 3 != 0;
let carried_empty = !ev[5].as_bool().unwrap();
let click = if name == "press" {
clicks.press(&target, button, carried_empty, shift, false)
} else {
match clicks.release(&target, button, carried_empty, false, shift, false) {
Release::Click(input) => Some(input),
Release::QuickCraft => panic!("no drags in these cases"),
Release::Nothing => None,
}
};
if let Some(input) = click {
let id = match target {
Target::Slot(s) => s,
Target::Outside => -999,
Target::Nothing => -1,
};
line += &format!(" click {id} {} {}", button.menu_button(), input_name(input));
}
}
writeln!(out, "{line}")?;
}
}
out.flush()?;
Ok(())
}
@@ -0,0 +1,53 @@
//! The creative inventory, for tools/test_creative_parity.py: loads an
//! exported `creative-inventory.json` into `horizon_client::creative::Creative`
//! and prints the tabs it shows (canonical stacks) and the search tab's
//! results for every query of the vanilla oracle's output.
//!
//! usage: creative_search_fixture RESOURCES CREATIVE_JSON VANILLA_JSON OUTPUT
use horizon_client::{
creative::{Creative, Names},
item_data::canon_stack,
};
use serde_json::{Value, json};
use std::{fs, path::Path};
fn main() -> horizon_client::Result<()> {
let args: Vec<String> = std::env::args().collect();
let usage = "usage: creative_search_fixture RESOURCES CREATIVE_JSON VANILLA_JSON OUTPUT";
let names = Names::load(Path::new(args.get(1).ok_or(usage)?));
let creative = Creative::from_json(&serde_json::from_slice(&fs::read(
args.get(2).ok_or(usage)?,
)?)?)?;
let vanilla: Value = serde_json::from_slice(&fs::read(args.get(3).ok_or(usage)?)?)?;
let tabs: Vec<Value> = creative
.tabs
.iter()
.map(|t| {
json!({
"id": t.id,
"title": t.title,
"icon": t.icon,
"row": if t.top { "TOP" } else { "BOTTOM" },
"column": t.column,
"items": t.items.iter().map(|s| canon_stack(Some(s))).collect::<Vec<_>>(),
})
})
.collect();
let searches: Vec<Value> = vanilla["searches"]
.as_array()
.ok_or("searches")?
.iter()
.map(|s| {
let query = s["query"].as_str().unwrap_or_default();
json!({"query": query, "results": creative.search_results(query, &names)})
})
.collect();
let search: Vec<String> = creative
.search_items()
.iter()
.map(|s| canon_stack(Some(s)))
.collect();
let out = json!({"tabs": tabs, "search": search, "searches": searches});
fs::write(args.get(4).ok_or(usage)?, out.to_string())?;
Ok(())
}
@@ -0,0 +1,74 @@
#![forbid(unsafe_code)]
//! Runs tools/test_emitter_particles_parity.py's emitters through
//! `particles::on_block_faces`, `particles::along_axis` and
//! `particles::item_use_particles`.
use horizon_client::{Result, particles};
use horizon_core::random::{LegacyRandom, RandomSource};
use serde_json::Value;
use std::{
fs::File,
io::{BufRead, BufReader, BufWriter, Write},
};
fn d(v: f64) -> String {
format!("{:016x}", v.to_bits())
}
fn main() -> Result<()> {
let args: Vec<String> = std::env::args().collect();
let mut out = BufWriter::new(File::create(&args[2])?);
for (n, line) in BufReader::new(File::open(&args[1])?).lines().enumerate() {
let c: Value = serde_json::from_str(&line?)?;
writeln!(out, "== {n}")?;
let mut random = LegacyRandom::new(c["seed"].as_i64().ok_or("seed")?);
let mut lines = Vec::new();
let record = |kind: &str| {
let kind = kind.to_owned();
move |p: [f64; 3], v: [f64; 3]| {
format!(
"+ {kind} {} {} {} {} {} {}",
d(p[0]),
d(p[1]),
d(p[2]),
d(v[0]),
d(v[1]),
d(v[2])
)
}
};
if c["kind"] == "item_use" {
let p: [f64; 3] = std::array::from_fn(|i| c["pos"][i].as_f64().unwrap_or(0.0));
let f = |k: &str| c[k].as_f64().unwrap_or(0.0) as f32;
let line = record("item");
particles::item_use_particles(
&mut random,
f("pitch"),
f("yaw"),
p,
p[1] + f64::from(f("eye")),
c["count"].as_u64().unwrap_or(0) as u32,
|p, v| lines.push(line(p, v)),
);
} else {
let p: [i32; 3] = std::array::from_fn(|i| c["pos"][i].as_i64().unwrap_or(0) as i32);
match c["axis"].as_i64() {
Some(axis @ 0..=2) => {
let line = record("electric_spark");
particles::along_axis(&mut random, axis as usize, p, |p, v| {
lines.push(line(p, v))
});
}
_ => {
let line = record("wax_on");
particles::on_block_faces(&mut random, p, |p, v| lines.push(line(p, v)));
}
}
}
for l in lines {
writeln!(out, "{l}")?;
}
writeln!(out, "next {}", random.next_long())?;
}
out.flush()?;
Ok(())
}
@@ -1,14 +1,17 @@
//! Replays the render states of the vanilla entity-animation oracle through
//! Horizon's `mobs::anim::setup` and writes every part's pose.
//! Horizon's `mobs::anim::setup` and writes every part's pose, then draws the
//! posed model with `mobs::render::draw` under the case's living-entity root
//! transform and writes each drawn part's packed vertex normals.
//!
//! cargo run --profile fast -p horizon-client --example entity_anim_fixture -- \
//! RESOURCES VANILLA.jsonl OUT.jsonl
use horizon_client::mesher::Vertex;
use horizon_client::mobs::{
Mob, MobData, MobTypes, Part, Species, allay,
anim::{self, Poses, State},
aquatic, body_anim as b_anim, equine, guardian,
keyframes::AnimationState,
shulker, species, tame,
render, shulker, sniffer, species, tame,
};
use horizon_core::geometry::Vec3;
use serde_json::{Value, json};
@@ -44,6 +47,61 @@ fn walk(part: &Part, path: &str, poses: &Poses, out: &mut BTreeMap<String, Value
}
}
/// Splits the vertices `render::draw` emitted for `part` into its drawn parts,
/// following draw's walk: a hidden or zero-scaled part ends its branch, a
/// skip-draw part keeps its children. Per part: n = packed normal bytes per
/// vertex, p = sum of x + 2y + 3z over the positions.
fn drawn(
part: &Part,
path: &str,
poses: &Poses,
vertices: &[Vertex],
cursor: &mut usize,
out: &mut BTreeMap<String, Value>,
) {
let p = poses.pose(part);
if poses.is_hidden(part) || p[6] == 0.0 && p[7] == 0.0 && p[8] == 0.0 {
return;
}
let count = if poses.skips(part) {
0
} else {
part.polygons.len() * 4
};
if count > 0 {
let own = &vertices[*cursor..*cursor + count];
let normals: Vec<i8> = own.iter().flat_map(|v| v.normal[..3].to_vec()).collect();
let sum: f64 = own
.iter()
.map(|v| f64::from(v.pos[0]) + 2.0 * f64::from(v.pos[1]) + 3.0 * f64::from(v.pos[2]))
.sum();
out.insert(path.to_owned(), json!({"n": normals, "p": sum}));
}
*cursor += count;
for c in &part.children {
let child = if path.is_empty() {
c.name.clone()
} else {
format!("{path}/{}", c.name)
};
drawn(c, &child, poses, vertices, cursor, out);
}
}
/// LivingEntityRenderer's root transform without the entity's position:
/// rotate 180 - yaw about Y, scale(-1, -1, 1), the renderer's own scale, then
/// translate(0, -1.501, 0) (as `render::base_transform`).
fn root_transform(case: &Value) -> glam::Mat4 {
let yaw = case["@rootYaw"].as_f64().unwrap_or(0.0) as f32;
let scale = case["@rootScale"].as_array().map_or(glam::Vec3::ONE, |s| {
glam::Vec3::from_array(std::array::from_fn(|i| s[i].as_f64().unwrap_or(1.0) as f32))
});
glam::Mat4::from_rotation_y((180.0 - yaw).to_radians())
* glam::Mat4::from_scale(glam::Vec3::new(-1.0, -1.0, 1.0))
* glam::Mat4::from_scale(scale)
* glam::Mat4::from_translation(glam::Vec3::new(0.0, -1.501, 0.0))
}
/// The entity-side values behind the render-state fields the case sets, for
/// the species whose Horizon animation reads them from the `Mob`.
fn entity_state(mob: &mut Mob, species: Species, case: &Value) {
@@ -173,6 +231,56 @@ fn entity_state(mob: &mut Mob, species: Species, case: &Value) {
mob.anim.states[i].started = case[k].as_f64().map(|v| v as f32);
}
}
Species::Breeze => {
// breeze::anim's state slots.
for (i, k) in ["idle", "shoot", "slide", "slideBack", "inhale", "longJump"]
.into_iter()
.enumerate()
{
mob.anim.states[i].started = case[k].as_f64().map(|v| v as f32);
}
}
Species::Sniffer => {
if flag("isSearching") {
mob.extra.variant = sniffer::SEARCHING;
}
// Sniffer's animation states, in `sniffer::anim`'s order.
for (i, k) in [
"feelingHappyAnimationState",
"scentingAnimationState",
"sniffingAnimationState",
"diggingAnimationState",
"risingAnimationState",
]
.into_iter()
.enumerate()
{
mob.anim.states[i].started = case[k].as_f64().map(|v| v as f32);
}
}
Species::HappyGhast => {
mob.extra.head = case["bodyItem"].as_str().map(Into::into);
if flag("isRidden") {
mob.rider = Some(Default::default());
}
}
Species::Warden => {
use horizon_client::mobs::warden;
mob.anim.v[warden::TENDRIL] = num("tendrilAnimation") * 10.0;
mob.anim.vo[warden::TENDRIL] = num("tendrilAnimation") * 10.0;
mob.anim.v[warden::HEART] = num("heartAnimation") * 10.0;
mob.anim.vo[warden::HEART] = num("heartAnimation") * 10.0;
for (i, k) in [
(warden::ROAR, "roarAnimationState"),
(warden::SNIFF, "sniffAnimationState"),
(warden::EMERGE, "emergeAnimationState"),
(warden::DIGGING, "diggingAnimationState"),
(warden::ATTACK, "attackAnimationState"),
(warden::SONIC_BOOM, "sonicBoomAnimationState"),
] {
mob.anim.states[i].started = case[k].as_f64().map(|v| v as f32);
}
}
Species::Witch if flag("isHoldingItem") => {
mob.extra.main_hand = Some("minecraft:potion".into());
}
@@ -186,12 +294,26 @@ fn main() -> horizon_client::Result<()> {
let types = MobTypes::load(&root)?;
let animations = MobData::load_animations(&root);
let mut out = String::new();
let crystal = horizon_client::mobs::load_model(&root, "minecraft:end_crystal#main");
for line in fs::read_to_string(&args[1])?.lines() {
let v: Value = serde_json::from_str(line)?;
let layer = v["layer"]
.as_str()
.unwrap_or_default()
.trim_start_matches("minecraft:");
// EndCrystalModel is not a mob's: horizon_client::end_crystal poses it.
if layer == "end_crystal#main"
&& let Some(model) = &crystal
{
let case = &v["case"];
let mut poses = horizon_client::end_crystal::poses(
model,
case["ageInTicks"].as_f64().unwrap_or(0.0) as f32,
case["showsBottom"].as_bool().unwrap_or(false),
);
out.push_str(&format!("{}\n", emit(model, &mut poses, case, layer)));
continue;
}
let baby = layer.contains("_baby#");
let adult = layer.replace("_baby#", "#");
// Variant layers (sizes, hatless villagers, climate cows...) animate
@@ -215,6 +337,13 @@ fn main() -> horizon_client::Result<()> {
base = base.replace(cut, "");
}
let base = base.replace("undead_horse#", "zombie_horse#");
// The breeze's wind and eyes and the creaking's eyes are layers of
// the species' own model class; LlamaDecorLayer's model animates like
// the llama.
let base = base
.replace("#wind", "#main")
.replace("#eyes", "#main")
.replace("#decor", "#main");
let base = base.trim_start_matches("cold_").trim_start_matches("warm_");
let Some(def) = species::ALL.iter().find(|d| {
d.model == layer
@@ -222,6 +351,11 @@ fn main() -> horizon_client::Result<()> {
|| d.model == base
|| d.model.trim_end_matches("#main") == base.trim_end_matches("#main")
|| norm(d.model) == base
// The warden's emissive layers are its model over other parts.
|| (["#tendrils", "#heart", "#bioluminescent", "#pulsating_spots"]
.iter()
.any(|s| layer.ends_with(s))
&& d.model == format!("{}#main", layer.split('#').next().unwrap_or_default()))
}) else {
out.push_str(&format!("{}\n", json!({"skip": "no species"})));
continue;
@@ -370,6 +504,22 @@ fn main() -> horizon_client::Result<()> {
},
&animations,
),
Species::CopperGolem => {
// CopperGolemRenderState's animation states, in the golem's slots.
for (slot, key) in [
"idleAnimationState",
"interactionGetItem",
"interactionGetNoItem",
"interactionDropItem",
"interactionDropNoItem",
]
.into_iter()
.enumerate()
{
mob.anim.states[slot] = started(key);
}
horizon_client::mobs::copper_golem::anim(&mob, s, p, &animations);
}
Species::Rabbit => b_anim::rabbit(
p,
s,
@@ -440,10 +590,38 @@ fn main() -> horizon_client::Result<()> {
}
_ => anim::setup(&mob, s, p, &animations),
}
let mut parts = BTreeMap::new();
walk(&model, "", &poses, &mut parts);
out.push_str(&format!("{}\n", json!({"parts": parts})));
out.push_str(&format!("{}\n", emit(&model, &mut poses, case, layer)));
}
fs::write(&args[2], out)?;
Ok(())
}
/// Every part's pose, and the vertices drawn under the harness's root transform.
fn emit(model: &Part, poses: &mut Poses, case: &Value, layer: &str) -> Value {
// The harness's part-scale override, set after setupAnim as the oracle does.
if let Some(scale) = case["@partScale"].as_array() {
let pose = poses.get(scale[0].as_str().unwrap_or_default());
for i in 0..3 {
pose[6 + i] = scale[1 + i].as_f64().unwrap_or(1.0) as f32;
}
}
let poses = &*poses;
let mut parts = BTreeMap::new();
walk(model, "", poses, &mut parts);
let mut emitted = Vec::new();
render::draw(
model,
root_transform(case),
poses,
[0.0, 0.0, 1.0, 1.0],
0xFFFF_FFFF,
240 | 240 << 8,
0,
&mut emitted,
);
let mut vertices = BTreeMap::new();
let mut cursor = 0;
drawn(model, "", poses, &emitted, &mut cursor, &mut vertices);
assert_eq!(cursor, emitted.len(), "{layer}: draw's walk changed");
json!({"parts": parts, "vertices": vertices})
}
Loaded 100 of 1027 files, more files were not shown because too many files have changed in this diff. Show more