refactor: extract generic digging system, drop tables, remove debug code

- New src/entities/item/drop_table.rs: DropEntry (chance, min/max count,
  pseudo-RNG roll) + DropTable wrapper. grass=5% coin 1-2, rock=10% coin 1,
  dirt/air=none.
- New src/entities/shared_systems/digging.rs: Digger component + dig_system.
  Any entity with Digger digs the tile below on its interval. Replaces
  rabbit_dig_system/rabbit_fall_debug_system/RabbitDigTimer/RabbitFallDebug.
- New TileMap::dig_floor: remove_floor + insert air. Used by dig_system.
- FloorTileData: added drop_table field. Lost Copy derive (Vec field).
  Updated all 6 terrain.rs call sites with per-tile drop tables.
- Pig: removed PigDropTimer + pig_drop_system. Drops were debug placeholder.
  TODO added for future loot-on-death/butcher system.
- Rabbit: removed all debug components/systems. Now uses Digger::new(5.0).
- main.rs: removed rabbit_dig_system/rabbit_fall_debug_system/pig_drop_system,
  added shared_systems::digging::dig_system.
This commit is contained in:
2026-03-21 15:40:34 +00:00
parent 1a170ea9a9
commit ce3746366c
9 changed files with 238 additions and 301 deletions
+36 -14
View File
@@ -4,6 +4,9 @@ use bevy_platform::time::Instant;
use noise::{NoiseFn, Perlin};
use std::sync::{Arc, Mutex};
use crate::entities::item::drop_table::{DropEntry, DropTable};
use crate::entities::item::prefabs::misc::misc_prefabs::MiscPrefab;
use crate::{
config::TileRegistry,
constants::{SEED, TILE_SIZE},
@@ -14,6 +17,19 @@ use crate::{
},
};
fn drop_table_for(tile_name: &str) -> DropTable {
match tile_name {
"grass" => DropTable(vec![
DropEntry::chance(MiscPrefab::Coin, 0.05, 1, 2),
]),
"dirt" => DropTable::default(),
"rock" => DropTable(vec![
DropEntry::chance(MiscPrefab::Coin, 0.1, 1, 1),
]),
_ => DropTable::default(),
}
}
/// Thread-safe storage for completed terrain blobs.
/// Uses type erasure to avoid Debug bounds on TerrainBlob.
type BlobStorage = Arc<Mutex<Box<dyn Send + Sync>>>;
@@ -114,6 +130,7 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
tile.transparent,
tile.astar_weight,
[0; 8],
drop_table_for("air"),
),
));
chunk_data.set_floor_tile(
@@ -136,6 +153,7 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
tile.transparent,
tile.astar_weight,
[0; 8],
drop_table_for("rock"),
),
));
chunk_data.set_floor_tile(
@@ -146,20 +164,21 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
tile.can_stand_in,
tile.can_stand_on,
tile.astar_weight,
);
} else {
let tile = registry.floor("dirt");
tile_updates.push((
pos_ivec,
FloorTileData::new(
tile.id,
tile.can_stand_in,
tile.can_stand_on,
tile.transparent,
tile.astar_weight,
[0; 8],
),
));
);
} else {
let tile = registry.floor("dirt");
tile_updates.push((
pos_ivec,
FloorTileData::new(
tile.id,
tile.can_stand_in,
tile.can_stand_on,
tile.transparent,
tile.astar_weight,
[0; 8],
drop_table_for("dirt"),
),
));
chunk_data.set_floor_tile(
local_x,
local_y,
@@ -182,6 +201,7 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
tile.transparent,
tile.astar_weight,
[0; 8],
drop_table_for("grass"),
),
));
chunk_data.set_floor_tile(
@@ -205,6 +225,7 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
tile.transparent,
tile.astar_weight,
[0; 8],
drop_table_for("dirt"),
),
));
chunk_data.set_floor_tile(
@@ -228,6 +249,7 @@ fn generate_terrain_blob(chunk_pos: IVec2) -> TerrainBlob {
tile.transparent,
tile.astar_weight,
[0; 8],
drop_table_for("air"),
),
));
chunk_data.set_floor_tile(
+26 -1
View File
@@ -33,16 +33,18 @@ use rustc_hash::FxHashMap;
use super::chunk_data::ChunkData;
use crate::constants::ITILE_SIZE;
use crate::entities::item::drop_table::DropTable;
use crate::world::chunks::{world_to_chunk, CHUNK_SIZE, Z_ABOVE, Z_BELOW};
/// Packed floor tile data for efficient storage. ~35 bytes vs 76 bytes tuple.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Debug)]
pub struct FloorTileData {
pub id: u8,
/// bit0=can_stand_in, bit1=can_stand_on, bit2=visibly_transparent
pub flags: u8,
pub astar_weight: u8,
pub visible_range: [u32; 8],
pub drop_table: DropTable,
}
impl Default for FloorTileData {
@@ -52,6 +54,7 @@ impl Default for FloorTileData {
flags: 0b001,
astar_weight: 0,
visible_range: [0; 8],
drop_table: DropTable::default(),
}
}
}
@@ -64,6 +67,7 @@ impl FloorTileData {
visibly_transparent: bool,
astar_weight: u8,
visible_range: [u32; 8],
drop_table: DropTable,
) -> Self {
let mut flags = 0u8;
if can_stand_in {
@@ -80,6 +84,7 @@ impl FloorTileData {
flags,
astar_weight,
visible_range,
drop_table,
}
}
@@ -214,6 +219,26 @@ impl TileMap {
self.floor_tiles.insert(pos, tile);
}
pub fn dig_floor(&mut self, pos: &IVec3) -> Option<FloorTileData> {
let removed = self.remove_floor(pos);
if removed.is_some() {
let air = crate::config::TileRegistry::global().floor("air");
self.insert_floor(
*pos,
FloorTileData::new(
air.id,
air.can_stand_in,
air.can_stand_on,
air.transparent,
air.astar_weight,
[0; 8],
DropTable::default(),
),
);
}
removed
}
#[inline]
pub fn insert_fixture(&mut self, pos: IVec3, tile: FixtureTileData) {
let chunk_pos = world_to_chunk(pos);