* feat: broadcast EntityStatus when equipment breaks
Pumpkin did not play any sound or show break particles when a tool or
piece of armour reached zero durability. Vanilla sends a per-slot
EntityStatus packet (47-52, 65, 68) that every nearby client uses to
play the break sound and spawn break particles textured with the item
that just broke.
Changes
-------
player.rs – new damage_item_in_slot(slot, amount) method:
- Generalises the old damage_held_item to cover all EquipmentSlots:
MainHand, OffHand, Head, Chest, Legs, Feet.
- Resolves the correct PlayerInventory slot index per slot (36-39 for
armour, 40 for off-hand) consistent with build_equipment_slots().
- Sends the EntityStatus break packet BEFORE clearing the slot so
clients can use the item texture for break particles.
- Bypasses sync_hand_slot (which only broadcast for hand slots) and
instead calls enqueue_slot_set_packet + send_equipment_changes
directly, ensuring armour equipment changes also propagate.
- damage_held_item is kept as a thin convenience wrapper.
apply_mending_from_xp – DRY refactor:
- Replaces three separate candidate-gathering blocks (main hand, off
hand, armour loop) with a single unified slot_pairs list iterated
once. Behaviour is identical.
living.rs – damage_armor_items:
- When a player takes hit damage, armour durability is reduced through
LivingEntity::damage_armor_items, a separate code path from the
player item-damage methods. This path now also broadcasts the
EntityStatus break packet when an armour piece's durability hits zero.
entity/mod.rs – shared helper:
- Add equipment_break_status(slot) -> EntityStatus as a #[must_use]
pub const fn. Eliminates the duplicated slot→status match that would
otherwise exist in both call sites (player.rs and living.rs).
Tests (16 new)
--------------
- entity::tests::equipment_break_status_maps_all_slots – asserts every
EquipmentSlot variant (including Body and Saddle) maps to its
expected EntityStatus break variant.
- item::tests (15 tests) – first unit tests for ItemStack durability
logic, covering damage_item_with_context (zero/negative amount,
non-damageable item, unbreakable item, accumulation, stack break at
max damage, over-damage) and repair_item (zero/negative amount,
undamaged item, partial repair, cap at current damage, full repair
clears the Damage component patch entry) and set_damage (negative
value clamps to zero).
* refactor: use table-driven cases in damage_increases_damage_value test
* chore: make clippy happy
* refactor: the rest of damage and repair tests to use table-driven cases
* feat: broadcast EntityStatus when equipment breaks
- Implement strict packet ordering (EntityStatus before slot sync)
- Add break broadcast in play.rs use_on_block for all tools
- Generalize damage_item_in_slot to support all equipped slots
- Trim PR comments to 1-2 professional lines
- Convert equipment_break_status test to table-driven format
- Ensure vanilla parity per decompiled 1.21.11 EntityEvent mappings
* feat(item): durability overhaul — DamageResult, armor/weapon parity, elytra fix
pumpkin-world
- Add DamageResult enum (Untouched/Damaged/Broken) replacing bool return on
damage_item_with_context and damage_item
- Elytra clamped at max_damage-1; never deleted from inventory
- Stacked item break correctly returns Broken regardless of remaining count
- Add is_axe/is_pickaxe/is_shovel/is_hoe tag-based predicates to ItemStack
- 21 new unit tests covering all cases (elytra, stacks, Unbreaking, categories)
pumpkin
- Armor damage type filter: bypasses_armor_durability() driven by the
vanilla minecraft:bypasses_armor data tag (1.21.11); id-based u8 lookup
- Elytra worn in armor slot skipped from hit damage
- Thorns: extra +2 durability cost + 1-4 magic retaliation damage
- Weapon 2-durability cost: axes/pickaxes/shovels/hoes in combat
- Fix armor slot Unbreaking formula (is_armor_slot() gate)
- Fix stacked-item break broadcast (Broken not is_empty())
- Extract combat_weapon_durability_cost as sync fn; reuse existing lock
- 5 forward-compatible TODO one-liners for shield/trident/crossbow/fishing rod/brush
* fix(item): resolve vanilla parity issues in durability and combat tracking
- Move armor durability calculation to pre-absorption damage
- Fix Thorns damage range to uniform float [1.0, 5.0) and correct execution order
- Attribute Thorns damage to victim for correct combat tracking
- Refactor `damage_item` to auto-infer armor via `#minecraft:enchantable/armor`
- Decouple Elytra clamping from generic item damage loop into dedicated methods
- Add TODOs for DAMAGE_RESISTANT, post-attack effects, and data-driven bypasses
Also reformatted long comments to be concise and techincal
* chore: trigger CI rerun
* fix: shears no longer take durability damage when attacking mobs (refactor + codegen to standardize)
Replace hardcoded item-category checks in combat_weapon_durability_cost
with a data-driven lookup of the minecraft:weapon component.
- Add item_damage_per_attack field to WeaponImpl with DataComponentImpl
- Wire WeaponComponent deserialization into pumpkin-codegen item builder
- Regenerate item data so weapon durability values come from items.json
- Items without the Weapon component (e.g. shears) return 0 cost
* chore: retrigger CI
* refactor: Remove Thorns retaliation and trigger mechanics
- Remove Thorns enchantment trigger check and probability
- Remove Thorns extra +2 durability cost on armor
- Remove Thorns retaliation damage to attacker (1-5 magic damage)
- Remove Thorns combat attribution via damage_with_context
- Remove related imports and TODO comments
- Keep source parameter for future compatibility
* fix: glaring issues
- Fix WeaponImpl::read_data to actually read item_damage_per_attack from NBT
instead of hardcoding 1; custom weapons now load correctly
- Remove unused _source parameter from damage_armor_items signature
- Move is_axe/is_pickaxe/is_shovel/is_hoe behind #[cfg(test)] since they're
test-only helpers, keeping public API clean
* fix: elytra unbreaking and Pre-absorption Armor Test
Also a comment for clarity
* refactor: remove elytra scope creep: damage handling and related tests
* adjustment: tighten unbreaking test, update comments to be correct
* fix: clamp negative NBT, widen Unbreaking test, document elytra and shield-disable TODOs
* refactor: armor bypass logic: use bitmask, hoist lookups, optimize durability loop
* feat: Remove hardcoded Elytra armor check; use EquippableImpl::damage_on_hurt for data-driven durability logic.
* fix: add bitmask compile-time assert, clarify NBT clamping, document damage_on_hurt logic, rename slot_result, add #[must_use] to damage_item, and fix all unused result warnings.
* fix: clarify stacked item break edge, strengthen bitmask asserts, document NBT error handling, add TODOs for tool break handling and loop short-circuit, remove dead code and trident stub, note TOCTOU, and document test determinism. All tests passing.
* fix: Various
CRITICAL ITEMS:
* bypasses_armor_durability correctness: Verified by existing test suite
(validates all 19 bypass types return true, 12 physical types return false).
* TOCTOU race in attack(): Enhanced documentation with 3 specific mitigation
options and justification for single-player safety.
* must_use suppressions: Removed #[must_use] from damage_item; added TODO to
restore once all DamageResult::Broken handlers implement proper semantics.
SIGNIFICANT ITEMS:
* DamageResult::Broken semantics: Updated doc comment to clarify that breaking
always broadcasts correctly—whether consuming a single item or decrementing
a stack. Callers need not split the enum.
* Stacked item multi-break behavior: Verified matches vanilla (one break per
call, never chains). Updated comment to document this as correct behavior,
not a regression.
* should_apply_durability_damage_with visibility: Made private to prevent
incorrect unbreaking formula usage outside durability context.
* Elytra exemption caching optimization: Added PERF comment noting O(1)
component lookup is already efficient (max 4/hit). Deferred to dedicated
caching architecture pass.
MINOR ITEMS:
* Unbreaking test windows: Tightened from (500–1500) to (865–1135) for ±5σ
confidence—catches actual formula regressions while remaining statistically
sound. Updated both tool and armor tests.
* WeaponImpl NBT error handling: Documented conservative fallback behavior
(clamp negatives, default missing keys). Added TODO for tracing::warn! at
higher-level call site.
* default_item_damage naming: Renamed return_1u32 for consistency and clarity
in weapon damage context.
* WeaponImpl Hash collision prevention: Added struct-level NOTE reminding
developers to update get_hash() if fields are added. Deferred until
multi-field scenario (currently impossible with one field).
* fix: Resolve duplicate `return_1f32` and restore `#[must_use]` on `damage_item`
- Removed duplicate `return_1f32` function in `pumpkin-codegen/src/item.rs` to fix a compile blocker.
- Restored `#[must_use]` attribute on `damage_item` in `pumpkin-world/src/item/mod.rs` to enforce proper handling of `DamageResult`.
* fix: several effects (ticking and instant)
* chore: clippy and formatting
* fix: optimize send_attribute_update calls and stored active_effects
* feat: add infested support
* feat: per-entity attributes system
* refactor: clean up living.rs and apply some fixes
* feat: attributes system, absorption, and health boost!
* chore: clippy and formatting
* chore: oof
* chore: installed typos lol
* fix: updated some default attributes
* fix: glowing and invisibility
* fix: imports and proper base_damage
* fix: remove effect damage dupe from try_attack
* fix: bat default attributes
* fix: silverfish default attributes
* fix: check local attribute base first
* Remove erroneous comment (near glowing effect removal)
forgot to remove this after copying the block from add_effect 💀
* fix: update other mob default attributes
* sheep ai (#1604)
* feat: sheep AI with wool color, eating grass, escape panic, and tempt
* fix: check both hands for tempt items
* beg goal (#1611)
* follow owner goal
* fix teleport validation and look target
* trigger ci
* feat: bat ai with roosting, flying, and damage wake-up
* fix clippy
* fix: bat ai improvements matching vanilla behavior
- Move velo.y dampening into travel_in_air via get_y_velocity_drag
- Set bat gravity to 0 (vanilla bat travel has no gravity)
- Fix on_damage firing before damage validation
- Remove unused caller param from post_tick (eliminates Arc clone)
- Add ambient idle sounds every 80 ticks
- Pre-validate flight targets to avoid water, lava, and hazards
* switch to btreemap to comply with lint
* amplifier i32 -> u8
* switch allow to expect lint
* remove many many unnecessary clippy lints
* dont use expect inside quotes
* beetroot chance 1/3
* prevent sugar cane from growing more than 3 high
* add sweet berry bush
* check for block above
* start nether warts
* nether warts with random ticks
* cargo fmt
* bamboo!
* pass when using bone meal on sweet berry bush with age < 3
* fix first two bamboo not being wide
* use early returns to flatten nesting
* switch damage and damage context to take references instead of arcs
* entity collision damage with sweet berry bush and campfire
* prevent panic and instead just reject placement if y < 0
* fix cactus growing and add cactus flowers
* cargo fmt
* switch to btreemap to comply with lint
* amplifier i32 -> u8
* switch allow to expect lint
* remove many many unnecessary clippy lints
* dont use expect inside quotes
* Added bed block entity
* Player can sleep
* Format
* Respawn point works
* Clippy
* Added dimension support
* Sleeping works!
* Bed explodes when not in overworld
* Omg there was a packet missing
* Clippy
* Sleeping checks fully working!
* Clippy
* Wrong tick time
* Bruh mb