Files
dorf/src/entities/item/systems.rs
T
popertots 466a20700a Wrap TileMap HashMaps in Arc for async pathfinding access
- Add Arc<AHashMap> wrapper around floor_tiles, fixture_tiles, item_tiles
- Copy-on-write semantics: Arc::make_mut clones only if other Arcs exist
- Add insert_floor, insert_fixture, insert_item, remove_item methods
- Add get_floor_mut, get_fixture_mut for visibility updates
- Update all mutation sites to use new TileMap methods
- Enables cheap Arc::clone for async pathfinding workers
- Single-threaded pathfinding: no clone, direct access
- Multi-threaded pathfinding: clone Arc, read without locks
2026-03-18 14:56:57 +00:00

170 lines
5.2 KiB
Rust

use bevy::prelude::*;
use bevy_platform::collections::HashMap;
use crate::entities::item::decorations::ItemDecorations;
use crate::entities::item::material::{GemType, Material, MetalType};
use crate::entities::item::quality::Quality;
use crate::entities::item::types::ItemType;
use crate::entities::item::Item;
use crate::entities::item::ItemBundle;
use crate::entities::item::ItemName;
use crate::world::tiles::TileMap;
pub fn stain_fade_system(time: Res<Time>, mut items: Query<&mut Item>) {
if time.elapsed_secs_f64() as u32 % 10 == 0 {
for mut item in items.iter_mut() {
item.reduce_stain_time(1);
}
}
}
/// Ensures all items in item_tiles have the ItemRotationState component.
/// This handles items that were spawned before the rotation system was added,
/// or items that somehow got missing the component.
pub fn initialize_item_rotation_state(
mut commands: Commands,
items_without_state: Query<(Entity, &Item), Without<ItemRotationState>>,
) {
for (entity, _item) in items_without_state.iter() {
commands.entity(entity).insert(ItemRotationState {
should_be_visible: true,
});
}
}
// Helper function to create a decorated item (DEMO ONLY)
pub fn create_decorated_item(
commands: &mut Commands,
item_type: ItemType,
base_material: Material,
quality: Quality,
position: Vec3,
sprite: Sprite,
) -> Entity {
let mut decorations = ItemDecorations::new();
// Example: Add a ruby encrusting to valuable items
if quality >= Quality::Superior {
decorations.add_gem_encrusting(
Material::Gem(GemType::Ruby),
0.5, // Small gem
Quality::WellCrafted,
);
}
// Example: Add silver trim to masterwork items
if quality >= Quality::Masterwork {
decorations.add_trim(
Material::Metal(MetalType::Silver),
0.2, // Small amount of trim
quality,
);
}
// Example: Add engraving to exceptional+ items
if quality >= Quality::Exceptional {
decorations.add_engraving("a majestic dorf holding a pickaxe".to_string(), quality);
}
commands
.spawn(ItemBundle {
item: Item {
quality,
..Item::default()
},
item_type: item_type.clone(),
base_material,
decorations,
transform: Transform::from_translation(position),
visibility: Visibility::Visible,
sprite: sprite,
})
.insert(ItemName::new(item_type.name()))
.id()
}
#[derive(Resource)]
pub struct ItemRotationTimer {
timer: Timer,
current_indices: HashMap<IVec3, usize>,
}
impl Default for ItemRotationTimer {
fn default() -> Self {
Self {
timer: Timer::from_seconds(0.4f32, TimerMode::Repeating),
current_indices: HashMap::default(),
}
}
}
#[derive(Component)]
pub struct ItemRotationState {
pub should_be_visible: bool,
}
pub fn item_tile_management_system(
time: Res<Time>,
mut tilemap: ResMut<TileMap>,
mut rotation_timer: ResMut<ItemRotationTimer>,
mut item_query: Query<&mut ItemRotationState, With<Item>>,
) {
rotation_timer.timer.tick(time.delta());
if rotation_timer.timer.just_finished() {
let positions: Vec<IVec3> = tilemap.item_tiles.keys().copied().collect();
for position in positions {
let items = match tilemap.item_tiles.get(&position) {
Some(i) => i.clone(),
None => continue,
};
// Clean up empty tiles
if items.is_empty() {
tilemap.remove_item(&position);
rotation_timer.current_indices.remove(&position);
continue;
}
// Single item: ensure visible
if items.len() <= 1 {
if let Some(&entity_id) = items.first() {
if let Some(entity) = Entity::from_raw_u32(entity_id) {
if let Ok(mut rotation_state) = item_query.get_mut(entity) {
rotation_state.should_be_visible = true;
}
}
}
continue;
}
// Rotate visibility
let current_index = rotation_timer
.current_indices
.get(&position)
.copied()
.unwrap_or(0);
for entity_id in &items {
if let Some(entity) = Entity::from_raw_u32(*entity_id) {
if let Ok(mut rotation_state) = item_query.get_mut(entity) {
rotation_state.should_be_visible = false;
}
}
}
let next_index = (current_index + 1) % items.len();
if let Some(&next_entity_id) = items.get(next_index) {
if let Some(next_entity) = Entity::from_raw_u32(next_entity_id) {
if let Ok(mut rotation_state) = item_query.get_mut(next_entity) {
rotation_state.should_be_visible = true;
}
}
}
rotation_timer.current_indices.insert(position, next_index);
}
}
}