diff --git a/js_src/test.js b/js_src/test.js new file mode 100644 index 0000000..06811dc --- /dev/null +++ b/js_src/test.js @@ -0,0 +1,36 @@ +export function do_classify_find(room_name) { + let room = Game.rooms[room_name]; + + if (room) { + let res = room.find(FIND_STRUCTURES); + + let all_structures = []; + let repairable = []; + let container = []; + let link = []; + + res.forEach((structure) => { + all_structures.push(structure); + + //let can_own = switch(structure.structureType) { + // case: + //} + + if (structure.hits < structure.hitsMax && structure.structureType != STRUCTURE_WALL) { + repairable.push(structure) + } + + if (structure.structureType == STRUCTURE_LINK) { + link.push(structure) + } + + if (structure.structureType == STRUCTURE_CONTAINER) { + container.push(structure); + } + }) + + return [all_structures, repairable, container, link]; + } else { + return []; + } + } \ No newline at end of file diff --git a/js_tools/deploy.js b/js_tools/deploy.js index 7cc672e..e213d1d 100644 --- a/js_tools/deploy.js +++ b/js_tools/deploy.js @@ -83,6 +83,7 @@ function run_wasm_pack(extra_options) { async function run_rollup(use_terser) { const bundle = await rollup({ input: 'js_src/main.js', + plugins: [ commonjs(), nodeResolve(), diff --git a/src/room/cache/experimental_structures.rs b/src/room/cache/experimental_structures.rs new file mode 100644 index 0000000..d77d6a4 --- /dev/null +++ b/src/room/cache/experimental_structures.rs @@ -0,0 +1,35 @@ +use std::str::FromStr; + +use js_sys::{Array, JsString}; +use screeps::{RoomName, StructureContainer, StructureLink, StructureObject}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(module = "test")] +extern "C" { + // Returns an array 4 long: + // 0 - All Structures + // 1 - Repairable + // 2 - Container + // 3 - Link + fn do_classify_find(room_name: JsString) -> Array; +} + +pub fn do_find(room_name: &RoomName) -> (Vec, Vec, Vec, Vec) { + let res = do_classify_find(JsString::from_str(room_name.to_string().as_str()).unwrap()); + + if res.length() == 0 { + return (vec![], vec![], vec![], vec![]); + } + + let all_js: Array = res.get(0).into(); + let repairable_js: Array = res.get(1).into(); + let container: Array = res.get(2).into(); + let links: Array = res.get(3).into(); + + let all_rs: Vec = all_js.iter().map(|structure| structure.into()).collect(); + let repairable_rs: Vec = repairable_js.iter().map(|structure| structure.into()).collect(); + let container_rs: Vec = container.iter().map(|structure| structure.into()).collect(); + let links_rs: Vec = links.iter().map(|structure| structure.into()).collect(); + + (all_rs, repairable_rs, container_rs, links_rs) +} \ No newline at end of file diff --git a/src/room/cache/mod.rs b/src/room/cache/mod.rs index 7e5539f..0f7fa1e 100644 --- a/src/room/cache/mod.rs +++ b/src/room/cache/mod.rs @@ -19,6 +19,7 @@ pub mod resources; pub mod traffic; pub mod terminals; pub mod stats; +pub mod experimental_structures; pub struct RoomCache { pub rooms: HashMap, @@ -132,6 +133,9 @@ impl CachedRoom { let pre_structures = game::cpu::get_used(); let mut structures = RoomStructureCache::new_from_room(room, &mut resources, memory, &mut room_heap); let total_structures = game::cpu::get_used() - pre_structures; + let pre_new_structures = game::cpu::get_used(); + //structures.new_refresh_structure_cache(&mut resources, memory); + let total_new_structures = game::cpu::get_used() - pre_new_structures; let pre_creeps = game::cpu::get_used(); let creeps = CreepCache::new_from_room(room, memory, &structures, owning_room); let total_creeps = game::cpu::get_used() - pre_creeps; @@ -197,6 +201,10 @@ impl CachedRoom { cached.stats.cpu_cache = game::cpu::get_used() - pre_cache_cpu; + if cached.room.my() { + info!("[CACHE] Room {} took {} for old {} for new.", room.name(), total_structures, total_new_structures); + } + //if cached.room.my() { // info!(" Creation for room {} took {:.2} CPU.", room.name(), game::cpu::get_used() - pre_cache_cpu); // info!(" Structures took {:.2} - Creeps took {:.2} - Resources took {:.2}", total_structures, total_creeps, total_resource); diff --git a/src/room/cache/structures.rs b/src/room/cache/structures.rs index 613d5c4..c1d9517 100644 --- a/src/room/cache/structures.rs +++ b/src/room/cache/structures.rs @@ -19,7 +19,7 @@ use crate::{ #[cfg(feature = "season1")] use screeps::ScoreCollector; -use super::resources::RoomResourceCache; +use super::{experimental_structures::do_find, resources::RoomResourceCache}; #[derive(Debug, Clone)] pub struct CachedRoomContainers { @@ -171,7 +171,7 @@ impl RoomStructureCache { cache.controller = Some(controller); } - cache.refresh_structure_cache(resource_cache, memory); + cache.new_refresh_structure_cache(resource_cache, memory); #[cfg(feature = "season1")] { @@ -464,7 +464,7 @@ impl RoomStructureCache { } if let Some(repairable) = structure.as_repairable() { - if repairable.hits() < repairable.hits_max() { + if repairable.hits() < repairable.hits_max() && structure.structure_type() != StructureType::Wall { self.needs_repair.push(structure.clone()); } } @@ -523,6 +523,126 @@ impl RoomStructureCache { //} } + pub fn new_refresh_structure_cache( + &mut self, + resource_cache: &mut RoomResourceCache, + memory: &mut ScreepsMemory, + ) { + let room_memory = memory.rooms.get_mut(&self.room.name()); + + /* + let mut can_structures_be_placed = true; + if let Some(controller) = self.room.controller() { + if !controller.my() { + can_structures_be_placed = false; + } + } else { + can_structures_be_placed = false; + }*/ + + let mut check_ownable = false; + if let Some(room_memory) = room_memory { + if room_memory.rcl < room_memory.max_rcl { + check_ownable = true; + } + } + + let mut has_containers = false; + let mut has_links = false; + + let pre_structure = game::cpu::get_used(); + + let (all_structures, repairables, containers, links) = do_find(&self.room.name()); + + self.needs_repair = repairables; + for container in containers { + self.containers.insert(container.id(), container); + } + for link in links { + self.links.insert(link.id(), link); + } + + // TODO: + // Roads decay every 1k ticks, and containers every 500 (100 in remotes), so we can probably cut down what we are iterating + for structure in all_structures { + let ty = structure.structure_type(); + let entry = self + .structures_at_pos + .entry(structure.pos().xy()) + .or_default(); + if !entry.contains(&ty) { + entry.push(ty); + } + + //if self.skip_check(can_structures_be_placed, &structure) { + // continue; + //} + + // Dont to the is_active check UNLESS we downgraded. + // Its very expensive from what I have heard. + // This information has been reported by: Gadjung + if check_ownable && !structure.is_active() { + self.inactive_structures.push(structure); + + info!("Inactive structure found: {:?}", false); + + continue; + } + + // TODO: Improve this code... + if let Some(ownable) = structure.as_owned() { + if !ownable.my() && ty != StructureType::InvaderCore { + continue; + } + } + + self.classify_structure( + resource_cache, + structure, + &mut has_links, + &mut has_containers, + ); + } + + let structure_used = game::cpu::get_used() - pre_structure; + + let pre_container = game::cpu::get_used(); + if has_containers { + self.process_containers(resource_cache); + } + let container_used = game::cpu::get_used() - pre_container; + + let pre_link = game::cpu::get_used(); + if has_links { + self.process_links(resource_cache); + } + let link_used = game::cpu::get_used() - pre_link; + + let pre_csite = game::cpu::get_used(); + let mut csites = Vec::new(); + for csite in self.room.find(find::CONSTRUCTION_SITES, None) { + let entry = self.structures_at_pos.entry(csite.pos().xy()).or_default(); + if !entry.contains(&csite.structure_type()) { + entry.push(csite.structure_type()); + } + + csites.push(csite) + } + self.construction_sites = csites; + let csite_used = game::cpu::get_used() - pre_csite; + + let pre_ruin = game::cpu::get_used(); + let ruins = self.room.find(find::RUINS, None).into_iter(); + for ruin in ruins { + self.ruins.insert(ruin.id(), ruin); + } + let ruin_used = game::cpu::get_used() - pre_ruin; + + //if self.room.my() { + // info!(" Structures used: {:.2} - Containers: {:.2} - Links: {:.2} - Csites: {:.2} - Ruins: {:.2}", structure_used, container_used, link_used, csite_used, ruin_used); + //} + } + pub fn process_links(&mut self, resource_cache: &mut RoomResourceCache) { //if self.classified_links.is_some() { // return &self.classified_links.as_ref().unwrap(); diff --git a/src/room/spawning/creep_sizing.rs b/src/room/spawning/creep_sizing.rs index e562516..3767576 100644 --- a/src/room/spawning/creep_sizing.rs +++ b/src/room/spawning/creep_sizing.rs @@ -97,23 +97,23 @@ pub fn miner_body(room: &Room, cache: &CachedRoom, is_remote: bool, source_parts #[cfg_attr(feature = "profile", screeps_timing_annotate::timing)] pub fn mineral_miner_body(room: &Room, cache: &CachedRoom) -> Vec { - let mut body = Vec::new(); + let mut body: Vec = Vec::new(); let stamp = vec![Part::Work, Part::Work, Part::Work, Part::Work, Part::Move]; let cost = get_body_cost(&stamp); let max_cost = room.energy_capacity_available(); - let mut current_cost = cost; + let mut current_cost = 0; while current_cost < max_cost { - if current_cost + cost > max_cost { + if current_cost + cost > max_cost || body.len() >= 50 { break; } - body.extend_from_slice(&stamp); + body.extend(&stamp.clone()); current_cost += cost; } - stamp + body } #[cfg_attr(feature = "profile", screeps_timing_annotate::timing)]