Skip to content

Commit

Permalink
Documentation improvements (#473)
Browse files Browse the repository at this point in the history
  • Loading branch information
shanemadden authored Dec 18, 2023
1 parent 022cc29 commit 7c2c735
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 49 deletions.
1 change: 0 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ pub(crate) mod macros {
}
}
impl std::str::FromStr for $ty {
// add a new error type for this - or something
type Err = InvalidConstantString;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Expand Down
16 changes: 0 additions & 16 deletions src/constants/numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,16 +504,8 @@ pub const LAB_UNBOOST_MINERAL: u32 = 15;

/// Exponential growth rate of control points needed per global control level
/// (GCL).
///
/// See [`control_points_for_gcl`] function to calculate for each level
///
/// [`control_points_for_gcl`]: crate::constants::math::control_points_for_gcl
pub const GCL_POW: f64 = 2.4;
/// Base growth rate of control points needed per global control level (GCL).
///
/// See [`control_points_for_gcl`] function to calculate for each level
///
/// [`control_points_for_gcl`]: crate::constants::math::control_points_for_gcl
pub const GCL_MULTIPLY: u32 = 1_000_000;
/// Maximum GCL for players allowed to spawn in a Novice area.
pub const GCL_NOVICE: u32 = 3;
Expand Down Expand Up @@ -740,17 +732,9 @@ pub const SIGN_PLANNED_AREA: &str = "A new Novice or Respawn Area is being plann
// EVENT_* constants in src/objects/impls/room.rs

/// Base growth rate of processed power needed per global power level (GPL).
///
/// See [`power_for_gpl`] function to calculate for each level
///
/// [`power_for_gpl`]: crate::constants::math::power_for_gpl
pub const POWER_LEVEL_MULTIPLY: u32 = 1000;
/// Exponential growth rate of processed power needed per global power level
/// (GPL).
///
/// See [`power_for_gpl`] function to calculate for each level
///
/// [`power_for_gpl`]: crate::constants::math::power_for_gpl
pub const POWER_LEVEL_POW: u32 = 2;
/// Time, in milliseconds, that a power creep must wait to respawn after dying.
pub const POWER_CREEP_SPAWN_COOLDOWN: u32 = 8 * 3600 * 1000;
Expand Down
12 changes: 7 additions & 5 deletions src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,23 @@ pub fn resources() -> JsHashMap<IntershardResourceType, u32> {
Game::resources().into()
}

/// Get an [`JsHashMap<RoomName, Room>`] with the rooms visible for the current
/// Get a [`JsHashMap<RoomName, Room>`] with the rooms visible for the current
/// tick.
///
/// [Screeps documentation](https://docs.screeps.com/api/#Game.rooms)
pub fn rooms() -> JsHashMap<RoomName, Room> {
Game::rooms().into()
}

/// Get an [`JsHashMap<String, StructureSpawn>`] with all of your spawns, which
/// Get a [`JsHashMap<String, StructureSpawn>`] with all of your spawns, which
/// has spawn names as keys.
///
/// [Screeps documentation](https://docs.screeps.com/api/#Game.spawns)
pub fn spawns() -> JsHashMap<String, StructureSpawn> {
Game::spawns().into()
}

/// Get an [`JsHashMap<RawObjectId, StructureObject>`] with all of your owned
/// Get a [`JsHashMap<RawObjectId, StructureObject>`] with all of your owned
/// structures.
///
/// [Screeps documentation](https://docs.screeps.com/api/#Game.spawns)
Expand Down Expand Up @@ -205,8 +205,10 @@ pub fn get_object_by_id_erased(id: &RawObjectId) -> Option<RoomObject> {
Game::get_object_by_id(&js_str)
}

/// Send an email message to yourself with a given message. Set a group
/// interval to only send messages every `group_interval` minutes.
/// Send an email message to yourself with a given message.
///
/// Set a `group_interval` with a limit, in minutes, on how frequently emails
/// are allowed to be sent.
///
/// [Screeps documentation](https://docs.screeps.com/api/#Game.notify)
pub fn notify(message: &str, group_interval: Option<u32>) {
Expand Down
17 changes: 11 additions & 6 deletions src/js_collections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub trait JsCollectionFromValue {
fn from_value(val: JsValue) -> Self;
}

/// Container holding a reference to an [`Object`] in JavaScript as well as
/// expected types for both the keys and values.
pub struct JsHashMap<K, V> {
map: Object,
_phantom: PhantomData<(K, V)>,
Expand Down Expand Up @@ -161,16 +163,19 @@ impl<T> std::iter::FusedIterator for OwnedArrayIter<T> where T: JsCollectionFrom

impl<T> std::iter::ExactSizeIterator for OwnedArrayIter<T> where T: JsCollectionFromValue {}

/// Represents a reference to an Object ID string held on the javascript heap
/// and a type that the ID points to.
/// Represents a reference to an Object ID string in JavaScript memory, typed
/// according to the object type Rust expects for the object after resolving.
///
/// This representation is less useful on the Rust side due to lack of
/// visibility on the underlying string and lack of most trait implementations,
/// and consumes more memory, but is faster to resolve and may be useful with
/// objects you plan to resolve frequently.
/// Use [`ObjectId`] if a value stored in Rust memory is preferred; the
/// JavaScript representation can be harder to work with in Rust code due to
/// lack of visibility on the underlying string and lack of most trait
/// implementations, and consumes more memory, but is faster to resolve and may
/// be useful with objects you plan to resolve frequently.
///
/// This object ID is typed, but not strictly, and can be converted into
/// referring into another type of object with [`JsObjectId::into_type`].
///
/// [`ObjectId`]: crate::local::ObjectId
// Copy, Clone, Debug, PartialEq, Eq, Hash, PartialEq, Eq implemented manually
// below
pub struct JsObjectId<T> {
Expand Down
50 changes: 49 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,52 @@
//! Typed bindings to the Screeps in-game API for WASM Rust AIs.
//! Typed bindings to the Screeps: World in-game API for WASM Rust AIs.
//!
//! # Performance
//!
//! Due to the limited CPU available to the player in Screeps: World, the
//! performance implications of running WebAssembly are good to be aware of.
//!
//! WebAssembly instances have a dedicated linear memory, and data being passed
//! in or out must be copied. Additionally, Rust uses UTF-8 strings while
//! JavaScript uses UTF-16 strings, so any strings being copied must also be
//! converted between encodings.
//!
//! Additionally, compile time for the `WebAssembly.Module` can be considerable,
//! requiring a lot of CPU time on each initial startup tick (and potentially
//! requiring skipped ticks for larger bots). However, global resets are very
//! infrequent in most environments, so the impact of this isn't severe.
//!
//! After compilation, the WebAssembly environment has near-native performance,
//! and no Javascript garbage collection happening for its memory space,
//! allowing for faster execution of some types of workloads. Overall, the
//! advantages and disadvantages of WebAssembly in Screeps are relatively small,
//! especially when compared to the relatively high 0.2ms cost of game actions.
//!
//! # Data Persistence
//!
//! In the Screeps: World JavaScript environment, the `Memory` object is the
//! typical way to store data in a way that persists through the environment
//! resets that happen occasionally, either triggered by deploying a new version
//! of your code or due to natural expiration in the server. It provides a
//! wrapper that automatically deserializes the contents of `RawMemory` via the
//! `JSON.parse()` JavaScript function when accessed for the first time each
//! tick, then gets serialized by `JSON.stringify()` at the end of the tick.
//!
//! Using this untyped `Memory` object (or the reference to a part of it, which
//! can be obtained from the `memory` function on various game objects) from
//! within WebAssembly can be awkward, but is recommended if you need to
//! maintain compatibility with the default `Memory` object.
//!
//! An alternative that you may prefer is to use `RawMemory` instead, fetching
//! the stored data in string format using [`raw_memory::get`] and deserializing
//! within WebAssembly using [`serde`] or another serializion approach, then
//! serializing and using [`raw_memory::set`] to store the data.
//!
//! If you choose the `RawMemory` approach, be aware that some game methods
//! (notably [`StructureSpawn::spawn_creep`] and [`Creep::move_to`]) directly
//! store data in the `Memory` object; replacing the 'special' `Memory` object
//! with one that doesn't attempt to deserialize the contents of `RawMemory` may
//! be advisable if you're using it directly (note that this needs to be done
//! each tick to be effective).
//!
//! # Cargo Features
//!
Expand Down
4 changes: 4 additions & 0 deletions src/local/cost_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ use crate::{

use super::{linear_index_to_xy, xy_to_linear_index, Position, RoomXY, ROOM_AREA};

/// A matrix of pathing costs for a room, stored in Rust memory.
///
/// Use [`CostMatrix`] if a reference to data stored in JavaScript memory is
/// preferred.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct LocalCostMatrix {
Expand Down
19 changes: 9 additions & 10 deletions src/local/object_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,16 @@ mod raw;
pub use errors::*;
pub use raw::*;

/// Represents an Object ID and a type that the ID points to.
/// Represents an Object ID and a type that the ID points to, stored in Rust
/// memory.
///
/// Each object id in screeps is represented by a Mongo GUID, which,
/// while not guaranteed, is unlikely to change. This takes advantage of that by
/// storing a packed representation of 12 bytes.
/// Use [`JsObjectId`] if a reference stored in JavaScript memory is preferred.
///
/// This object ID is typed, but not strictly. It's completely safe to create an
/// ObjectId with an incorrect type, and all operations which use the type will
/// double-check at runtime.
///
/// With that said, using this can provide nice type inference, and should have
/// few disadvantages to the lower-level alternative, [`RawObjectId`].
/// Each object ID in Screeps: World is represented by an ID of up to 24
/// hexidemical characters, which cannot change. This implementation takes
/// advantage of that by storing a packed representation in a `u128`, using 96
/// bits for the ID and 32 bits for tracking the length of the ID string for
/// reconstruction in JS.
///
/// # Conversion
///
Expand All @@ -55,6 +53,7 @@ pub use raw::*;
/// accuracy, these ids will be sorted by object creation time.
///
/// [`BTreeMap`]: std::collections::BTreeMap
/// [`JsObjectId`]: crate::js_collections::JsObjectId
/// [1]: https://docs.mongodb.com/manual/reference/method/ObjectId/
// Copy, Clone, Debug, PartialEq, Eq, Hash, PartialEq, Eq implemented manually below
#[derive(Serialize, Deserialize)]
Expand Down
12 changes: 5 additions & 7 deletions src/local/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@ mod game_methods;
mod pair_utils;
mod world_utils;

/// Represents a position in a particular room in Screeps.
/// Represents a position in a particular room in Screeps, stored in Rust
/// memory.
///
/// **Note:** This is analogous to the `RoomPosition` JavaScript type.
///
/// We've renamed this type to `Position` in `screeps-game-api` to reflect the
/// fact that it's implemented entirely as a local type, and does represent a
/// position located within an entire shard, not only within a single room.
/// Use [`RoomPosition`] if a reference to an object stored in JavaScript memory
/// is preferred.
///
/// This should be a very efficient type to use in most if not all situations.
/// It's represented by a single `u32`, all math operations are implemented in
Expand Down Expand Up @@ -112,7 +110,7 @@ mod world_utils;
///
/// # Method Behavior
///
/// While this corresponds with the JavaScript `RoomPosition` type, it is not
/// While this corresponds with the JavaScript [`RoomPosition`] type, it is not
/// identical. In particular, all "calculation" methods which take in another
/// position are re-implemented in pure Rust code, and some behave slightly
/// different.
Expand Down
15 changes: 15 additions & 0 deletions src/local/room_coordinate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ impl Error for OutOfBoundsError {}

/// Converts a [`RoomXY`] coordinate pair to a linear index appropriate for use
/// with the internal representation of a [`CostMatrix`] or [`LocalCostMatrix`].
///
/// [`CostMatrix`]: crate::objects::CostMatrix
/// [`LocalCostMatrix`]: crate::local::LocalCostMatrix
#[inline]
pub const fn xy_to_linear_index(xy: RoomXY) -> usize {
xy.x.u8() as usize * ROOM_SIZE as usize + xy.y.u8() as usize
Expand All @@ -27,6 +30,9 @@ pub const fn xy_to_linear_index(xy: RoomXY) -> usize {
/// Converts a linear index from the internal representation of a [`CostMatrix`]
/// or [`LocalCostMatrix`] to a [`RoomXY`] coordinate pair for the position the
/// index represents.
///
/// [`CostMatrix`]: crate::objects::CostMatrix
/// [`LocalCostMatrix`]: crate::local::LocalCostMatrix
#[inline]
pub fn linear_index_to_xy(idx: usize) -> RoomXY {
assert!(idx < ROOM_AREA, "Out of bounds index: {idx}");
Expand All @@ -39,6 +45,9 @@ pub fn linear_index_to_xy(idx: usize) -> RoomXY {

/// Converts a [`RoomXY`] coordinate pair to a terrain index appropriate for use
/// with the internal representation of [`RoomTerrain`] or [`LocalRoomTerrain`].
///
/// [`RoomTerrain`]: crate::objects::RoomTerrain
/// [`LocalRoomTerrain`]: crate::local::LocalRoomTerrain
#[inline]
pub const fn xy_to_terrain_index(xy: RoomXY) -> usize {
xy.y.u8() as usize * ROOM_SIZE as usize + xy.x.u8() as usize
Expand All @@ -47,6 +56,9 @@ pub const fn xy_to_terrain_index(xy: RoomXY) -> usize {
/// Converts a terrain index from the internal representation of a
/// [`RoomTerrain`] or [`LocalRoomTerrain`] to a [`RoomXY`] coordinate pair for
/// the position the index represents.
///
/// [`RoomTerrain`]: crate::objects::RoomTerrain
/// [`LocalRoomTerrain`]: crate::local::LocalRoomTerrain
#[inline]
pub fn terrain_index_to_xy(idx: usize) -> RoomXY {
assert!(idx < ROOM_AREA, "Out of bounds index: {idx}");
Expand All @@ -57,6 +69,8 @@ pub fn terrain_index_to_xy(idx: usize) -> RoomXY {
}
}

/// An X or Y coordinate in a room, restricted to the valid range of
/// coordinates.
#[derive(
Debug, Hash, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)]
Expand Down Expand Up @@ -161,6 +175,7 @@ impl fmt::Display for RoomCoordinate {
}
}

/// An X/Y pair representing a given coordinate relative to any room.
#[derive(Debug, Default, Hash, Clone, Copy, PartialEq, Eq)]
pub struct RoomXY {
pub x: RoomCoordinate,
Expand Down
3 changes: 3 additions & 0 deletions src/local/terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub struct LocalRoomTerrain {
bits: Box<[u8; ROOM_AREA]>,
}

/// A matrix representing the terrain of a room, stored in Rust memory.
///
/// Use [`RoomTerrain`] if data stored in JavaScript memory is preferred.
impl LocalRoomTerrain {
/// Gets the terrain at the specified position in this room.
pub fn get(&self, xy: RoomXY) -> Terrain {
Expand Down
6 changes: 5 additions & 1 deletion src/objects/impls/cost_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ use crate::{

#[wasm_bindgen]
extern "C" {
/// An object representing a [`CostMatrix`] held in the javascript heap.
/// A reference to a matrix of pathing costs for a room, stored in
/// JavaScript memory.
///
/// Use [`LocalCostMatrix`] to store and access the same data in Rust
/// memory.
///
/// [Screeps documentation](https://docs.screeps.com/api/#PathFinder-CostMatrix)
#[wasm_bindgen(js_namespace = PathFinder)]
Expand Down
5 changes: 4 additions & 1 deletion src/objects/impls/room_position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crate::{

#[wasm_bindgen]
extern "C" {
/// An object representing a position in a room.
/// An object representing a position in a room, stored in JavaScript
/// memory.
///
/// Use [`Position`] to store and access the same data in Rust memory.
///
/// [Screeps documentation](https://docs.screeps.com/api/#RoomPosition)
pub type RoomPosition;
Expand Down
6 changes: 5 additions & 1 deletion src/objects/impls/room_terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ use crate::{

#[wasm_bindgen]
extern "C" {
/// An object representing a room's terrain held in the javascript heap.
/// A matrix representing the terrain of a room, held in the JavaScript
/// heap.
///
/// Use [`LocalRoomTerrain`] to store and access the same data in Rust
/// memory.
///
/// [Screeps documentation](https://docs.screeps.com/api/#Room-Terrain)
#[wasm_bindgen(js_namespace = Room, js_name = Terrain)]
Expand Down

0 comments on commit 7c2c735

Please sign in to comment.