use std::collections::HashMap; use specs::{ World, WorldExt, DispatcherBuilder, Dispatcher, Join, Entity, RunNow }; use crate::{ controls::Control, worldmessages::WorldMessage, resources::{ Size, Output, Input, NewEntities, Spawn as SpawnPosition, Players, Emigration, Time, RoomFlags }, components::{ Position, Serialise, Player, Inventory, Health, Removed, Clan }, Encyclopedia, roomtemplate::RoomTemplate, savestate::SaveState, Template, playerstate::{PlayerState, RoomPos}, componentwrapper::extract_parameter, Pos, PlayerId, RoomId, aerr, Result, Timestamp, systems::{ Move, RegisterNew, ControlInput, View, Remove, Create, Take, Migrate, Use, Attacking, Trapping, Fight, Heal, UpdateCooldowns, ControlAI, Die, Spawn, Interact, DropLoot, Timeout, Clear, Building, SpawnTrigger, Replace, } }; pub fn default_dispatcher<'a, 'b>() -> Dispatcher<'a, 'b> { DispatcherBuilder::new() .with(Replace, "replace", &[]) .with(Timeout, "timeout", &[]) .with(UpdateCooldowns, "cool_down", &[]) .with(Spawn, "spawn", &[]) .with(ControlInput, "controlinput", &["cool_down"]) .with(ControlAI, "controlai", &["cool_down"]) .with(Take, "take", &["controlinput", "controlai"]) .with(Use, "use", &["controlinput", "controlai"]) .with(Interact, "interact", &["controlinput", "controlai"]) .with(SpawnTrigger, "spawntrigger", &["spawn", "replace"]) .with(Move, "move", &["controlinput", "controlai"]) .with(Trapping, "trapping", &["move"]) .with(Fight, "fight", &["move"]) .with(Heal, "heal", &[]) .with(Attacking, "attacking", &["use", "trapping", "fight", "heal", "interact", "spawntrigger"]) .with(Die, "die", &["attacking"]) .with(DropLoot, "droploot", &["attacking"]) .with(Building, "building", &["attacking"]) .with(Migrate, "migrate", &["move", "attacking", "die"]) .build() } pub struct Room<'a, 'b> { world: World, dispatcher: Option>, pub id: RoomId, places: HashMap } macro_rules! register_insert { ($world: expr, ($($comp: ident),*), ($($res: ident),*)) => { $( $world.register::(); )* $( $world.insert(crate::resources::$res::default()); )* } } impl <'a, 'b>Room<'a, 'b> { pub fn new(id: RoomId, encyclopedia: Encyclopedia, dispatcher: Option>) -> Room<'a, 'b> { let mut world = World::new(); world.insert(NewEntities::new(encyclopedia)); register_insert!( world, (Position, Visible, Controller, Movable, New, Removed, Moved, Player, Inventory, Health, Serialise, RoomExit, Entered, TriggerBox, Trap, Fighter, Healing, ControlCooldown, Autofight, MonsterAI, Home, AttackInbox, Item, Spawner, Clan, Faction, Interactable, Loot, Timer, Equipment, TimeOffset, Flags, Ear, Build, Whitelist, Minable, LootHolder, OnSpawn, Substitute), (Ground, Input, Output, Size, Spawn, Players, Emigration, Time, RoomFlags) ); Room { world, dispatcher, id, places: HashMap::new() } } pub fn load_from_template(&mut self, template: &RoomTemplate) -> Result<()> { let (width, height) = template.size; self.world.fetch_mut::().width = width; self.world.fetch_mut::().height = height; self.world.fetch_mut::().pos = template.spawn; self.world.insert::(template.flags.clone()); for (idx, templates) in template.field.iter().enumerate() { let x = (idx as i64) % width; let y = (idx as i64) / width; for template in templates { self.create_entity(template.clone().unsaved(), Pos{x, y})?; } } for (name, place) in &template.places { self.places.insert(name.clone(), *place); } Ok(()) } pub fn view(&self) -> HashMap { self.world.fetch::().output.clone() } pub fn update(&mut self, timestamp: Timestamp, default_dispatcher: &mut Dispatcher) { self.world.fetch_mut::