Skip to content

Commit

Permalink
squash snippets branch with current part progress
Browse files Browse the repository at this point in the history
  • Loading branch information
shanemadden committed Mar 9, 2024
1 parent cfef1c2 commit e09d01c
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 52 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ seasonal-season-5 = []
# enable compatibility with the sim environment for positions
sim = []

snippets = []

# Enable unsafe conversions of return codes with undefined behavior when values
# aren't in the expected range
unsafe-return-conversion = []
9 changes: 9 additions & 0 deletions js/part.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports.bodypart_to_part_num = function(part_str_to_num_map, bodypart) {
return part_str_to_num_map.get(bodypart.type)
}

module.exports.part_nums_to_str_array = function(part_num_to_str_map, body_num_array) {
// this is a Uint8Array and its map can't produce strings as-is,
// spread it first so the map can result in an array with constant strings
return [...body_num_array].map((v) => part_num_to_str_map.get(v));
}
5 changes: 3 additions & 2 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,14 @@ pub mod extra;
pub mod find;
pub mod look;
mod numbers;
mod part;
mod recipes;
pub mod seasonal;
mod small_enums;
mod types;

pub use self::{
extra::*, find::FindConstant, look::LookConstant, numbers::*, recipes::FactoryRecipe,
extra::*, find::FindConstant, look::LookConstant, numbers::*, part::*, recipes::FactoryRecipe,
small_enums::*, types::*,
};

Expand All @@ -95,7 +96,7 @@ pub mod creep {
MAX_CREEP_SIZE, RANGED_HEAL_POWER, REPAIR_COST, REPAIR_POWER, SPAWN_RENEW_RATIO,
UPGRADE_CONTROLLER_POWER,
},
small_enums::Part,
part::Part,
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/constants/numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::types::{ResourceType, StructureType};

// OBSTACLE_OBJECT_TYPES not yet implemented

// BODYPART_COST defined in `small_enums.rs`
// body parts and BODYPART_COST defined in `part.rs`

// WORLD_WIDTH/HEIGHT deprecated, not implemented

Expand Down Expand Up @@ -816,7 +816,7 @@ pub const fn stronghold_rampart_hits(core_level: u32) -> Option<u32> {
pub const STRONGHOLD_DECAY_TICKS: u32 = 75_000;

// POWER_INFO not yet implemented
// BODYPARTS_ALL implemented via Sequence trait in `small_enums.rs`
// BODYPARTS_ALL implemented via Sequence trait in `part.rs`
// RESOURCES_ALL implemented via Sequence trait in `types.rs`
// COLORS_ALL implemented via Sequence trait in `small_enums.rs`
// INTERSHARD_RESOURCES defined in `types.rs`
Expand Down
181 changes: 181 additions & 0 deletions src/constants/part.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
use enum_iterator::Sequence;
use js_sys::{Array, JsString, Map};
use num_derive::FromPrimitive;
use serde_repr::{Deserialize_repr, Serialize_repr};
use wasm_bindgen::prelude::*;

use crate::objects::BodyPart;

/// Translates body part type and `BODYPARTS_ALL` constants
#[wasm_bindgen]
#[derive(
Debug,
PartialEq,
Eq,
Clone,
Copy,
Hash,
FromPrimitive,
Serialize_repr,
Deserialize_repr,
Sequence,
)]
#[repr(u8)]
pub enum Part {
Move = 0,
Work = 1,
Carry = 2,
Attack = 3,
RangedAttack = 4,
Tough = 5,
Heal = 6,
Claim = 7,
}

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = MOVE)]
static MOVE_JS: JsString;
#[wasm_bindgen(js_name = WORK)]
static WORK_JS: JsString;
#[wasm_bindgen(js_name = CARRY)]
static CARRY_JS: JsString;
#[wasm_bindgen(js_name = ATTACK)]
static ATTACK_JS: JsString;
#[wasm_bindgen(js_name = RANGED_ATTACK)]
static RANGED_ATTACK_JS: JsString;
#[wasm_bindgen(js_name = TOUGH)]
static TOUGH_JS: JsString;
#[wasm_bindgen(js_name = HEAL)]
static HEAL_JS: JsString;
#[wasm_bindgen(js_name = CLAIM)]
static CLAIM_JS: JsString;
}

thread_local! {
static PART_NUM_TO_STR_MAP: js_sys::Map = {
js_sys::Map::new()
.set(&JsValue::from(Part::Move as u8), &MOVE_JS)
.set(&JsValue::from(Part::Work as u8), &WORK_JS)
.set(&JsValue::from(Part::Carry as u8), &CARRY_JS)
.set(&JsValue::from(Part::Attack as u8), &ATTACK_JS)
.set(&JsValue::from(Part::RangedAttack as u8), &RANGED_ATTACK_JS)
.set(&JsValue::from(Part::Tough as u8), &TOUGH_JS)
.set(&JsValue::from(Part::Heal as u8), &HEAL_JS)
.set(&JsValue::from(Part::Claim as u8), &CLAIM_JS)
};

static PART_STR_TO_NUM_MAP: js_sys::Map = {
js_sys::Map::new()
.set(&MOVE_JS, &JsValue::from(Part::Move as u8))
.set(&WORK_JS, &JsValue::from(Part::Work as u8))
.set(&CARRY_JS, &JsValue::from(Part::Carry as u8))
.set(&ATTACK_JS, &JsValue::from(Part::Attack as u8))
.set(&RANGED_ATTACK_JS, &JsValue::from(Part::RangedAttack as u8))
.set(&TOUGH_JS, &JsValue::from(Part::Tough as u8))
.set(&HEAL_JS, &JsValue::from(Part::Heal as u8))
.set(&CLAIM_JS, &JsValue::from(Part::Claim as u8))
};
}

#[cfg(feature = "snippets")]
#[wasm_bindgen(module = "/js/part.js")]
extern "C" {
fn bodypart_to_part_num(map: &Map, body_part: &BodyPart) -> Part;
fn part_nums_to_str_array(map: &Map, part_array: &[u8]) -> Array;
}

#[cfg(not(feature = "snippets"))]
fn bodypart_to_part_num(map: &Map, body_part: &BodyPart) -> Part {
use num_traits::FromPrimitive;

let n = map.get(&body_part.part_jsvalue()).as_f64().expect("number") as u8;
Part::from_u8(n).expect("known part")
}

#[cfg(not(feature = "snippets"))]
fn part_nums_to_str_array(map: &Map, part_array: &[u8]) -> Array {
let array = Array::new();
for part_num in part_array {
array.push(&map.get(&JsValue::from(*part_num)));
}
array
}

impl Part {
/// Translates the `BODYPART_COST` constant.
#[inline]
pub const fn cost(self) -> u32 {
match self {
Part::Move => 50,
Part::Work => 100,
Part::Carry => 50,
Part::Attack => 80,
Part::RangedAttack => 150,
Part::Tough => 10,
Part::Heal => 250,
Part::Claim => 600,
}
}

pub(crate) fn slice_to_js_array(parts: &[Self]) -> Array {
PART_NUM_TO_STR_MAP.with(|map| {
// SAFETY: &[Part] contains u8 values because it's repr(u8), safe to transmute
// to &[u8]
part_nums_to_str_array(map, unsafe { std::mem::transmute(parts) })
})
}

pub(crate) fn from_bodypart(body_part: &BodyPart) -> Self {
PART_STR_TO_NUM_MAP.with(|map| bodypart_to_part_num(map, body_part))
}
}

#[cfg(test)]
mod test {
use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;

use super::{part_nums_to_str_array, Part};

thread_local! {
static TEST_PART_NUM_TO_STR_MAP: js_sys::Map = {
js_sys::Map::new()
.set(&JsValue::from(Part::Move as u8), &JsValue::from_str("move"))
.set(&JsValue::from(Part::Work as u8), &JsValue::from_str("work"))
.set(&JsValue::from(Part::Carry as u8), &JsValue::from_str("carry"))
.set(&JsValue::from(Part::Attack as u8), &JsValue::from_str("attack"))
.set(&JsValue::from(Part::RangedAttack as u8), &JsValue::from_str("ranged_attack"))
.set(&JsValue::from(Part::Tough as u8), &JsValue::from_str("tough"))
.set(&JsValue::from(Part::Heal as u8), &JsValue::from_str("heal"))
.set(&JsValue::from(Part::Claim as u8), &JsValue::from_str("claim"))
};

static TEST_PART_STR_TO_NUM_MAP: js_sys::Map = {
js_sys::Map::new()
.set(&JsValue::from_str("move"), &JsValue::from(Part::Move as u8))
.set(&JsValue::from_str("work"), &JsValue::from(Part::Work as u8))
.set(&JsValue::from_str("carry"), &JsValue::from(Part::Carry as u8))
.set(&JsValue::from_str("attack"), &JsValue::from(Part::Attack as u8))
.set(&JsValue::from_str("ranged_attack"), &JsValue::from(Part::RangedAttack as u8))
.set(&JsValue::from_str("tough"), &JsValue::from(Part::Tough as u8))
.set(&JsValue::from_str("heal"), &JsValue::from(Part::Heal as u8))
.set(&JsValue::from_str("claim"), &JsValue::from(Part::Claim as u8))
};
}

#[wasm_bindgen_test]
pub fn parts_to_array() {
let body = [Part::Work, Part::Carry, Part::Move, Part::Move].as_slice();
let array = TEST_PART_NUM_TO_STR_MAP.with(|map| {
// SAFETY: &[Part] contains u8 values because it's repr(u8), safe to transmute
// to &[u8]
part_nums_to_str_array(map, unsafe { std::mem::transmute(body) })
});
assert_eq!(array.length(), 4);
assert_eq!(array.get(0), "work");
assert_eq!(array.get(1), "carry");
assert_eq!(array.get(2), "move");
assert_eq!(array.get(3), "move");
}
}
44 changes: 2 additions & 42 deletions src/constants/small_enums.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
//! Various constants translated as small enums.
use std::{borrow::Cow, fmt};
use std::fmt;

use enum_iterator::Sequence;
use js_sys::JsString;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use serde::{
de::{Error as _, Unexpected},
Deserialize, Serialize,
};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use wasm_bindgen::prelude::*;

use super::{macros::named_enum_serialize_deserialize, InvalidConstantString};
use crate::{
constants::find::{Exit, Find},
prelude::*,
Expand Down Expand Up @@ -417,42 +413,6 @@ impl Terrain {
}
}

/// Translates body part type and `BODYPARTS_ALL` constants
#[wasm_bindgen]
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Sequence)]
pub enum Part {
Move = "move",
Work = "work",
Carry = "carry",
Attack = "attack",
RangedAttack = "ranged_attack",
Tough = "tough",
Heal = "heal",
Claim = "claim",
}

named_enum_serialize_deserialize!(Part);

impl Part {
/// Translates the `BODYPART_COST` constant.
#[inline]
pub const fn cost(self) -> u32 {
match self {
Part::Move => 50,
Part::Work => 100,
Part::Carry => 50,
Part::Attack => 80,
Part::RangedAttack => 150,
Part::Tough => 10,
Part::Heal => 250,
Part::Claim => 600,
// I guess bindgen is adding a `#[non_exhaustive]` onto the enum and forcing us to do
// this:
_ => 0,
}
}
}

/// Translates the `DENSITY_*` constants.
#[wasm_bindgen]
#[derive(
Expand Down
8 changes: 7 additions & 1 deletion src/objects/impls/creep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,8 +679,14 @@ extern "C" {
pub fn boost(this: &BodyPart) -> Option<ResourceType>;

#[wasm_bindgen(method, getter = type)]
pub fn part(this: &BodyPart) -> Part;
pub(crate) fn part_jsvalue(this: &BodyPart) -> JsValue;

#[wasm_bindgen(method, getter)]
pub fn hits(this: &BodyPart) -> u32;
}

impl BodyPart {
pub fn part(&self) -> Part {
Part::from_bodypart(self)
}
}
10 changes: 5 additions & 5 deletions src/objects/impls/structure_spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extern "C" {
#[wasm_bindgen(method, js_name = spawnCreep)]
fn spawn_creep_internal(
this: &StructureSpawn,
body: &Array,
body: Array,
name: &str,
options: Option<&Object>,
) -> i8;
Expand All @@ -79,9 +79,9 @@ impl StructureSpawn {
///
/// [Screeps documentation](https://docs.screeps.com/api/#StructureSpawn.spawnCreep)
pub fn spawn_creep(&self, body: &[Part], name: &str) -> Result<(), ErrorCode> {
let body = body.iter().cloned().map(JsValue::from).collect();
let body_array = Part::slice_to_js_array(body);

ErrorCode::result_from_i8(Self::spawn_creep_internal(self, &body, name, None))
ErrorCode::result_from_i8(Self::spawn_creep_internal(self, body_array, name, None))
}

/// Create a new creep with the specified body part [`Array`], name
Expand All @@ -99,7 +99,7 @@ impl StructureSpawn {
name: &str,
opts: &SpawnOptions,
) -> Result<(), ErrorCode> {
let body = body.iter().cloned().map(JsValue::from).collect();
let body_array = Part::slice_to_js_array(body);

let js_opts = ObjectExt::unchecked_from_js(JsValue::from(Object::new()));

Expand All @@ -121,7 +121,7 @@ impl StructureSpawn {

ErrorCode::result_from_i8(Self::spawn_creep_internal(
self,
&body,
body_array,
name,
Some(&js_opts),
))
Expand Down

0 comments on commit e09d01c

Please sign in to comment.