From caf4830c103ba842602509a14162f60d1d997248 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Sat, 29 Sep 2018 11:25:24 -0400 Subject: [PATCH 1/9] Implement Room.Terrain. Fixes #57 --- screeps-game-api/javascript/utils.js | 9 --------- screeps-game-api/src/constants.rs | 18 +++++------------- screeps-game-api/src/game.rs | 11 ++++------- screeps-game-api/src/objects/impls/mod.rs | 1 + screeps-game-api/src/objects/impls/room.rs | 6 +++++- .../src/objects/impls/room_terrain.rs | 15 +++++++++++++++ screeps-game-api/src/objects/mod.rs | 2 ++ 7 files changed, 32 insertions(+), 30 deletions(-) create mode 100644 screeps-game-api/src/objects/impls/room_terrain.rs diff --git a/screeps-game-api/javascript/utils.js b/screeps-game-api/javascript/utils.js index 695d5cb2..78f59b20 100644 --- a/screeps-game-api/javascript/utils.js +++ b/screeps-game-api/javascript/utils.js @@ -192,15 +192,6 @@ function __resource_type_str_to_num(str) { } } -function __terrain_type_str_to_num(str) { - switch (str) { - case "plain": return 0; - case "wall": return 1; - case "swamp": return 2; - default: throw new Error("unknown terrain type " + str); - } -} - function _hasActiveBodypart(body, type) { for (var i = body.length - 1; i >= 0; i--) { if (body[i].hits <= 0) { diff --git a/screeps-game-api/src/constants.rs b/screeps-game-api/src/constants.rs index f4b8b63b..91e2eacc 100644 --- a/screeps-game-api/src/constants.rs +++ b/screeps-game-api/src/constants.rs @@ -250,6 +250,9 @@ pub enum Terrain { Plain = 0, Wall = 1, Swamp = 2, + SwampWall = 3, + Lava = 4, + // Todo: Implement the other masks when lava becomes a thing } impl TryFrom for Terrain { @@ -267,9 +270,8 @@ impl TryFrom for Terrain { 0 => Terrain::Plain, 1 => Terrain::Wall, 2 => Terrain::Swamp, - // might not need this, but just in case we try - // to decode a game-encoded number and '3' represents swamp + wall - 3 => Terrain::Wall, + 3 => Terrain::SwampWall, + 4 => Terrain::Lava, x => panic!("unknown terrain encoded integer {}", x), }, }; @@ -277,16 +279,6 @@ impl TryFrom for Terrain { } } -impl AsRef for Terrain { - fn as_ref(&self) -> &str { - match *self { - Terrain::Plain => "plain", - Terrain::Wall => "wall", - Terrain::Swamp => "swamp", - } - } -} - /// Internal enum representing each LOOK_* constant. /// /// It's recommended to use the constants in the `look` module instead for type safety. diff --git a/screeps-game-api/src/game.rs b/screeps-game-api/src/game.rs index 44dd7a8b..86f5c19e 100644 --- a/screeps-game-api/src/game.rs +++ b/screeps-game-api/src/game.rs @@ -130,8 +130,8 @@ pub mod map { use std::collections; use { - constants::{find::Exit, Direction, ReturnCode, Terrain}, - objects::{Room, RoomPosition}, + constants::{find::Exit, Direction, ReturnCode}, + objects::{Room, RoomTerrain}, traits::{TryFrom, TryInto}, }; @@ -164,11 +164,8 @@ pub mod map { js_unwrap!(Game.map.getRoomLinearDistance(@{room1}, @{room2}, @{continuous})) } - /// See [http://docs.screeps.com/api/#Game.map.getTerrainAt] - /// - /// [http://docs.screeps.com/api/#Game.map.getTerrainAt]: http://docs.screeps.com/api/#Game.map.getTerrainAt - pub fn get_terrain_at(pos: &RoomPosition) -> Terrain { - js_unwrap!(__terrain_type_str_to_num(Game.map.getTerrainAt(@{pos.as_ref()}))) + pub fn get_room_terrain(room_name: &str) -> RoomTerrain { + js_unwrap!(Game.map.getRoomTerrain(@{room_name})) } /// See [http://docs.screeps.com/api/#Game.map.getWorldSize] diff --git a/screeps-game-api/src/objects/impls/mod.rs b/screeps-game-api/src/objects/impls/mod.rs index ec4bb7ac..8a50bc63 100644 --- a/screeps-game-api/src/objects/impls/mod.rs +++ b/screeps-game-api/src/objects/impls/mod.rs @@ -7,6 +7,7 @@ mod nuke; mod resource; mod room; mod room_position; +mod room_terrain; mod source; mod structure_controller; mod structure_keeper_lair; diff --git a/screeps-game-api/src/objects/impls/room.rs b/screeps-game-api/src/objects/impls/room.rs index b57a3dc1..0b966a96 100644 --- a/screeps-game-api/src/objects/impls/room.rs +++ b/screeps-game-api/src/objects/impls/room.rs @@ -8,7 +8,7 @@ use { }, memory::MemoryReference, objects::{ - HasPosition, Room, RoomPosition, StructureController, StructureStorage, StructureTerminal, + HasPosition, Room, RoomPosition, RoomTerrain, StructureController, StructureStorage, StructureTerminal, }, pathfinder::CostMatrix, positions::LocalRoomName, @@ -106,6 +106,10 @@ impl Room { js_unwrap!{@{self.as_ref()}.get_position_at(@{x}, @{y})} } + pub fn get_terrain(&self) -> RoomTerrain { + js_unwrap!(@{self.as_ref()}.getTerrain()) + } + // pub fn look_at(&self, x: u32, y: u32) -> ! { // unimplemented!() // } diff --git a/screeps-game-api/src/objects/impls/room_terrain.rs b/screeps-game-api/src/objects/impls/room_terrain.rs new file mode 100644 index 00000000..2d74a542 --- /dev/null +++ b/screeps-game-api/src/objects/impls/room_terrain.rs @@ -0,0 +1,15 @@ +use {constants::Terrain, objects::RoomTerrain}; + +impl RoomTerrain { + pub fn constructor(room_name: &str) -> Self { + js_unwrap!{new Room.Terrain(@{room_name})} + } + + pub fn get(&self, x: u32, y: u32) -> Terrain { + js_unwrap!{@{self.as_ref()}.get(@{x}, @{y})} + } + + pub fn get_raw_buffer(&self) -> Vec { + js_unwrap!(@{self.as_ref()}.getRawBuffer()) + } +} diff --git a/screeps-game-api/src/objects/mod.rs b/screeps-game-api/src/objects/mod.rs index 92bc800f..f845258e 100644 --- a/screeps-game-api/src/objects/mod.rs +++ b/screeps-game-api/src/objects/mod.rs @@ -49,6 +49,8 @@ reference_wrappers!( RoomObject, #[reference(instance_of = "RoomPosition")] RoomPosition, + #[reference(instance_of = "Room.Terrain")] + RoomTerrain, #[reference(instance_of = "Source")] Source, #[reference(instance_of = "StructureContainer")] From c84e80c07a7eed128711f7c8f3600ff4813d8e29 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Sat, 29 Sep 2018 12:04:32 -0400 Subject: [PATCH 2/9] Named version of create_construction_site. Fixes #62 --- screeps-game-api/src/objects/impls/room_position.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/screeps-game-api/src/objects/impls/room_position.rs b/screeps-game-api/src/objects/impls/room_position.rs index 016f772d..50521d5d 100644 --- a/screeps-game-api/src/objects/impls/room_position.rs +++ b/screeps-game-api/src/objects/impls/room_position.rs @@ -42,6 +42,13 @@ impl RoomPosition { ) } + pub fn create_named_construction_site(&self, ty: StructureType, name: &str) -> ReturnCode { + js_unwrap!( + @{self.as_ref()}.createConstructionSite(__structure_type_num_to_str(@{ty as i32}), + @{name}) + ) + } + pub fn create_flag(&self, name: &str, main_color: Color, secondary_color: Color) -> ReturnCode { // TODO: determine if ERR_NOT_IN_RANGE is the best choice here (js! { From 8254d50080ab3785567e2d33053587078a1a4029 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Sat, 29 Sep 2018 12:09:03 -0400 Subject: [PATCH 3/9] Implements unboostCreep. Fixes #60 --- screeps-game-api/src/objects/impls/structure_lab.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/screeps-game-api/src/objects/impls/structure_lab.rs b/screeps-game-api/src/objects/impls/structure_lab.rs index d6cdce4a..c2ab2d8b 100644 --- a/screeps-game-api/src/objects/impls/structure_lab.rs +++ b/screeps-game-api/src/objects/impls/structure_lab.rs @@ -27,4 +27,8 @@ impl StructureLab { pub fn run_reaction(&self, lab1: &StructureLab, lab2: &StructureLab) -> ReturnCode { js_unwrap!{@{self.as_ref()}.runReaction(@{lab1.as_ref()}, @{lab2.as_ref()})} } + + pub fn unboost_creep(&self, creep: &Creep) -> ReturnCode { + js_unwrap!(@{self.as_ref()}.unboostCreep(@{creep.as_ref()})) + } } From 30dfbd6840da2e0c648f1d9ef2c9098b8017937c Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Sat, 29 Sep 2018 14:34:31 -0400 Subject: [PATCH 4/9] Implements getEventLog. Fixes #59 --- screeps-game-api/Cargo.toml | 1 + screeps-game-api/src/lib.rs | 1 + screeps-game-api/src/objects/impls/room.rs | 123 +++++++++++++++++++++ 3 files changed, 125 insertions(+) diff --git a/screeps-game-api/Cargo.toml b/screeps-game-api/Cargo.toml index 8acbc729..ff1b28cd 100644 --- a/screeps-game-api/Cargo.toml +++ b/screeps-game-api/Cargo.toml @@ -27,6 +27,7 @@ log = "0.4" num-traits = "0.2" serde = "1" serde_derive = "1" +serde_json = "1" scoped-tls = "0.1" stdweb = "0.4" stdweb-derive = "0.5" diff --git a/screeps-game-api/src/lib.rs b/screeps-game-api/src/lib.rs index 637da0eb..72cc0b77 100644 --- a/screeps-game-api/src/lib.rs +++ b/screeps-game-api/src/lib.rs @@ -28,6 +28,7 @@ extern crate scoped_tls; extern crate serde; #[macro_use] extern crate serde_derive; +extern crate serde_json; #[macro_use] extern crate stdweb; #[macro_use] diff --git a/screeps-game-api/src/objects/impls/room.rs b/screeps-game-api/src/objects/impls/room.rs index 0b966a96..d04cc229 100644 --- a/screeps-game-api/src/objects/impls/room.rs +++ b/screeps-game-api/src/objects/impls/room.rs @@ -1,5 +1,6 @@ use std::{marker::PhantomData, mem, ops::Range}; +use serde_json; use stdweb::Reference; use { @@ -102,6 +103,11 @@ impl Room { } } + pub fn get_event_log(&self) -> Vec { + let raw_event_log: String = js_unwrap!{@{self.as_ref()}.getEventLog(true)}; + serde_json::from_str(&raw_event_log).expect("Malformed Event Log") + } + pub fn get_position_at(&self, x: u32, y: u32) -> Option { js_unwrap!{@{self.as_ref()}.get_position_at(@{x}, @{y})} } @@ -424,3 +430,120 @@ pub enum Path { } js_deserializable!{Path} + +#[derive(Deserialize)] +pub struct Event { + #[serde(flatten)] + pub event: EventType, + #[serde(rename = "objectId")] + pub object_id : String, +} + +#[derive(Deserialize)] +#[serde(tag = "event", content = "data")] +pub enum EventType { + #[serde(rename = "1")] + Attack(AttackEvent), + #[serde(rename = "2")] + ObjectDestroyed(ObjectDestroyedEvent), + #[serde(rename = "3")] + AttackController, + #[serde(rename = "4")] + Build(BuildEvent), + #[serde(rename = "5")] + Harvest(HarvestEvent), + #[serde(rename = "6")] + Heal(HealEvent), + #[serde(rename = "7")] + Repair(RepairEvent), + #[serde(rename = "8")] + ReserveController(ReserveControllerEvent), + #[serde(rename = "9")] + UpgradeController(UpgradeControllerEvent), + #[serde(rename = "10")] + Exit(ExitEvent), +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AttackEvent { + pub target_id: String, + pub damage: u32, + pub attack_type: AttackType, +} + +#[derive(Deserialize)] +#[repr(u32)] +pub enum AttackType { + Melee = 1, + Ranged = 2, + RangedMass = 3, + Dismantle = 4, + HitBack =5, + Nuke =6, +} + +#[derive(Deserialize)] +pub struct ObjectDestroyedEvent { + #[serde(rename = "type")] + pub object_type: String, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BuildEvent { + pub target_id: String, + pub amount: u32, + pub energy_spent: u32, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct HarvestEvent { + pub target_id: String, + pub amount: u32, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct HealEvent { + pub target_id: String, + pub amount: u32, + pub heal_type: HealType, +} + +#[derive(Deserialize)] +#[repr(u32)] +pub enum HealType { + Melee = 1, + Ranged = 2, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RepairEvent { + pub target_id: String, + pub amount: u32, + pub energy_spent: u32, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReserveControllerEvent { + pub amount: u32, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UpgradeControllerEvent { + pub amount: u32, + pub energy_spent: u32 +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExitEvent { + pub room: String, + pub x: u32, + pub y: u32, +} From 6c253137d3d439fae8b1f6a2117272fc2afe7386 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Sat, 29 Sep 2018 14:53:28 -0400 Subject: [PATCH 5/9] Export room events and add derives --- screeps-game-api/src/objects/impls/mod.rs | 6 +++- screeps-game-api/src/objects/impls/room.rs | 37 +++++++++++----------- screeps-game-api/src/objects/mod.rs | 6 +++- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/screeps-game-api/src/objects/impls/mod.rs b/screeps-game-api/src/objects/impls/mod.rs index 8a50bc63..cf2eb111 100644 --- a/screeps-game-api/src/objects/impls/mod.rs +++ b/screeps-game-api/src/objects/impls/mod.rs @@ -25,7 +25,11 @@ mod structure_tower; mod tombstone; pub use self::{ - room::{FindOptions, Path, Step}, + room::{ + AttackEvent, AttackType, BuildEvent, Event, EventType, ExitEvent, FindOptions, + HarvestEvent, HealEvent, HealType, ObjectDestroyedEvent, Path, RepairEvent, + ReserveControllerEvent, Step, UpgradeControllerEvent, + }, structure_controller::{Reservation, Sign}, structure_spawn::SpawnOptions, }; diff --git a/screeps-game-api/src/objects/impls/room.rs b/screeps-game-api/src/objects/impls/room.rs index d04cc229..39d69694 100644 --- a/screeps-game-api/src/objects/impls/room.rs +++ b/screeps-game-api/src/objects/impls/room.rs @@ -9,7 +9,8 @@ use { }, memory::MemoryReference, objects::{ - HasPosition, Room, RoomPosition, RoomTerrain, StructureController, StructureStorage, StructureTerminal, + HasPosition, Room, RoomPosition, RoomTerrain, StructureController, StructureStorage, + StructureTerminal, }, pathfinder::CostMatrix, positions::LocalRoomName, @@ -431,15 +432,15 @@ pub enum Path { js_deserializable!{Path} -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] pub struct Event { #[serde(flatten)] pub event: EventType, #[serde(rename = "objectId")] - pub object_id : String, + pub object_id: String, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(tag = "event", content = "data")] pub enum EventType { #[serde(rename = "1")] @@ -464,7 +465,7 @@ pub enum EventType { Exit(ExitEvent), } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AttackEvent { pub target_id: String, @@ -472,24 +473,24 @@ pub struct AttackEvent { pub attack_type: AttackType, } -#[derive(Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] #[repr(u32)] pub enum AttackType { Melee = 1, Ranged = 2, RangedMass = 3, Dismantle = 4, - HitBack =5, - Nuke =6, + HitBack = 5, + Nuke = 6, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] pub struct ObjectDestroyedEvent { #[serde(rename = "type")] pub object_type: String, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct BuildEvent { pub target_id: String, @@ -497,14 +498,14 @@ pub struct BuildEvent { pub energy_spent: u32, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct HarvestEvent { pub target_id: String, pub amount: u32, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct HealEvent { pub target_id: String, @@ -512,14 +513,14 @@ pub struct HealEvent { pub heal_type: HealType, } -#[derive(Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] #[repr(u32)] pub enum HealType { Melee = 1, Ranged = 2, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RepairEvent { pub target_id: String, @@ -527,20 +528,20 @@ pub struct RepairEvent { pub energy_spent: u32, } -#[derive(Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ReserveControllerEvent { pub amount: u32, } -#[derive(Deserialize)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpgradeControllerEvent { pub amount: u32, - pub energy_spent: u32 + pub energy_spent: u32, } -#[derive(Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExitEvent { pub room: String, diff --git a/screeps-game-api/src/objects/mod.rs b/screeps-game-api/src/objects/mod.rs index f845258e..a503b950 100644 --- a/screeps-game-api/src/objects/mod.rs +++ b/screeps-game-api/src/objects/mod.rs @@ -24,7 +24,11 @@ mod impls; mod structure; pub use self::{ - impls::{FindOptions, Path, Reservation, Sign, SpawnOptions, Step}, + impls::{ + AttackEvent, AttackType, BuildEvent, Event, EventType, ExitEvent, FindOptions, + HarvestEvent, HealEvent, HealType, ObjectDestroyedEvent, Path, RepairEvent, Reservation, + ReserveControllerEvent, Sign, SpawnOptions, Step, UpgradeControllerEvent, + }, structure::Structure, }; From 22a6c0b48e704027390b771f668d12f29be44571 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Fri, 5 Oct 2018 02:28:22 -0400 Subject: [PATCH 6/9] Fixed deserialization of events using integers --- screeps-game-api/src/macros.rs | 55 +++++++ screeps-game-api/src/objects/impls/room.rs | 164 +++++++++++++++++---- 2 files changed, 193 insertions(+), 26 deletions(-) diff --git a/screeps-game-api/src/macros.rs b/screeps-game-api/src/macros.rs index add02a49..5eae6c77 100644 --- a/screeps-game-api/src/macros.rs +++ b/screeps-game-api/src/macros.rs @@ -630,3 +630,58 @@ macro_rules! mem_set { compile_error!(concat!("Unexpected usage of mem_set! usage: ", stringify!($($not_valid)*))) } } + +/// Taken from https://serde.rs/enum-number.html +macro_rules! enum_number { + ($name:ident { $($variant:ident = $value:expr, )* }) => { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + #[repr(u32)] + pub enum $name { + $($variant = $value,)* + } + + impl ::serde::Serialize for $name { + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::Serializer, + { + // Serialize the enum as a u64. + serializer.serialize_u64(*self as u64) + } + } + + impl<'de> ::serde::Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: ::serde::Deserializer<'de>, + { + struct Visitor; + + impl<'de> ::serde::de::Visitor<'de> for Visitor { + type Value = $name; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("positive integer") + } + + fn visit_u64(self, value: u64) -> Result<$name, E> + where + E: ::serde::de::Error, + { + // Rust does not come with a simple way of converting a + // number to an enum, so use a big `match`. + match value { + $( $value => Ok($name::$variant), )* + _ => Err(E::custom( + format!("unknown {} value: {}", + stringify!($name), value))), + } + } + } + + // Deserialize the enum from a u64. + deserializer.deserialize_u64(Visitor) + } + } + } +} diff --git a/screeps-game-api/src/objects/impls/room.rs b/screeps-game-api/src/objects/impls/room.rs index 39d69694..b31bb372 100644 --- a/screeps-game-api/src/objects/impls/room.rs +++ b/screeps-game-api/src/objects/impls/room.rs @@ -1,5 +1,6 @@ -use std::{marker::PhantomData, mem, ops::Range}; +use std::{fmt, marker::PhantomData, mem, ops::Range}; +use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor}; use serde_json; use stdweb::Reference; @@ -105,8 +106,11 @@ impl Room { } pub fn get_event_log(&self) -> Vec { - let raw_event_log: String = js_unwrap!{@{self.as_ref()}.getEventLog(true)}; - serde_json::from_str(&raw_event_log).expect("Malformed Event Log") + serde_json::from_str(&self.get_event_log_raw()).expect("Malformed Event Log") + } + + pub fn get_event_log_raw(&self) -> String { + js_unwrap!{@{self.as_ref()}.getEventLog(true)} } pub fn get_position_at(&self, x: u32, y: u32) -> Option { @@ -432,36 +436,148 @@ pub enum Path { js_deserializable!{Path} -#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Event { - #[serde(flatten)] pub event: EventType, - #[serde(rename = "objectId")] pub object_id: String, } -#[derive(Clone, Debug, PartialEq, Eq, Deserialize)] -#[serde(tag = "event", content = "data")] +impl<'de> Deserialize<'de> for Event { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(field_identifier, rename_all = "camelCase")] + enum Field { + Event, + ObjectId, + Data, + }; + + struct EventVisitor; + + impl<'de> Visitor<'de> for EventVisitor { + type Value = Event; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("struct Event") + } + + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + let mut event_type = None; + let mut obj_id = None; + let mut data = None; + let mut data_buffer: Option = None; + + while let Some(key) = map.next_key()? { + match key { + Field::Event => { + if event_type.is_some() { + return Err(de::Error::duplicate_field("event")); + } + event_type = Some(map.next_value()?); + } + Field::ObjectId => { + if obj_id.is_some() { + return Err(de::Error::duplicate_field("objectId")); + } + obj_id = Some(map.next_value()?); + } + Field::Data => { + if data.is_some() { + return Err(de::Error::duplicate_field("data")); + } + + match event_type { + None => data_buffer = map.next_value()?, + Some(event_id) => { + data = match event_id { + 1 => Some(EventType::Attack(map.next_value()?)), + 2 => Some(EventType::ObjectDestroyed(map.next_value()?)), + 3 => Some(EventType::AttackController), + 4 => Some(EventType::Build(map.next_value()?)), + 5 => Some(EventType::Harvest(map.next_value()?)), + 6 => Some(EventType::Heal(map.next_value()?)), + 7 => Some(EventType::Repair(map.next_value()?)), + 8 => Some(EventType::ReserveController(map.next_value()?)), + 9 => Some(EventType::UpgradeController(map.next_value()?)), + 10 => Some(EventType::Exit(map.next_value()?)), + _ => { + return Err(de::Error::custom(format!( + "Event Type Unrecognized: {}", + event_id + ))) + } + }; + } + }; + } + } + } + + if data_buffer.is_some() && event_type.is_some() && data.is_none() { + let val: serde_json::Value = data_buffer.unwrap(); + let err = |_| de::Error::custom("Can't parse Event data."); + if let Some(event_id) = event_type { + data = match event_id { + 1 => Some(EventType::Attack(serde_json::from_value(val).map_err(err)?)), + 2 => Some(EventType::ObjectDestroyed( + serde_json::from_value(val).map_err(err)?, + )), + 3 => Some(EventType::AttackController), + 4 => Some(EventType::Build(serde_json::from_value(val).map_err(err)?)), + 5 => Some(EventType::Harvest( + serde_json::from_value(val).map_err(err)?, + )), + 6 => Some(EventType::Heal(serde_json::from_value(val).map_err(err)?)), + 7 => Some(EventType::Repair(serde_json::from_value(val).map_err(err)?)), + 8 => Some(EventType::ReserveController( + serde_json::from_value(val).map_err(err)?, + )), + 9 => Some(EventType::UpgradeController( + serde_json::from_value(val).map_err(err)?, + )), + 10 => Some(EventType::Exit(serde_json::from_value(val).map_err(err)?)), + _ => { + return Err(de::Error::custom(format!( + "Event Type Unrecognized: {}", + event_id + ))) + } + }; + } + } + + let data = data.ok_or_else(|| de::Error::missing_field("data"))?; + let obj_id = obj_id.ok_or_else(|| de::Error::missing_field("objectId"))?; + + Ok(Event { + event: data, + object_id: obj_id, + }) + } + } + + const FIELDS: &'static [&'static str] = &["event", "objectId", "data"]; + deserializer.deserialize_struct("Event", FIELDS, EventVisitor) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] pub enum EventType { - #[serde(rename = "1")] Attack(AttackEvent), - #[serde(rename = "2")] ObjectDestroyed(ObjectDestroyedEvent), - #[serde(rename = "3")] AttackController, - #[serde(rename = "4")] Build(BuildEvent), - #[serde(rename = "5")] Harvest(HarvestEvent), - #[serde(rename = "6")] Heal(HealEvent), - #[serde(rename = "7")] Repair(RepairEvent), - #[serde(rename = "8")] ReserveController(ReserveControllerEvent), - #[serde(rename = "9")] UpgradeController(UpgradeControllerEvent), - #[serde(rename = "10")] Exit(ExitEvent), } @@ -473,16 +589,14 @@ pub struct AttackEvent { pub attack_type: AttackType, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] -#[repr(u32)] -pub enum AttackType { +enum_number!(AttackType { Melee = 1, Ranged = 2, RangedMass = 3, Dismantle = 4, HitBack = 5, Nuke = 6, -} +}); #[derive(Clone, Debug, PartialEq, Eq, Deserialize)] pub struct ObjectDestroyedEvent { @@ -513,12 +627,10 @@ pub struct HealEvent { pub heal_type: HealType, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] -#[repr(u32)] -pub enum HealType { +enum_number!(HealType { Melee = 1, Ranged = 2, -} +}); #[derive(Clone, Debug, PartialEq, Eq, Deserialize)] #[serde(rename_all = "camelCase")] From c668487204d893539e1d41deaeb37d7b60522ff4 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Fri, 5 Oct 2018 03:21:17 -0400 Subject: [PATCH 7/9] Removes unused terrain codes --- screeps-game-api/src/constants.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/screeps-game-api/src/constants.rs b/screeps-game-api/src/constants.rs index 91e2eacc..2c6493cb 100644 --- a/screeps-game-api/src/constants.rs +++ b/screeps-game-api/src/constants.rs @@ -250,9 +250,6 @@ pub enum Terrain { Plain = 0, Wall = 1, Swamp = 2, - SwampWall = 3, - Lava = 4, - // Todo: Implement the other masks when lava becomes a thing } impl TryFrom for Terrain { @@ -270,8 +267,7 @@ impl TryFrom for Terrain { 0 => Terrain::Plain, 1 => Terrain::Wall, 2 => Terrain::Swamp, - 3 => Terrain::SwampWall, - 4 => Terrain::Lava, + 3 => Terrain::Wall, x => panic!("unknown terrain encoded integer {}", x), }, }; From 5f092234c3adcc5f5c2dada4a5de5300491be0e1 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Fri, 5 Oct 2018 03:22:27 -0400 Subject: [PATCH 8/9] Implements passing vector to get_raw_buffer --- .../src/objects/impls/room_terrain.rs | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/screeps-game-api/src/objects/impls/room_terrain.rs b/screeps-game-api/src/objects/impls/room_terrain.rs index 2d74a542..a51ccc65 100644 --- a/screeps-game-api/src/objects/impls/room_terrain.rs +++ b/screeps-game-api/src/objects/impls/room_terrain.rs @@ -1,15 +1,37 @@ -use {constants::Terrain, objects::RoomTerrain}; +use stdweb::UnsafeTypedArray; + +use {constants::{ReturnCode, Terrain}, objects::RoomTerrain, traits::TryInto}; impl RoomTerrain { pub fn constructor(room_name: &str) -> Self { - js_unwrap!{new Room.Terrain(@{room_name})} + js_unwrap!(new Room.Terrain(@{room_name})) } pub fn get(&self, x: u32, y: u32) -> Terrain { - js_unwrap!{@{self.as_ref()}.get(@{x}, @{y})} + js_unwrap!(@{self.as_ref()}.get(@{x}, @{y})) } pub fn get_raw_buffer(&self) -> Vec { - js_unwrap!(@{self.as_ref()}.getRawBuffer()) + let mut buffer: Vec = vec![0; 2500]; + self.get_raw_buffer_array_ref(&mut buffer).expect("Panic in get_raw_buffer."); + buffer } + + pub fn get_raw_buffer_array_ref<'a>(&self, buffer: &'a mut Vec) -> Result<&'a mut Vec, ReturnCode> { + let is_success: bool; + { + let arr: UnsafeTypedArray = unsafe{ UnsafeTypedArray::new(buffer.as_mut_slice()) }; + + is_success = js!{ + var bytes = @{arr}; + return @{self.as_ref()}.getRawBuffer(bytes) != -10; + }.try_into().unwrap(); + } + if is_success { + Ok(buffer) + } else { + Err(ReturnCode::InvalidArgs) + } + } + } From 4851cb0bbdd12cea6d0f833b8dd1f16abb1c8df7 Mon Sep 17 00:00:00 2001 From: Adam Salvail Date: Fri, 5 Oct 2018 04:25:59 -0400 Subject: [PATCH 9/9] Addresses @daboross comments --- screeps-game-api/src/objects/impls/room.rs | 13 +++++++---- .../src/objects/impls/room_terrain.rs | 22 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/screeps-game-api/src/objects/impls/room.rs b/screeps-game-api/src/objects/impls/room.rs index b31bb372..d069e254 100644 --- a/screeps-game-api/src/objects/impls/room.rs +++ b/screeps-game-api/src/objects/impls/room.rs @@ -519,10 +519,15 @@ impl<'de> Deserialize<'de> for Event { } } - if data_buffer.is_some() && event_type.is_some() && data.is_none() { - let val: serde_json::Value = data_buffer.unwrap(); - let err = |_| de::Error::custom("Can't parse Event data."); - if let Some(event_id) = event_type { + if data.is_none() { + let err = |e| { + de::Error::custom(format_args!( + "can't parse event data due to inner error {}", + e + )) + }; + + if let (Some(val), Some(event_id)) = (data_buffer, event_type) { data = match event_id { 1 => Some(EventType::Attack(serde_json::from_value(val).map_err(err)?)), 2 => Some(EventType::ObjectDestroyed( diff --git a/screeps-game-api/src/objects/impls/room_terrain.rs b/screeps-game-api/src/objects/impls/room_terrain.rs index a51ccc65..7af76f74 100644 --- a/screeps-game-api/src/objects/impls/room_terrain.rs +++ b/screeps-game-api/src/objects/impls/room_terrain.rs @@ -1,6 +1,10 @@ use stdweb::UnsafeTypedArray; -use {constants::{ReturnCode, Terrain}, objects::RoomTerrain, traits::TryInto}; +use { + constants::{ReturnCode, Terrain}, + objects::RoomTerrain, + traits::TryInto, +}; impl RoomTerrain { pub fn constructor(room_name: &str) -> Self { @@ -13,19 +17,24 @@ impl RoomTerrain { pub fn get_raw_buffer(&self) -> Vec { let mut buffer: Vec = vec![0; 2500]; - self.get_raw_buffer_array_ref(&mut buffer).expect("Panic in get_raw_buffer."); + self.get_raw_buffer_to_vec(&mut buffer) + .expect("Panic in get_raw_buffer."); buffer } - pub fn get_raw_buffer_array_ref<'a>(&self, buffer: &'a mut Vec) -> Result<&'a mut Vec, ReturnCode> { + pub fn get_raw_buffer_to_vec<'a>( + &self, + buffer: &'a mut Vec, + ) -> Result<&'a mut Vec, ReturnCode> { let is_success: bool; { - let arr: UnsafeTypedArray = unsafe{ UnsafeTypedArray::new(buffer.as_mut_slice()) }; + let arr: UnsafeTypedArray = unsafe { UnsafeTypedArray::new(buffer.as_mut_slice()) }; is_success = js!{ var bytes = @{arr}; - return @{self.as_ref()}.getRawBuffer(bytes) != -10; - }.try_into().unwrap(); + return @{self.as_ref()}.getRawBuffer(bytes) === bytes; + }.try_into() + .unwrap(); } if is_success { Ok(buffer) @@ -33,5 +42,4 @@ impl RoomTerrain { Err(ReturnCode::InvalidArgs) } } - }