Commit Graph

653 Commits

Author SHA1 Message Date
ZlordHUN
09d23bd15f feat: Add Mineshaft Generation (#2740)
* feat: Add Mineshaft Generation

* fix(structures): remove redundant mineshaft probability gate

The MINESHAFTS structure_set already gates generation via its
frequency reduction (0.004, LegacyType3) in placement, so the extra
0.01 roll in the generator was double-gating and made mineshafts far
too rare. No other Pumpkin structure generator rolls its own
probability, so the gate has been removed to match vanilla frequency.

* feat(structures): faithful port of vanilla mineshaft generation

Rewrites all mineshaft pieces to match vanilla MineshaftPieces
(decompiled from server.jar):

- Corridor: 3-wide tunnel with fence posts + plank beams every 5
  blocks, floor planks below the box at y=-1, cobwebs, rails (with
  correct NORTH_SOUTH / EAST_WEST shape per corridor axis), cave-spider
  spawner (spider corridors), chest (1%), wood support pillars
- Room: carved dome chamber at Y=50, vanilla dims (8-13 wide)
- Crossing: 5x5 with corner pillars, optional two-floored
- Stairs: vanilla descending staircase (air-only, no planks)
- Assembly: vanilla piece weights (70% corridor / 10% stairs / 20%
  crossing), depth <= 8, bounds = 80 blocks from start
- Liquid check (isInInvalidLocation): aborts pieces in water/lava
- Mesa variant: dark oak wood throughout

* feat(world): support generated loot minecarts

* Minecart Vanila Parity

* Rebased And Added Furnace, Hopper, TNT Minecarts

* Refactor minecarts and fix off-rail gravity

Split minecart variants into focused modules, correct airborne minecart physics, and remove the test-only entity chunk-loading rework.

* Fix mineshaft vanilla parity

---------

Co-authored-by: Zoltán Virágh <zoltan.viragh@cloudtalk.io>
2026-08-05 08:48:26 +02:00
ZlordHUN
150eff5897 feat: Implement End City structures (#2761) 2026-08-05 08:45:34 +02:00
Alexander Medvedev
9ececd9eca chore: add more chunk tests 2026-08-04 10:38:27 +02:00
Alexander Medvedev
e1117ce4a6 chore: nicer event firing 2026-08-03 21:16:07 +02:00
Alexander Medvedev
f474756b16 fix: ci 2026-08-02 12:42:21 +02:00
Alexander Medvedev
98d4451fc9 chore: some fixes 2026-08-02 10:49:37 +02:00
Alexander Medvedev
141b49f973 chore: some more tests 2026-08-02 08:31:01 +02:00
Oswald
c14d946a74 fix: transposed heightmap restore left resumed chunks with stone surfaces (#2448) 2026-08-02 00:03:30 -04:00
Alexander Medvedev
e74a3d4dda feat: handle signed plugins 2026-08-01 12:29:26 +02:00
Jamie Little
75994f3302 feat: /place command (#2473)
* Add /place template command with BlockPlacer trait and tab-completion support

- Add BlockPlacer trait to abstract block placement over ProtoChunk (worldgen)
  and WorldBlockPlacer (live command), used by place_template()
- Implement BlockPlacer for ProtoChunk (pumpkin-world) and WorldBlockPlacer
  (pumpkin crate)
- Add World::queue_block_updates() to insert into unsent_block_changes
  without triggering full set_block_state callbacks
- Generate _generated_all_template_names() at build time from structure
  assets for use in tab-completion suggestions
- Add TemplateNameArgumentType for the new command system with
  list_suggestions() using all_template_names()
- Implement /place template <template> [pos] in the new command system
  (CommandDispatcher, CommandExecutor, ArgumentBuilder)
- Fix borrow-across-await: clone template name to owned String early

* feat: add /place structure and /place jigsaw commands

Adds /place structure <id> [pos] for all structure types with two placement paths:
- Jigsaw structures (ancient_city, bastion_remnant, etc.): fast path using
  JigsawPlacement::add_pieces directly at the target position
- Non-jigsaw structures (desert_pyramid, end_city, etc.): generate pieces
  via dispatch, place into synthetic ProtoChunks with pre-seeded heightmaps
  and a stone floor so pieces can detect terrain, then delta-apply only
  changed blocks to the world via WorldBlockPlacer

Also adds /place jigsaw <pool> <target> <depth> [pos] for manual jigsaw
template placement.

Architecture:
- generate_structure_position() extracts the shared generator dispatch
  from try_generate_structure / lazily_generate_structure (both now
  delegate to it, eliminating ~150 lines of duplicated match arms)
- place_pool_element_templates() extracted from PoolElementStructurePiece
  for reuse by the command with WorldBlockPlacer
- StructureKeys gains from_name()/to_name()/all_names() via codegen
- StructureNameArgumentType and PoolNameArgumentType for tab-completion
- flat_ocean_floor_height_map made pub in ProtoChunk for heightmap seeding

* feat: add /place feature command

Adds /place feature <feature> [pos] for placing configured features
at a specific position. Resolves the PlacedFeature name via from_name(),
resolves the inner ConfiguredFeature from PLACED_FEATURES /
CONFIGURED_FEATURES, then calls ConfiguredFeature::generate() directly
at the target position -- skipping placement modifiers so the feature
appears exactly where specified.

Also adds /place structure improvements:
- Synthetic chunk terrain fill: stone below surface + grass on top, so
  pieces that carve through solid terrain (stronghold corridors, etc.)
  find material to work with. Snapshot/delta ensures only structure
  blocks reach the world.
- Shared snapshot_blocks() and apply_delta() helpers eliminate ~30 lines
  of duplicated diff logic between structure and feature paths.
- ground_y() and chunk_population_seed() helpers replace magic numbers.
- Structure success message now reports the structure name instead of
  the piece count.

Infrastructure:
- PlacedFeature::all_names() generated via pumpkin-codegen for
  tab-completion suggestions in PlacedFeatureNameArgumentType.
- GenerationCache trait implemented for ProtoChunk (single-chunk
  delegation) so ConfiguredFeature::generate() works without the full
  chunk-generation cache system.
- flat_ocean_floor_height_map made pub in ProtoChunk for heightmap
  seeding.
- configured_features and feature modules made pub for access from
  the command crate.

* fix(command): use world settings for place

* docs(place): clarify synthetic terrain delta behavior
2026-07-31 11:45:23 +02:00
Jamie Little
732aa24fe3 fix: persist block entity data on chunk save (#2452)
* feat(command): add /reload command

* feat: campfire cooking + block entity persistence for all entity types

- Implement full campfire cooking: 4-slot cooking, recipe lookup,
  auto-pop-off as ItemEntity or hopper insertion, config-gated manual
  pickup, Inventory/Clearable traits, tick with particle effects
- Add sync_write_items_to_nbt() utility for sync-safe inventory NBT
  serialization via try_lock()
- Extend add_block_entity() and update_block_entity() to persist NBT
  with id/x/y/z fields to pending_block_entities
- Fix migrate_pending_block_entities(): run once per chunk activation
  in update_active_chunks(), add already_loaded guard
- Add chunk_data_nbt() overrides to 35 block entity types — every
  entity with persistent state now correctly sends data to clients
  and survives chunk unload/reload

* style: cargo fmt

* rename: auto_pop_off -> campfire_auto_pop_off for clarity

* fix(persistence): report contended inventory slots

* refactor: split campfire cooking from persistence

* fix(command): remove stale reload registration
2026-07-31 11:44:42 +02:00
ZlordHUN
dfbf44805b feat: implement woodland mansion generation (#2654)
Co-authored-by: Zoltán Virágh <zoltan.viragh@cloudtalk.io>
2026-07-31 11:31:15 +02:00
ZlordHUN
a3b66be27b feat: Implement pillager outpost structures (#2470) 2026-07-30 14:27:00 +02:00
Alexander Medvedev
a2263c55cc chore: update bug report template 2026-07-30 12:55:41 +02:00
Maxime Chaffraix
8a2075779b fix(worldgen): give the stronghold room chest a block entity (#2543)
The chest in the stronghold square room was placed as a bare block state,
so no chest block entity was ever created for it. Opening a chest and
resolving a double chest both go through `get_block_entity`, so the chest
could neither be opened nor paired with a chest placed next to it.

Use the existing `add_chest` helper, which writes the block state and the
matching block entity with a loot table, as the nether fortress corridors
already do. Vanilla `StrongholdPieces$RoomCrossing` uses
`chests/stronghold_crossing` at the same position.
2026-07-26 11:39:46 +02:00
Jamie Little
7552eff6b2 feat: data-driven mob spawn equipment system with vanilla-accurate gear (#2454)
Implements the full vanilla Minecraft 26.2 mob equipment system, giving
mobs weapons, armor, enchantments, and loot-pickup flags at spawn.

Added:

- Data-driven EQUIPMENT_REGISTRY mapping 13 mob types (zombie, husk,
  zombie_villager, drowned, zombified_piglin, skeleton, stray, bogged,
  wither_skeleton, piglin, pillager, vindicator) to their weapon and
  armor configurations, all verified against decompiled vanilla sources.

- Exact vanilla RegionalDifficulty formula from DifficultyInstance.java:
  computes effective_difficulty and special_multiplier from base
  difficulty, game time, chunk inhabited time, and moon phase. When
  special_multiplier is 0.0 (fresh Normal/Easy worlds), equipment,
  enchantments, and loot-pickup flags are suppressed, matching vanilla.

- Vanilla-accurate armor selection: random base tier (0-2) with up to 3
  upgrade attempts at 10.87% each, partial armor break chance (10% on
  Hard, 25% otherwise). Higher difficulty produces fewer pieces.

- Weighted enchantment selection with exclusive-set conflict resolution
  and cost-based level determination. Curated flat pools per equipment
  category (melee/trident/bow/crossbow/fishing_rod/head/chest/legs/feet).

- Per-slot equipment drop chances (0.085 default) with looting bonus
  (+lootingLevel * 0.01 per vanilla EnchantmentHelper).

- Exact vanilla drop durability formula from Mob.dropCustomDeathLoot:
  damage = maxDamage - random(1 + random(max(maxDamage-3, 1))).

- CAN_PICK_UP_LOOT mob flag (bit 3, value 8) set probabilistically at
  55% * special_multiplier.

- Guard against empty equipment packets in send_equipment_changes to
  prevent client decode crashes.

- Chunk inhabited_time tracking in world tick for difficulty scaling.

Integration: equip_mob_on_spawn is called from the blanket
EntityBase::init_data_tracker impl, so every mob type automatically
participates. New mobs are added by inserting a MobEquipmentDef into
the EQUIPMENT_REGISTRY with their weapon/armor config.

cargo check: passes / cargo clippy (pedantic): 0 warnings / cargo fmt: clean
2026-07-24 18:20:49 +02:00
Jamie Little
3ff3eeaf74 perf(world): bulk-build generated chunk palettes (#2492) 2026-07-24 17:02:29 +02:00
Alexander Medvedev
3103e97e18 ci: remove macos-15-intel 2026-07-24 12:31:57 +02:00
Alexander Medvedev
e0117ab559 perf: ditch serde because its slower
i rather trade performance and compile time over convenience
2026-07-19 18:07:37 +02:00
Alexander Medvedev
55219f870f fix: https://github.com/Pumpkin-MC/Pumpkin/issues/2233 2026-07-16 19:56:53 +02:00
Alexander Medvedev
c7be511fbc chore: some more chunk gen work 2026-07-15 19:02:31 +02:00
Alexander Medvedev
37bed1c8b5 feat(command): add fillbiome command 2026-07-14 19:19:03 +02:00
Mcxiaocaibug
1f38ba8054 feat(pumpkin): add /save-all, /save-off and /save-on commands (#2394)
Implements the three vanilla save-control commands (tracked in #15):

- /save-all saves all online players' data and advancements, then
  requests a chunk save from every world's chunk scheduler. It works
  even while autosaving is disabled, matching Vanilla.
- /save-off disables periodic autosaving via a new save_enabled flag
  on Level; running it again fails with commands.save.alreadyOff.
- /save-on re-enables autosaving; running it again fails with
  commands.save.alreadyOn.
2026-07-13 17:40:23 +02:00
Alexander Medvedev
ea7ee250fe fix: clippy 2026-07-13 13:14:00 +02:00
Alexander Medvedev
b1b2a31c49 fix: vanilla level.dat loading 2026-07-13 12:53:33 +02:00
TheDarkSword
1ca089df17 perf(generation): speed up chunk generation(#2335)
* perf(generation): cache computed structure starts

set_structure_references runs for every chunk and, for each nearby structure
candidate, recomputed the structure's placement from scratch. For jigsaw
structures (villages, ancient cities, ...) that means re-running the full
jigsaw expansion for every chunk whose references overlap the structure -- the
same start recomputed many times over.

A structure's placement depends only on its start chunk and the world seed (the
surface-height estimate it uses is position-independent and min_y is constant
per dimension), so memoize it in GlobalStructureCache and reuse it. In the
bench, structure references drop from ~342us to ~105us.

* perf(lighting): use a fast hasher in the generation light engine

The BFS light propagator's visited/shadow_cache/pending_updates maps were
aliased to std HashSet/HashMap (SipHash) despite being named "Fast". They are
probed on every neighbour of every propagated block, so the hash function
dominates. Point the aliases at rustc-hash's FxHash (already a dependency).

Lighting generation drops from ~65ms to ~36ms and full chunk generation from
~103ms to ~68ms in the bench, with identical output.

* perf(lighting): propagate light through storage, not a shadow cache

The BFS light propagator kept a hashed shadow cache of in-flight light values
plus a per-chunk batched write buffer, layered on top of the light storage. The
storage is itself a fast array lookup, so the extra hashing and buffering cost
more than they saved. Read and write it directly and treat it as the single
source of truth.

Lighting generation drops from ~36ms to ~22ms and full chunk generation from
~68ms to ~52ms, output unchanged (all pumpkin-world tests, including the
fixed-seed ancient-city parity test, still pass).

---------

Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
2026-07-11 18:46:29 +02:00
TheDarkSword
a4af4269fb fix: sky light propagation hanging on unloaded chunks (#2334)
* fix(lighting): stop sky light updates from looping on unloaded chunks

The sky light propagation could spin forever when a light update happened
next to a chunk that wasn't loaded. Writes to an unloaded chunk are dropped
silently and reads come back as 0, so the "this neighbor is darker than us"
check stayed true on every pass and the same position kept getting queued
again. In practice this hangs a tick thread when a block is broken near the
edge of the loaded area.

Skip neighbors whose chunk isn't loaded in both the increase and decrease
passes, matching how the border of loaded chunks already behaves: light
doesn't bleed into chunks that aren't there yet.

* Use Level::is_chunk_loaded for the unloaded-chunk guard
2026-07-09 20:59:38 +02:00
Alexander Medvedev
47fe060665 fix: rust 1.97 lints 2026-07-09 20:39:01 +02:00
Alexander Medvedev
339d9dde5b feat: add bedrock biome mappings 2026-07-08 17:30:55 +02:00
BitForge
adbc8e2b6a fix: prevent capacity overflow crash (#2348)
* fix: prevent capacity overflow crash when flying with elytra or in creative mode

The NoiseBasedCountPlacementModifier::get_count() can return negative i32
values when foliage noise sampling produces negative results at certain
world coordinates. The previous code cast this negative i32 directly to
usize, causing an integer wrap to ~18 quintillion, which triggered a
capacity overflow panic in Vec allocation during chunk feature generation.

This aligns with vanilla Minecraft behavior which also clamps the count
to a minimum of 0 before using it.

Closes #2345

* Hi
2026-07-07 15:53:11 +02:00
ChocoDev
da2401d07d feat: aquifer sample and top material in cave carver (#2242)
* sin/cos util

* 4 nieghbor check

* formating

* air helper

* carver wrapper

* fmt

* clippy

* clipp2

* remove local y

* out of bound guard

* fluid tick

* surface rule

* wire up

* math correct

* start fix

* bring back xoroshiro oops

* scheduler guard

* simplify test

* clean test

* comment

* crash fix

* clippy

* clippy

* i hate you codex

* sin cos

* im stupid f32
2026-07-05 15:55:43 +02:00
Alexander Medvedev
5d117b3213 fix: ci in release 2026-07-03 19:26:17 +02:00
Alexander Medvedev
a9f69fea01 chore: enforce clippy lints in pumpkin-world 2026-07-03 18:51:47 +02:00
PigTurtle
7bfc6a6737 refactor(data) BlockId and BlockStateId wrapper types (#2328)
* refactor: less manual BlockMetadata impls

* refactor: added BlockId type

BlockId is a wrapper for u16: it is valid for any u16 that is the id of a Block.
- Changed the Block.id field type to BlockId
- added named BlockId constants
- BlockMetadata::ids() now returns Box<[BlockId]>
- adjusted pumpkin-macros to use BlockId constants
- fixed some methods that were comparing blockstate ids or item ids (u16) against block ids (previously u16)

TODO: check if unsafe blocks can be removed; The compiler might understand that BlockId is always a valid index into mappings::TYPE_FROM_RAW_ID

* refactor: added BlockStateId type

A BlockStateId is a safe wrapper around the numerical index of a BlockState in pumpkin-data. They help avoiding validity checks (outside of IO and, currently, plugins), and make it easier for other contributors to reason about what they're comparing; BlockStateIds, BlockIds or Item ids (still u16).
pumpkin-data::BlockStateId replaces RawBlockState and BlockStateId from pumpkin-world.

- added the BlockStateId wrapper type
- made (almost; plugins) every function interacting with block states or block state ids use the wrapper type
- changed codegen logic to create/work with BlockStateIds
- made ChunkPalette parsing check BlockStateId validity (pumpkin-world::chunk::format::ChunkSectionBlockStates)

TODO: check if unsafe blocks can be removed; The compiler might understand that BlockStateId is always a valid index into mappings::BLOCK_ID_FROM_STATE_ID and mappings::STATE_FROM_STATE_ID

* refactor: imports
changed every use pumpkin_world::BlockStateId to pumpkin_data::BlockStateId

* refactor: Block- & BlockStateId

finishing touches;
- rebased on latest mater
- ensure there are no bound checks on Block(State)Id conversions, making them extremely cheap
  - this required unsafe std::hint::assert_unchecked annotations because the compiler is (occasionally) stupid
  - on debug builds the bound checks still exist because of ub_checks (see rust unstable book for the feature of the same name)
- added Safety notes to hopefully prevent anyone from enabling the creation of invalid Block(State)Ids in the future

- fixed a benchmark
2026-07-01 18:05:05 +02:00
ZlordHUN
395c4aa36b feat(generation): implement ancient city jigsaw structures (#2329) 2026-07-01 09:11:47 +02:00
dongzh1
af712b714e fix(pumpkin-world): correct inverted liquid_block_count (#2316)
BlockPalette::liquid_block_count() returned the inverse of what it
should: the Homogeneous arm returned 0 when the section was liquid and
the full VOLUME (4096) when it was not, and the Heterogeneous arm summed
the counts of non-liquid blocks (filtering on !is_liquid).

Flip both arms to actually count liquid blocks, mirroring the correct
sibling non_air_block_count(): Homogeneous yields VOLUME when the single
block is liquid (0 otherwise) and Heterogeneous filters on is_liquid.

This value is sent to clients as the fluid count in chunk data
(MC 26.1+), so the inversion reported wrong fluid counts to players.
2026-06-30 19:23:17 +02:00
ZlordHUN
5eb7cc0e81 feat: Add Overworld Fossil Generation (#2319) 2026-06-30 19:08:44 +02:00
Alexander Medvedev
7ff990c468 fix: bedrock crafting 2026-06-29 21:20:40 +02:00
Alexander Medvedev
8c5d6dc405 fix: bedrock SActorEvent packet 2026-06-28 13:26:32 +02:00
Alexander Medvedev
1dbfb75ecc fix: end spawning 2026-06-27 14:57:40 +02:00
Alexander Medvedev
322b7af6ae chore: made tnt explosion bit faster 2026-06-26 21:43:00 +02:00
Alexander Medvedev
23e7992b2d Port to 26.2 2026-06-20 20:07:31 +02:00
Alexander Medvedev
8634d8740f fix: nether/end 2026-06-13 22:44:29 +02:00
Alexander Medvedev
68bae5899e feat: add stats 2026-06-12 20:55:29 +02:00
Alexander Medvedev
b4a652c68c fix: ci 2026-06-12 06:58:14 +02:00
Alexander Medvedev
acb295b250 fix: ci/test 2026-06-11 23:02:42 +02:00
Alexander Medvedev
5b8eab0f56 feat: initial village support 2026-06-10 23:07:10 +02:00
ChocoDev
636331ead3 chore update world generation benchmark (#2216)
* benchmark

* clippy
2026-06-09 16:01:40 +02:00
shaches
1f63fae486 fix(world): handle unsupported custom anvil compression (#2217) 2026-06-04 10:24:36 +02:00
shaches
440d222f8a fix: stale proto chunk generation tasks (#2214) 2026-06-04 10:18:24 +02:00