module.exports.loop = function () { try { if (wasm_module) { wasm_module.loop(); } else { // attempt to load the wasm only if there's enough bucket to do a bunch of work this tick if (Game.cpu.bucket < 500) { console.log("we are running out of time, pausing compile!" + JSON.stringify(Game.cpu)); return; }
// delect the module from the cache, so we can reload it if (MODULE_NAMEinrequire.cache) { deleterequire.cache[MODULE_NAME]; } // load the wasm module wasm_module = require(MODULE_NAME); // load the wasm instance! wasm_module.initialize_instance(); // run the setup function, which configures logging wasm_module.setup(); // go ahead and run the loop for its first tick wasm_module.loop(); } } catch (error) { console_error("caught exception:", error); if (error.stack) { console_error("stack trace:", error.stack); } console_error("resetting VM next tick."); wasm_module = null; } }
use std::cell::RefCell; use std::collections::{hash_map::Entry, HashMap};
use log::*; use screeps::{ constants::{ErrorCode, Part, ResourceType}, enums::StructureObject, find, game, local::ObjectId, objects::{Creep, Source, StructureController}, prelude::*, }; use wasm_bindgen::prelude::*;
mod logging;
// add wasm_bindgen to any function you would like to expose for call from js #[wasm_bindgen] pubfnsetup() { logging::setup_logging(logging::Info); }
// this is one way to persist data between ticks within Rust's memory, as opposed to // keeping state in memory on game objects - but will be lost on global resets! thread_local! { static CREEP_TARGETS: RefCell<HashMap<String, CreepTarget>> = RefCell::new(HashMap::new()); }
// this enum will represent a creep's lock on a specific target object, storing a js reference // to the object id so that we can grab a fresh reference to the object each successive tick, // since screeps game objects become 'stale' and shouldn't be used beyond the tick they were fetched #[derive(Clone)] enumCreepTarget { Upgrade(ObjectId<StructureController>), Harvest(ObjectId<Source>), }
// to use a reserved name as a function name, use `js_name`: #[wasm_bindgen(js_name = loop)] pubfngame_loop() { debug!("loop starting! CPU: {}", game::cpu::get_used()); // mutably borrow the creep_targets refcell, which is holding our creep target locks // in the wasm heap CREEP_TARGETS.with(|creep_targets_refcell| { letmut creep_targets = creep_targets_refcell.borrow_mut(); debug!("running creeps"); forcreepin game::creeps().values() { run_creep(&creep, &mut creep_targets); } });
letbody = [Part::Move, Part::Move, Part::Carry, Part::Work]; if spawn.room().unwrap().energy_available() >= body.iter().map(|p| p.cost()).sum() { // create a unique name, spawn. letname_base = game::time(); letname = format!("{}-{}", name_base, additional); // note that this bot has a fatal flaw; spawning a creep // creates Memory.creeps[creep_name] which will build up forever; // these memory entries should be prevented (todo doc link on how) or cleaned up match spawn.spawn_creep(&body, &name) { Ok(()) => additional += 1, Err(e) => warn!("couldn't spawn: {:?}", e), } } }