screeps/objects/impls/structure_spawn.rs
1use js_sys::{Array, JsString, Object};
2use wasm_bindgen::prelude::*;
3
4use crate::{
5 constants::{Direction, ErrorCode, Part},
6 objects::{Creep, OwnedStructure, RoomObject, Store, Structure},
7 prelude::*,
8};
9
10#[wasm_bindgen]
11extern "C" {
12 /// An object representing a [`StructureSpawn`], which creates your creeps.
13 ///
14 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn)
15 #[wasm_bindgen(extends = RoomObject, extends = Structure, extends = OwnedStructure)]
16 #[derive(Clone, Debug)]
17 pub type StructureSpawn;
18
19 /// A shortcut to `Memory.spawns[spawn.name]`.
20 ///
21 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.memory)
22 #[wasm_bindgen(method, getter)]
23 pub fn memory(this: &StructureSpawn) -> JsValue;
24
25 /// Sets a new value to `Memory.spawns[spawn.name]`.
26 ///
27 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.memory)
28 #[wasm_bindgen(method, setter)]
29 pub fn set_memory(this: &StructureSpawn, val: &JsValue);
30
31 /// The spawn's name as a [`String`].
32 ///
33 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.name)
34 #[wasm_bindgen(method, getter)]
35 pub fn name(this: &StructureSpawn) -> String;
36
37 /// The spawn's name as a [`JsString`].
38 ///
39 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.name)
40 #[wasm_bindgen(method, getter = name)]
41 pub fn name_jsstring(this: &StructureSpawn) -> JsString;
42
43 /// Information about the spawning creep, if one is currently being spawned.
44 ///
45 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.spawning)
46 #[wasm_bindgen(method, getter)]
47 pub fn spawning(this: &StructureSpawn) -> Option<Spawning>;
48
49 /// The [`Store`] of the spawn, which contains information about what
50 /// resources it is it holding.
51 ///
52 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.store)
53 #[wasm_bindgen(method, getter)]
54 pub fn store(this: &StructureSpawn) -> Store;
55
56 #[wasm_bindgen(method, js_name = spawnCreep)]
57 fn spawn_creep_internal(
58 this: &StructureSpawn,
59 body: &Array,
60 name: &str,
61 options: Option<&Object>,
62 ) -> i8;
63
64 #[wasm_bindgen(method, js_name = recycleCreep)]
65 fn recycle_creep_internal(this: &StructureSpawn, creep: &Creep) -> i8;
66
67 #[wasm_bindgen(method, js_name = renewCreep)]
68 fn renew_creep_internal(this: &StructureSpawn, creep: &Creep) -> i8;
69}
70
71impl StructureSpawn {
72 /// Create a new creep with the specified body part [`Array`], name
73 /// [`JsString`], and optional spawning options. Note that successfully
74 /// spawning will store data in `Memory.creeps[creep_name]` _regardless
75 /// of whether any memory data was passed in the options object_ and enable
76 /// the default serialization behavior of the `Memory` object, which may
77 /// hamper attempts to directly use `RawMemory`. todo, add note+docs
78 /// about how to replace Memory and/or delete RawMemory._parsed
79 ///
80 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.spawnCreep)
81 pub fn spawn_creep(&self, body: &[Part], name: &str) -> Result<(), ErrorCode> {
82 let body = body.iter().cloned().map(JsValue::from).collect();
83
84 ErrorCode::result_from_i8(Self::spawn_creep_internal(self, &body, name, None))
85 }
86
87 /// Create a new creep with the specified body part [`Array`], name
88 /// [`JsString`], and optional spawning options. Note that successfully
89 /// spawning will store data in `Memory.creeps[creep_name]` _regardless
90 /// of whether any memory data was passed in the options object_ and enable
91 /// the default serialization behavior of the `Memory` object, which may
92 /// hamper attempts to directly use `RawMemory`. todo, add note+docs
93 /// about how to replace Memory and/or delete RawMemory._parsed
94 ///
95 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.spawnCreep)
96 pub fn spawn_creep_with_options(
97 &self,
98 body: &[Part],
99 name: &str,
100 opts: &SpawnOptions,
101 ) -> Result<(), ErrorCode> {
102 let body = body.iter().cloned().map(JsValue::from).collect();
103
104 let js_opts = ObjectExt::unchecked_from_js(JsValue::from(Object::new()));
105
106 if let Some(mem) = &opts.memory {
107 ObjectExt::set(&js_opts, "memory", mem);
108 }
109
110 if let Some(array) = &opts.energy_structures {
111 ObjectExt::set(&js_opts, "energyStructures", array);
112 }
113
114 if opts.dry_run {
115 ObjectExt::set(&js_opts, "dryRun", &true.into());
116 }
117
118 if let Some(array) = &opts.directions {
119 ObjectExt::set(&js_opts, "directions", array);
120 }
121
122 ErrorCode::result_from_i8(Self::spawn_creep_internal(
123 self,
124 &body,
125 name,
126 Some(&js_opts),
127 ))
128 }
129
130 /// Kill a [`Creep`] in melee range, returning 100% of its TTL-adjusted
131 /// resources (5x more than if the creep is killed another way). Can be used
132 /// while spawning.
133 ///
134 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.recycleCreep)
135 pub fn recycle_creep(&self, creep: &Creep) -> Result<(), ErrorCode> {
136 ErrorCode::result_from_i8(self.recycle_creep_internal(creep))
137 }
138
139 /// Renew a [`Creep`] in melee range, removing all boosts adding to its TTL.
140 /// Cannot be used while spawning.
141 ///
142 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.renewCreep)
143 pub fn renew_creep(&self, creep: &Creep) -> Result<(), ErrorCode> {
144 ErrorCode::result_from_i8(self.renew_creep_internal(creep))
145 }
146}
147
148impl JsCollectionFromValue for StructureSpawn {
149 fn from_value(val: JsValue) -> Self {
150 val.unchecked_into()
151 }
152}
153
154impl HasStore for StructureSpawn {
155 fn store(&self) -> Store {
156 Self::store(self)
157 }
158}
159
160impl Attackable for StructureSpawn {}
161impl Dismantleable for StructureSpawn {}
162impl Repairable for StructureSpawn {}
163impl Transferable for StructureSpawn {}
164impl Withdrawable for StructureSpawn {}
165
166#[derive(Default)]
167pub struct SpawnOptions {
168 memory: Option<JsValue>,
169 energy_structures: Option<Array>,
170 dry_run: bool,
171 directions: Option<Array>,
172}
173
174impl SpawnOptions {
175 pub fn new() -> Self {
176 Self::default()
177 }
178
179 pub fn memory(mut self, mem: JsValue) -> Self {
180 self.memory = Some(mem);
181 self
182 }
183
184 /// Structures other than [`StructureSpawn`] and [`StructureExtension`] will
185 /// be ignored.
186 ///
187 /// [`StructureExtension`]: crate::objects::StructureExtension
188 pub fn energy_structures<T: IntoIterator<Item = V>, V: AsRef<Structure>>(
189 mut self,
190 structures: T,
191 ) -> Self {
192 self.energy_structures = Some(
193 structures
194 .into_iter()
195 .map(|structure| JsValue::from(structure.as_ref()))
196 .collect(),
197 );
198 self
199 }
200
201 pub fn dry_run(mut self, dry_run: bool) -> Self {
202 self.dry_run = dry_run;
203 self
204 }
205
206 pub fn directions(mut self, directions: &[Direction]) -> Self {
207 self.directions = Some(
208 directions
209 .iter()
210 .map(|&d| JsValue::from(d as u32))
211 .collect(),
212 );
213 self
214 }
215}
216
217#[wasm_bindgen]
218extern "C" {
219 /// Object with info on what a [`StructureSpawn`] or
220 /// [`StructureInvaderCore`] is currently spawning.
221 ///
222 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn-Spawning)
223 ///
224 /// [`StructureInvaderCore`]: crate::objects::StructureInvaderCore
225 #[wasm_bindgen(js_namespace = StructureSpawn)]
226 pub type Spawning;
227
228 /// Allowed directions for the creep to exit the spawn; can be changed with
229 /// [`Spawning::set_directions`].
230 ///
231 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.directions)
232 #[wasm_bindgen(method, getter)]
233 pub fn directions(this: &Spawning) -> Array;
234
235 /// The name of the spawning creep.
236 ///
237 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.name)
238 #[wasm_bindgen(method, getter)]
239 pub fn name(this: &Spawning) -> JsString;
240
241 /// Total time needed to spawn this creep.
242 ///
243 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.needTime)
244 #[wasm_bindgen(method, getter = needTime)]
245 pub fn need_time(this: &Spawning) -> u32;
246
247 /// Total time remaining to spawn this creep.
248 ///
249 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.remainingTime)
250 #[wasm_bindgen(method, getter = remainingTime)]
251 pub fn remaining_time(this: &Spawning) -> u32;
252
253 /// Get a reference to the [`Structure`] spawning the creep, either a
254 /// [`StructureSpawn`] or a [`StructureInvaderCore`].
255 ///
256 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.spawn)
257 ///
258 /// [`StructureInvaderCore`]: crate::objects::StructureInvaderCore
259 #[wasm_bindgen(method, getter)]
260 pub fn spawn(this: &Spawning) -> Structure;
261
262 #[wasm_bindgen(method, js_name = cancel)]
263 fn cancel_internal(this: &Spawning) -> i8;
264
265 #[wasm_bindgen(method, js_name = setDirections)]
266 fn set_directions_internal(this: &Spawning, directions: &Array) -> i8;
267}
268
269impl Spawning {
270 /// Cancel spawning this creep, without refunding any energy.
271 ///
272 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.cancel)
273 pub fn cancel(&self) -> Result<(), ErrorCode> {
274 ErrorCode::result_from_i8(self.cancel_internal())
275 }
276
277 /// Change allowed directions for the creep to leave the spawn once it's
278 /// ready.
279 ///
280 /// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.Spawning.setDirections)
281 pub fn set_directions(&self, directions: &Array) -> Result<(), ErrorCode> {
282 ErrorCode::result_from_i8(self.set_directions_internal(directions))
283 }
284}