188 Commits
Author SHA1 Message Date
GabrielNichols c7d27a84a1 Fill Recipes grids without teaching the recipe 2026-11-06 19:10:19 -03:00
rdbt 7c58203441 Merge pull request #9668 from GabrielNichols/codex/recipes-hmod-server-fill
Keep .hmod Recipes searchable and placeable on the server
2026-11-06 21:18:28 +00:00
rdbt aea2bdadb1 Merge pull request #11114 from Delete228/content-item-block-alias-upstream
Native content: place a block through an item alias
2026-11-06 21:18:04 +00:00
DUzzL f7b204a231 Read mod features from worldgen/feature/, 26.3's folder 2026-11-06 15:17:45 +01:00
Delete228andCodex 21d66471d4 Bind content item aliases to ordinary block placement
Compile place_block declarations into the existing BlockItem binding table and load secondary item-to-block mappings for client prediction and server placement. Preserve alias item identity, component defaults and existing primary block-item mappings.

Validation: 49 compiler, 38 declaration and 63 item tests pass. Explicit prepared-resource tests verify original placement context IDs, real survival consumption, adventure refusal and dry client prediction. Strict clippy, formatting and public-tree checks pass.

Co-Authored-By: Codex <[email protected]>
2026-11-06 15:35:03 +03:00
GabrielNichols ce90330576 Sync Recipes content scenario with official main 2026-11-06 04:32:30 -03:00
Horizon agentandClaude Opus 5.5 56c896f51c docs/mods.md: which switches wait in a world
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 17:51:12 +01:00
Horizon agentandClaude Opus 5.5 408044e9a9 Mods: content mods of assets and data switch on and off without a restart
A content root is built per set of mods (.horizon-cache/mod-content/<stamp>),
so a running game keeps reading the root it was given while a switch
builds another; roots unused for a day are removed. Turning a mod on or
off in Options > Mods, or installing one from Browse Mods, applies at once
when the mod has only assets and data: the client reloads its resources,
then the server reloads its data packs as /reload does and resyncs its
players. A mod that adds blocks, items, mob effects, entity or menu types
or changes world generation keeps loading at start, and the Mods page
says to restart.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 16:36:58 +01:00
HiuoyandClaude Opus 5.5 777a71b039 Content mods: a living type may copy the wandering trader
minecraft:wandering_trader joins the zombie and the villager as a living
template. It is the neutral one whose behaviour is all goals, so a native
mod's register_goals can replace every bit of it: a citizen, a guard or an
NPC, which a zombie (hostile, burns in daylight) and a villager (its brain
stays) can't be. Saving and entity data already follow the template's
class (class_id); the tests now cover a trader type too.

Part of #8622.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 13:06:20 +04:00
GabrielNichols 055c47c98d Merge official main into Recipes content scenario 2026-11-05 02:45:32 -03:00
HiuoyandClaude Opus 5.5 178bf207c6 Native mods: register_goals, a new mob's goals (Mob.registerGoals)
A trait mod's register_goals hook is asked for every new mob, after its
species added its goals and before its saved data is read. It may clear
the goal and target selectors and add Goal types of its own, which steer
the mob with its navigation (nav_move_to, create_path_to) and controls.
A mod's living type from #9667 thus gets its own AI. The hook runs before
the float check, so a mod's Float goal floats the navigation as
FloatGoal's constructor does.

The hook is a free function in the client library, so it goes through
NativeClientHooks as living_breathe does. mod_api re-exports Mob,
MobWorld, Goal, GoalSelector and Cx; the generator's dispatch tests get
a Mob stub and the catalog test knows mobs/ai.rs.

Part of #8622.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 09:41:21 +04:00
GabrielNichols 0e6e28109f Keep the pilot fixture focused on an original content recipe 2026-11-05 01:56:50 -03:00
GabrielNichols e770447686 Keep Recipes search editable after an empty result 2026-11-05 01:11:59 -03:00
HiuoyandClaude Opus 5.5 d579acfa15 Content mods: living entity types from a zombie or villager template
A content mod's entity type could only copy minecraft:snowball, so a mod
had no way to add a mob. It may now copy minecraft:zombie or
minecraft:villager, as NeoForge's EntityType.Builder.of(Zombie::new, ...)
makes a type of a vanilla class, with its own default attribute values
(EntityAttributeCreationEvent) in an `attributes` map, for attributes the
template has. A thrown type still names its item; a living one has none.

The mod's row in entity-types.json is its template's with `template`
added and its attribute bases in place of the template's, every other
value kept as the template's text. MobTypes::load makes a row naming a
template into that species' MobType under the mod's id, so registry and
network ids, /summon and remote spawns, which already went through the
table and the registry, pick it up. What a class saves and syncs of its
own (a zombie's IsBaby, CanBreakDoors and conversion times, its entity
data, the villager's) follows MobType::class_id, the template's id for a
mod type; the saved and sent id stays the mod's.

A mob's default loot table, and /loot ... kill, now keep the type's
namespace (EntityType.getDefaultLootTable): ruby:ghoul rolled
minecraft:entities/ruby:ghoul, and rolls ruby:entities/ghoul. Nothing
changes without content mods: no row has a template, and class_id is the
type's own id.

First slice of #8622; goals, navigation and structure placement stay
open.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 08:00:38 +04:00
Delete228andCodex 7a3f407a54 Merge current main and retain world suffocation bindings
Keep main suffocation registration and the world damage catalog together when loading world tables. Preserve all intervening upstream changes without rewriting existing PR history.

Co-Authored-By: Codex <[email protected]>
2026-11-04 23:41:36 +03:00
Ludovic Marie 07a1a4af76 Merge pull request #8698 from ErikKalikas/mod-menu-extra
🤖 Agent: the 32 KiB cap is enforced on both encode and decode, a vanilla client ignores the unknown horizon:menu_extra channel, and the lan_bot test pins that the payload arrives right before its own window's OpenScreen.
2026-11-04 15:23:04 +01:00
Delete228andCodex 4ad8604280 Load world damage definitions and reload their frozen registry tags
Preserve ordinary player damage, enchantment predicates and synchronized registry data for enabled resource/data packs. Validate definitions before publication and keep world definitions stable through reload.

Co-Authored-By: Codex <[email protected]>
2026-11-04 05:40:37 +03:00
Ludovic Marie 36e36b063d Merge pull request #8296 from CocofireHD/fix/2120-cargo-binstall
🤖 Agent: all five targets build and the four runnable ones start on their runners (x86_64-apple-darwin through Rosetta on the arm64 macos-latest); releases are created with --latest=false so a cargo-horizon-mod tag never takes GitHub's latest from the game; the YAML-grep test is gone, the three left test the manifest-to-release contract.
2026-11-04 00:30:48 +01:00
ErikKalikasandClaude Opus 5.5 9841d6bffd Native mods: a mod menu type opened with extra data (openMenu with an extra-data writer)
A mod block opening its content mod's menu type asks native_menu_extra_data for bytes
of the mod's own; a horizon:menu_extra payload carries them with the window and the
block's position to Horizon clients right before OpenScreen. The client takes the
block from it instead of the last clicked one, and native_screen_pos /
native_screen_extra_data read both while the mod's screen is open.

Fixes #8675

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-03 23:28:50 +02:00
Ludovic Marie 447e043650 Merge pull request #8083 from OlaHulleberg/content/shapes-occludes
🤖 Agent: one point checked: occludes:false drops a solid render's dampening to 1 (0 with skylight_down) as getLightDampening does for non-solid full blocks; only content-mod blocks that set the key change, vanilla rows are untouched.
2026-11-03 17:59:50 +01:00
CocofireHDandDeepSeek V4.1 Flash ab49fe48b7 cargo-horizon-mod: prebuilt binaries for cargo-binstall
`cargo install --git ...` compiles the tool and its workspace, which for a
mod developer on a slow machine is a long wait to write one block (#2120).
`cargo binstall` skips the build when the release holds a binary for the
platform.

- crates/cargo-horizon-mod/Cargo.toml gains [package.metadata.binstall]:
  one `cargo-horizon-mod-v<version>` release, one tar.gz per Rust target,
  the binary at the archive's root; a `.sha256` beside each.
- .github/workflows/cargo-horizon-mod.yml builds those targets (Linux
  x86_64 and aarch64, Windows x86_64, macOS x86_64 and arm64), starts
  each binary it can run, and publishes them on the tag. A pull request
  builds them without publishing.
- tools/horizon_mod_binstall.py is the one list of targets: the workflow's
  matrix comes from it, and it checks the built archives and the tag
  against the manifest before anything is published.
- docs/mods.md shows the binstall command first, the source build after.

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
2026-11-03 16:16:07 +01:00
OlaHullebergandClaude Opus 5.5 da8eb9e43b Content blocks may occlude nothing (properties.occludes)
A content block occluded as its template does, so a thin panel or a block
drawn by its block entity on a full-cube template hid the faces of the
blocks beside it, leaving a hole in the floor under it.
`properties.occludes: false` is vanilla's `noOcclusion()`: the block's
gameplay state can't occlude and isn't a solid render, and its render
definition can't occlude (the faces beside it are drawn). A solid render's
full light dampening becomes a non-solid block's, as vanilla's data has it
for leaves and spawners: 1, or 0 when skylight passes down.

Item 2 of #5550.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ChJKHFsqiw1XFe27mMdroL
2026-11-03 07:28:03 +00:00
Ludovic MarieandClaude Opus 5.5 c2bf88085a Merge origin/main into #7968 after #8011: the mod API is generated at build time
generated.rs is no longer tracked, and xtask's generator moved to
horizon-mod-api-gen, so the dispatch tests' stand-in types get NativeConfig
and NativeConfigFile there.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-03 06:48:28 +01:00
Ludovic Marie d45d35a213 Merge pull request #7975 from GabrielNichols/mods/spawn-biome-modifiers
🤖 Agent: checked the output against 26.3's plains.json: spawners land in attributes[minecraft:gameplay/natural_mob_spawns].argument.spawns_by_category with count as an int or a minecraft:uniform object, the shape biome.rs already reads. One edge: an entity type missing from entity-types.json falls back to the misc category, but the entity_reg check skips such a spawner first, so that fallback never runs.
2026-11-03 04:37:41 +01:00
rdbt b5dcfe89b5 Merge pull request #7867 from OlaHulleberg/content/render-shape
Content blocks choose their render_shape
2026-11-03 01:35:59 +00:00
rdbt bfa085bb45 Merge pull request #7540 from UMCEKO/content-mods/atlas-sources
Content mods: sprites a mod adds to vanilla's atlases join the root
2026-11-03 01:32:09 +00:00
GabrielNicholsandClaude Opus 4.6 f5c34fc62e Content mods: read the spawn biome modifiers (#7478)
Read NeoForge's `add_spawns`, `remove_spawns`, `add_spawn_costs` and
`remove_spawn_costs` biome modifiers alongside `add_features` and
`remove_features` when building the content root:

- `add_spawns` appends its spawners (a single spawner object or a list)
  to each entity type's spawn category in `spawns_by_category` under
  `attributes[minecraft:gameplay/natural_mob_spawns]`, converting
  `minCount` and `maxCount` to 26.3's `count` (an integer when equal,
  `minecraft:uniform` otherwise) and taking the category from
  `entity-types.json`;
- `remove_spawns` removes the resolved `entity_types` (an id, `#tag`,
  list, or `any`/`or`/`and`/`not` holder set) from every category;
- `add_spawn_costs` sets `spawn_costs[type]` (`energy_budget`,
  `charge`) and `remove_spawn_costs` removes them;
- additions run before removals in mod and file order, unknown entity
  types or tags are skipped with a warning, malformed modifiers fail the
  build naming the mod and file, and changed biomes also update
  `data/<ns>/worldgen/biome/<path>.json` in the overlay when present.

Fixes #7478

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-11-02 22:27:07 -03:00
ErikKalikasandClaude Opus 5.5 ceadedaa0f Native mods: mod config files, loaded and reloaded (ModConfigEvent)
native_register_configs lists a mod's configs: a kind (Client, Common,
Server), a file in config/ (<mod id>-<kind>.toml unless named) and the
text written there when it is missing. Client configs load on the
window when the game starts, Common once per process, Server before
native_server_about_to_start for each world, from the world's
serverconfig/ copy when there is one. native_config_loading hands over
the text, which the mod parses. The files' modification times are read
once a second; changed text fires native_config_reloading. A server's
configs fire native_config_unloading when it stops. Fixes #7950.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-03 03:05:59 +02:00
Ludovic MarieandClaude Opus 5.5 3abeb4f845 Merge main into #7557
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 23:24:46 +01:00
OlaHullebergandClaude Opus 5.5 bb5c43d602 Content blocks choose their render_shape
A content block always drew as its template does, so a block whose moving parts its block entity
draws every frame (a turning shaft, a machine's arm) still had its model baked into the chunk mesh.
`properties.render_shape` takes vanilla's `RenderShape` by name: `MODEL`, `ENTITYBLOCK_ANIMATED`
(the model is left out of the chunk mesh) or `INVISIBLE`. It sets the state's `render_shape`, which
the mesher already reads. Outline, collision, light and occlusion are unchanged.

Item 1 of #5550.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 22:04:34 +00:00
[email protected]andGPT-6.1 Sol 5d41cf1623 feat(mods): support tuple-selected block and collision shapes
Checkpoint implementation and regression coverage for #7464.

Co-Authored-By: GPT-6.1 Sol <[email protected]>
2026-11-02 18:19:40 +01:00
umcekoandClaude Sonnet 5.5 00b567c1de Content mods: sprites a mod adds to vanilla's atlases join the root
A mod can add sources to vanilla's atlases (assets/minecraft/atlases/*.json),
as a resource reload appends every pack's sources to the ones below it.
The fence allows those files, the content root writes vanilla's sources
followed by the mods', and carry keeps them.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-02 20:16:51 +03:00
arismoko a848ae0be2 cargo horizon-mod new: a native trait mod template
`--template native [--horizon <commit>]` writes a trait mod's bundle: its
horizon-mixin.toml, pinned to that Horizon commit or left unpinned, and an
[api] crate whose hooks() greets each player who joins. The files are
what docs/api/mod-files.md lets a bundle carry, so the launcher builds the
folder as it is and packs it into an .hnmod; a test packs it that way and
runs the registry's check on it.
2026-11-02 14:13:03 +00:00
Lucas DelonandClaude Sonnet 5.5 08c5ffc3d3 docs: the join check sends only side = "both" mods; a manifest without a side is client
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-02 14:11:23 +01:00
Lucas DelonandClaude Sonnet 5.5 a2c34553d8 Join check: name the content mods that differ, by version and file hash
A server with content mods on sends each mod's id, version, side and the
SHA-256 of its .hmod on horizon:mod_list; the client answers with its own
list, and a client that differs is refused with the mods named. Only
side = "both" mods count, so client-only mods never block a join.

Refs #7192

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-02 13:54:03 +01:00
Aaron Wang bb6ec90df7 Let a mod's blocks be signs, by their template
A mod block only became a sign when its name ended in _sign, and then its
text never reached a client: the chunk encoder gave a mod block its own block
entity type and dropped any entity that wasn't the mod's. Its item also placed
vanilla's wall sign, and its editor looked for a texture named after the block.

Go by the template's class, as vanilla's instanceof SignBlock does, for the
block entity, the renderer, the editor, chaining and respawning, and for the
block entities world generation gives the blocks a feature places. A content
block declares wood_type, its WoodType name, and wall_block, the wall form its
item places, one of the same mod's blocks: a pair that doesn't fit leaves out
that mod alone. Mod signs go out with vanilla's sign and hanging_sign block
entity types, so text, glow, dye, wax and saving work as they do on an oak
sign. A stone block named road_sign is no longer a sign (#5532).

Written with Claude Opus 5.5 in OpenCode.
2026-11-02 02:39:32 -05:00
AkirabaneandClaude Sonnet 5.5 92967740a6 A furnace fuel leaves its crafting remainder, not only a bucket
AbstractFurnaceBlockEntity.consumeFuel takes the fuel item's own crafting
remainder: it takes the fuel slot once the stack is used up, and is dropped
at the furnace while more of the fuel is left. furnace.rs only knew the lava,
water and milk buckets by name, so a content mod's fuel with a
crafting_remainder burnt without leaving it. The remainder now comes from the
items table (the buckets carry theirs there), and Furnace::tick hands the
dropped ones to its caller, which drops them with Containers.dropItemStack's
helper.

Fixes #6524

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-02 00:00:57 +01:00
Ludovic Marie 7ee14b2df6 Merge pull request #6247 from Xmilon/native/content-state-vanilla-order
🤖 Agent: Reviewed by Ludovic's AI agent (Claude): content block states laid out in StateDefinition order (names sorted, first slowest) instead of refusing a property that sorts first; ids unchanged for blocks that already loaded (test); load-time only. Union of 6247+6260+6270+6279 with main: Python tests 594 OK, stamp_native_hooks OK; verify green on b40d434d4.
2026-11-01 21:11:55 +01:00
[email protected]andClaude Opus 5.5 29c9854e60 fix(mods): lay a content block's states out in vanilla's order
A block's states were its template's states times the declared combinations,
the template's properties varying slowest, but StateTable::new reads a state
table as vanilla's StateDefinition does: every property sorted by name, the
first name slowest. A declared name that sorts before one of the template's
(`bites` before `facing` on carved_pumpkin) stopped the game at load.

The states are now laid out in that order, with one lookup from a template
state and a declared combination to the state's row, used for the template
state's new id (the default state included), the collision shape fan-out and
the cached shapes. Declared names that sort after the template's lay out as
before, so those blocks' ids do not move. The refusal this replaces is gone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 19:22:25 +01:00
[email protected]andClaude Opus 5.5 9697811a90 feat(mods): a content block's random_ticks property
A mod block only got random ticks when its template ticks, so a crop,
sapling or soil on a template that never ticks (dirt, stone) never grew.
`properties.random_ticks` is `true` or `false` for every state, or
`{ "property", "values" }` for the states whose own state property is one of
the values. It sets the state's `random_ticks` flag, which
`isRandomlyTicking`, the sections' random tick counts and
`native_random_tick` already read.

Fixes #6138

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 18:43:07 +01:00
Ludovic Marie e576d02cd1 Merge pull request #5866 from reservedbytes/feat/mod-menu-engine
🤖 Agent: verified with main + #5866 + #5905: pr_ready --quick green (1756 tests), 18 item-use and menu harnesses pass on the 26.3 jars.
2026-11-01 18:23:30 +01:00
levzzzandClaude Opus 5.5 24f539c633 Content mod docs: every kind it declares, multiplayer, the sounds key, sections in place
Closes #5852.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 15:36:58 +05:00
reservedbytes 25e5dbb3da feat(mods): mod menu types on the vanilla menu engine, and a hook for their slot rules 2026-11-01 09:25:26 -01:00
levzzz ac68376123 Merge remote-tracking branch 'hr/main' into pr-5692 2026-11-01 14:02:39 +05:00
reservedbytes d81a16f409 feat(mods): content mods' thrown entity types are saved, summoned and listed 2026-11-01 04:33:54 -01:00
reservedbytes 9a47759df3 feat(mods): mod menu types with their own slot count and data slots 2026-11-01 02:44:59 -01:00
Ludovic Marie 9a4faa20d7 Merge pull request #5502 from sirrayi/mods/biome-modifiers
🤖 Agent: biome modifiers place mod features; fixed here: unread modifier types and unknown names are skipped with a warning instead of dropping every content mod. Proven on a union of main 956e35469 with 19 open PRs including this head: pr_ready --quick green for it (clippy -D warnings incl. the server build, workspace tests, content-root tests, Python tests). CI parity covers the harnesses.
2026-11-01 03:05:27 +01:00
Ludovic Marie f593240a0e Merge pull request #5564 from reservedbytes/feat/content-entity-types
🤖 Agent: content mods declare thrown entity types (snowball template); rdbtCVS found no defects; verify green. Proven on a union of main f99f8feaa with 37 open PRs including this head: pr_ready --quick green for it (fmt, clippy -D warnings incl. the server build, 3077 workspace tests, 20 content-root tests, launcher clippy + 340 tests, 510 Python tests; the one failure is #5570's own new test, not in this PR). CI parity covers the harnesses.
2026-11-01 02:42:14 +01:00
Ludovic MarieandClaude Opus 5.5 064313363c Biome modifiers: skip what can't be read, with a warning
A modifier of a type not read yet (add_spawns, add_carvers, a mod's own
serializer) or naming a biome, feature or tag the root doesn't have (another
mod's ids, #c: convention tags) dropped every content mod. Real mods ship
those beside their feature modifiers, so that modifier is now skipped with a
warning naming the mod and file, as NeoForge skips an unresolvable holder
set (reservedbytes's review). A malformed modifier of a read type (unknown
step) still stops the build. The docs say #tag in features reads vanilla's
feature tags only for now (arismoko's review).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 02:26:32 +01:00
Ludovic MarieandClaude Opus 5.5 05a64ece79 Merge main into #5426
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 02:06:23 +01:00