Commit Graph

2427 Commits

Author SHA1 Message Date
Alexander Medvedev
339d9dde5b feat: add bedrock biome mappings 2026-07-08 17:30:55 +02:00
TheDarkSword
c82bf52aec perf(pumpkin): tick block entities per active chunk instead of scanning all (#2340)
Block entities lived in one flat DashMap keyed by BlockPos, and every world
tick rebuilt the tick list by iterating the entire map and filtering it down
to the active chunks. That is O(all loaded block entities): the more of the
world that has been explored (chests, signs, hoppers... all count), the
longer every tick spends walking block entities it is not going to tick, so
TPS slowly bleeds away on long-running worlds.

Key the map by chunk instead (chunk -> its block entities). Ticking now walks
only the handful of active chunks and their entries, inserts/removals/lookups
compute the chunk key up front, and unloading a chunk drops its whole bucket.
Behaviour is unchanged - the same block entities get ticked - it just stops
scanning the ones that are loaded but nowhere near a player.
2026-07-07 16:00:27 +02:00
TheDarkSword
984e0098e2 perf(pumpkin): only tick entities in active chunks (#2341)
The world tick iterated every entity in the world and ticked all of them,
regardless of where they were - so entities sitting in loaded-but-not-active
chunks kept running their AI, movement and player-collision checks every tick.
That is O(all loaded entities) and grows as a world is explored, bleeding TPS
on long-running servers.

Skip entities whose chunk isn't in the active (ticking) set - the same set
block-entity ticking and mob spawning already use, and matching vanilla, which
only ticks entities within the simulation distance. The check uses the live
position rather than the cached chunk_pos, since fast movers (minecarts,
projectiles) update pos directly and leave chunk_pos stale.

Players are ticked separately and aren't in this list, so they're unaffected.
2026-07-07 15:59:41 +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
Red
0de72cbf18 feat(plugin-api): Forced use of setters (#2333) 2026-07-07 15:26:30 +02:00
ZlordHUN
cc2b537371 fix: set client player before spawn to prevent invisible chunks on first join (#2307)
* Fix First Join Invisible Chunk

* downgrade warn! to debug! in send_chunks drop path
2026-07-07 14:20:18 +02:00
Alexander Medvedev
44fd621294 fix: bedrock block mappings 2026-07-06 21:49:42 +02:00
yunuservices
5d27ab34d3 feat(plugin-api) Add ServerLoadEvent (#2302)
* feat: add ServerLoadEvent

* fix: address ServerLoadEvent review feedback
2026-07-06 20:01:54 +02:00
dependabot[bot]
8c1064908b build(deps): bump crate-ci/typos from 1.47.2 to 1.48.0 (#2349)
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.47.2 to 1.48.0.
- [Release notes](https://github.com/crate-ci/typos/releases)
- [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crate-ci/typos/compare/v1.47.2...v1.48.0)

---
updated-dependencies:
- dependency-name: crate-ci/typos
  dependency-version: 1.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-06 09:02:38 +02:00
Alexander Medvedev
4ec2315aef chore: implement all missing raknet packets 2026-07-05 20:26:32 +02:00
kedor
560a0ed77d feat(config): add Configuration for advancement saving (#2259)
* implementing the advancement configuration for saving or not the advancements

* adding a test for not loading files when save is disabled

* cargo fmt

* fix merge

* Fix variable name for players directory
2026-07-05 16:36:36 +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
3aea5ee720 fix: ci 2026-07-04 15:14:55 +02:00
Alexander Medvedev
c60fa90ed8 feat(bedrock): Add Protocol encryption 2026-07-04 15:01:42 +02:00
Aalivexy
52838d945b fix: trigger PlayerChangeWorldEvent on cross-dimension respawn (#2228) (#2250)
Rebased onto current master after #2296 (PlayerRespawnEvent).

- Fire PlayerChangeWorldEvent (cancellable) before the cross-dimension
  transfer in World::respawn_player; a plugin may redirect new_world,
  override position/yaw/pitch, or cancel to keep the player in the
  current world.
- Use the safe transfer ordering (remove_player -> unload_watched_chunks
  -> change_world -> set_world -> publish) so no observer sees the player
  in a world whose chunk manager doesn't match, and update the entity's
  world reference (set_world) to fix the latent stale-world bug.
- When cancelled or the target world can't be resolved, fall back to the
  current world's spawn.
- The non-cancellable PlayerRespawnEvent (#2296) now fires after this
  event and observes the resolved world automatically; document the
  ordering and mutation-vs-cancellation semantics on both events.
2026-07-04 12:21:46 +02:00
Red
28d6450426 fix: Made (CUSTOM_)NAME_VISIBLE work across versions (#2332) 2026-07-04 12:14:29 +02:00
Niclas
0800ed8878 feat(plugin-api): add namespaced custom item data (#2324)
* feat(plugin-api): add namespaced custom item data

* modified: pumpkin-plugin-wit

* feat(plugin-api): add NBT custom item data

* fix(plugin-api): satisfy clippy for NBT tree conversion

* feat(plugin-api): add NBT custom item data

* test(plugin-api): use neutral custom data fixtures

---------

Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
2026-07-04 09:50:06 +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
Niclas
920fc3ec50 fix: preserve infinite status effect durations (#2292) 2026-07-01 18:27:23 +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
dongzh1
ae1813735b fix(inventory): guard Swap slot click against negative slot index (#2313)
The `Swap` branch of `internal_on_slot_click` indexed
`self.get_behaviour().slots[slot_index as usize]` without first checking
`slot_index >= 0`, unlike every sibling branch (Pickup, QuickMove, Throw,
Clone, QuickCraft) which all guard with `if slot_index < 0 { return; }`.

`slot_index` originates from the client `SClickSlot` packet (`i16` slot
field, widened to `i32`). The upstream validation in `Player::on_slot_click`
relies on `ScreenHandler::is_slot_valid`, whose check
`slot == -1 || slot == -999 || slot < slots.len() as i32` returns `true`
for ANY negative slot (a negative value is always `< slots.len()`), so
negative indices are not filtered out before reaching the handler. A
crafted Swap packet with a negative slot (e.g. -5) and a hotbar button in
`0..9` (or 40) therefore evaluated `slots[(-5) as usize]`, an enormous
index, causing an out-of-bounds Vec panic and crashing the server.

Add the same `if slot_index < 0 { return; }` guard at the top of the Swap
branch, matching the sibling branches exactly. Minimal, low-risk: legitimate
Swap clicks always carry a non-negative container slot, so behaviour is
unchanged for valid input.
2026-07-01 13:43:54 +02:00
kedor
d8b7ae30a5 feat: add Seen advancement packet (#2326) 2026-07-01 13:21:45 +02:00
ZlordHUN
395c4aa36b feat(generation): implement ancient city jigsaw structures (#2329) 2026-07-01 09:11:47 +02:00
Mateus
e47061b44b fix: C_GLAZED_TERRACOTTAS ids (#2331)
Changed ids() in glazed_terracotta.rs from tag::Item to tag::Block
2026-07-01 09:07:49 +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
AnthonyDuong1
85c4ce0483 fix: creative fire ticks (#2308) 2026-06-30 19:20:24 +02:00
AnthonyDuong1
fbfc706f7b fix: air supply under water (#2317) 2026-06-30 19:18:01 +02:00
kedor
22c871ed9b fix(protocol): recipe book packet (#2318)
* fix recipe display to use itemStackTemplate parsing

* fix advancement packet
2026-06-30 19:13:16 +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
efa97ad174 fix: https://github.com/Pumpkin-MC/Pumpkin/issues/2283 2026-06-28 16:18:49 +02:00
Alexander Medvedev
8c5d6dc405 fix: bedrock SActorEvent packet 2026-06-28 13:26:32 +02:00
Niclas
28e8187f23 fix(plugin-api): expose data components to Rust plugins (#2306) 2026-06-28 09:35:52 +02:00
Alexander Medvedev
2f653f6336 feat: bedrock crafting 2026-06-27 22:16:21 +02:00
kedor
0eb7cb1a79 fix(advancement): Fix advancement tree and visibility (#2304)
* fix visibility evaluator

* fix a small issue with the placement of advancement
2026-06-27 20:42:35 +02:00
Alexander Medvedev
25048f5a6c fix: 2 bedrock packets 2026-06-27 17:44:55 +02:00
Alexander Medvedev
1dbfb75ecc fix: end spawning 2026-06-27 14:57:40 +02:00
Alexander Medvedev
03a90a40b1 chore: expand loot table 2026-06-27 10:35:46 +02:00
Alexander Medvedev
322b7af6ae chore: made tnt explosion bit faster 2026-06-26 21:43:00 +02:00
kedor
39596c1b9f feat: Advancement command (#2282)
* starting implementing the advancement command

* implementing globally of the advancement command

* fixing lib.rs

* implementing the new Advancement argument and updating the AdvancementArgs lifetime

* updating wit by adding advancement as command arg

* cargo fmt

* fixing the advancement
hooking the saving
spawn blocking task for IO task

* fixing the update of load to be async

* adding await to load for a test

* fix when save is disable

* making save_enable check first

* fix conflict

* update hash

* fix wit change

* fix column_pos

* adding rust documentation

* typos fix

* removing example

* invalid advancement packet

* fix itemstack parsing to use ItemStack Template ones

* changing enum type from i32 to VarInt

* fix packet by switching up the frame type and flags

* fixing packet and loading of the advancement

* cargo clippy

* update wit
2026-06-26 09:23:54 +02:00
BitForge
785de6d644 fix(inventory): prevent shield self-deadlock in prepare_hand_item_for_use (#2295)
When a player right-clicks with a shield already in the off-hand,
`prepare_hand_item_for_use` locks the ItemStack Mutex via `held`,
then tries to lock the same Mutex again through `get_or_insert`.
Tokio's Mutex is not reentrant, causing a permanent deadlock that
crashes the server 5 seconds later when the tick loop times out.

Add `PlayerInventory::is_already_equipped()` which uses Arc::ptr_eq
to detect when the item is already in the target slot, and skip the
redundant equip logic before any lock is attempted.

Closes #2288
2026-06-25 19:36:30 +02:00
Missing_Love
3b9c2bdf6d fix(player): fix newly joined players not seeing existing players in tab list (#2280)
* fix:tab_list

* fix:tab_list
2026-06-25 17:47:06 +02:00
SomeYellowGuy
e4bec2b14a fix(entity): split the types of wind charges (#2293) 2026-06-25 17:45:06 +02:00
Niclas
2fa7a1829b fix(protocol): encode and decode renamed item names (#2301) 2026-06-25 17:44:11 +02:00
Niclas
849cb05e07 fix(world): persist end portal block entity data (#2294) 2026-06-25 17:36:18 +02:00
dongzh1
86e41e1ebb feat(plugin): add PlayerRespawnEvent (#2296)
Adds a non-cancellable PlayerRespawnEvent fired from World::respawn_player
once a respawn destination (world, position, rotation) is determined,
exposing it to plugins through the WIT event API (host + guest). The
previous world, respawned world, position, yaw, pitch and whether the
player kept their data are provided. Bumps the pumpkin-plugin-wit
submodule to the matching event definition.

Closes #1714. Depends on Pumpkin-MC/pumpkin-plugin-wit#8.
2026-06-25 13:47:00 +02:00
Alexander Medvedev
9055a6133e fix: respawn packet data 2026-06-24 21:12:27 +02:00
Alexander Medvedev
2c0e981a85 fix: https://github.com/Pumpkin-MC/Pumpkin/issues/2253 2026-06-24 19:44:59 +02:00
Tunar Məmmədli
35c3ebf6b5 fix(math): prevent NaN from zero-length normalization (#2202)
* Guard vector normalization against zero length

* improve vector normalization
2026-06-24 19:18:48 +02:00