Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 26 additions & 24 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
[package]
name = "screeps-api"
# Ensure html_root_url in src/lib.rs is updated for each version.
version = "0.6.0"
authors = ["David Ross <daboross@daboross.net>"]
version = "0.6.0"

categories = ["api-bindings"]
documentation = "https://docs.rs/screeps-api/"
edition = "2018"
include = [
"Cargo.toml",
"LICENSE",
"README.md",
"src/**/*",
"tests/**/*",
"examples/**/*",
"protocol-docs/**/*"
"Cargo.toml",
"LICENSE",
"README.md",
"src/**/*",
"tests/**/*",
"examples/**/*",
"protocol-docs/**/*",
]
keywords = ["screeps"]
license = "MIT"
Expand All @@ -27,49 +27,51 @@ description = "Fully typed and tested wrapper over the Screeps Game's HTTP API"
all-features = true

[badges]
travis-ci = { repository = "daboross/rust-screeps-api", branch = "master" }
appveyor = { service = "github", repository = "daboross/rust-screeps-api", branch = "master" }
appveyor = {service = "github", repository = "daboross/rust-screeps-api", branch = "master"}
travis-ci = {repository = "daboross/rust-screeps-api", branch = "master"}

[dependencies]
# Logging
log = "0.4"
# Parsing
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_ignored = "0.1"
serde-tuple-vec-map = "1.0"
arrayvec = "0.5"
serde = {version = "1.0", features = ["derive"]}
serde-tuple-vec-map = "1.0"
serde_ignored = "0.1"
serde_json = "1.0"
time = "0.1"
# HTTP
bytes = "1.0"
futures = "0.3"
hyper = {version = "0.14", features = ["client", "http1", "stream"]}
url = "2.0"
hyper = { version = "0.14", features = ["client", "http1", "stream"] }
bytes = "1.0"
# Sync HTTP wrapper
tokio = { version = "1.0", optional = true }
hyper-tls = { version = "0.5", optional = true }
hyper-tls = {version = "0.5", optional = true}
tokio = {version = "1.0", optional = true}
# Websockets
num = {version = "0.3", default-features = false}
rand = "0.8"
num = { version = "0.3", default-features = false }

[features]
sync = ["tokio", "hyper-tls", "tokio/rt-multi-thread"]
protocol-docs = []
default = ["sync"]
protocol-docs = []
sync = ["tokio", "hyper-tls", "tokio/rt-multi-thread"]
# enables tests which modify game state (temporarily, but still)
destructive-tests = []

[dev-dependencies]
# error
anyhow = "1.0"
# .env parsing
dotenv = "0.15"
# logging in examples
fern = "0.6"
chrono = "0.4"
fern = "0.6"
# cli options in examples
clap = "2"
# socket connections in ws-debug example
futures01 = { package = "futures", version = "0.1" }
tokio01 = { package = "tokio", version = "0.1" }
futures01 = {package = "futures", version = "0.1"}
tokio01 = {package = "tokio", version = "0.1"}
websocket = "0.26"
# pretty printing in ws-debug.
serde_json = "1"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ Unofficial API documentation for:

- Logging in
- Getting all leaderboard information
- Getting room terrain
- Getting world size
- Getting room terrain (batch mode supported)
- Checking room status
- Getting room overview info
- Getting logged in user's info
Expand Down
2 changes: 1 addition & 1 deletion examples/me.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn main() {
"not set"
},
my_info.cpu,
my_info.gcl_points,
my_info.gcl_points.unwrap_or_default(),
my_info.credits
);
println!("{:#?}", my_info);
Expand Down
2 changes: 1 addition & 1 deletion src/data/room_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{error, fmt, ops};
use serde::{Deserialize, Serialize};

/// A structure representing a room name.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
pub struct RoomName {
/// Inner x coordinate representation.
///
Expand Down
6 changes: 4 additions & 2 deletions src/endpoints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ mod register;
mod room_overview;
mod room_status;
mod room_terrain;
mod rooms_terrain;
mod set_memory_segment;
mod shards;
mod world_size_info;
mod world_start_room;

// don't compile this endpoint template file with regular output, but still compile w/ tests to test for correctness.
Expand All @@ -21,8 +23,8 @@ pub mod template;

pub use self::{
leaderboard::*, login::*, map_stats::*, my_info::*, recent_pvp::*, register::*,
room_overview::*, room_status::*, room_terrain::*, set_memory_segment::*, shards::*,
world_start_room::*,
room_overview::*, room_status::*, room_terrain::*, rooms_terrain::*, set_memory_segment::*,
shards::*, world_size_info::*, world_start_room::*,
};

pub(crate) use self::memory_segment::*;
4 changes: 2 additions & 2 deletions src/endpoints/my_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub(crate) struct Response {
email: Option<String>,
password: bool,
cpu: i32,
gcl: u64,
gcl: Option<u64>,
money: f64,
// These can be added if needed
// lastChargeTime: Option<String>,
Expand Down Expand Up @@ -52,7 +52,7 @@ pub struct MyInfo {
/// This user's current CPU allowance.
pub cpu: i32,
/// This user's current total count of GCL points (perform calculation to find actual gcl level).
pub gcl_points: u64,
pub gcl_points: Option<u64>,
/// This user's current credit balance.
pub credits: f64,
/// Information on per-shard allocation. Unavailable on non-sharded servers.
Expand Down
56 changes: 31 additions & 25 deletions src/endpoints/room_terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) struct Response {
}

#[derive(serde::Deserialize, Clone, Hash, Debug)]
struct InnerResponse {
pub(crate) struct InnerResponse {
// this is returned as part of the data, but what the heck is it even for?
/// A cache key maybe?
_id: String,
Expand Down Expand Up @@ -50,7 +50,7 @@ pub type TerrainRow = ArrayVec<[TerrainType; 50]>;
pub type TerrainGrid = ArrayVec<[TerrainRow; 50]>;

/// Structure describing the terrain of a room
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct RoomTerrain {
/// The name of the room
pub room_name: data::RoomName,
Expand All @@ -66,34 +66,14 @@ pub struct RoomTerrain {
_non_exhaustive: (),
}

impl EndpointResult for RoomTerrain {
type RequestResult = Response;
type ErrorResult = data::ApiError;

fn from_raw(raw: Response) -> Result<RoomTerrain> {
let Response {
ok,
terrain: terrain_array,
} = raw;

if ok != 1 {
return Err(ApiError::NotOk(ok).into());
}

let terrain_data = match terrain_array {
Some(v) => match v.into_iter().next() {
Some(v) => v,
None => return Err(ApiError::MissingField("terrain.0").into()),
},
None => return Err(ApiError::MissingField("terrain").into()),
};

impl InnerResponse {
pub(crate) fn into_terrain(self) -> Result<RoomTerrain> {
let InnerResponse {
response_type,
room: room_string,
_id: response_id,
terrain,
} = terrain_data;
} = self;

if terrain.len() != 2500 {
return Err(ApiError::MalformedResponse(format!(
Expand Down Expand Up @@ -144,6 +124,32 @@ impl EndpointResult for RoomTerrain {
}
}

impl EndpointResult for RoomTerrain {
type RequestResult = Response;
type ErrorResult = data::ApiError;

fn from_raw(raw: Response) -> Result<RoomTerrain> {
let Response {
ok,
terrain: terrain_array,
} = raw;

if ok != 1 {
return Err(ApiError::NotOk(ok).into());
}

let terrain_data = match terrain_array {
Some(v) => match v.into_iter().next() {
Some(v) => v,
None => return Err(ApiError::MissingField("terrain.0").into()),
},
None => return Err(ApiError::MissingField("terrain").into()),
};

terrain_data.into_terrain()
}
}

#[cfg(test)]
mod tests {
use super::RoomTerrain;
Expand Down
54 changes: 54 additions & 0 deletions src/endpoints/rooms_terrain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! Interpreting room terrain results.

use serde::Serialize;

use crate::{
data,
error::{ApiError, Result},
EndpointResult, InnerResponse, RoomTerrain,
};

#[derive(Serialize, Clone, Debug)]
pub(crate) struct RoomsTerrainRequest<'a> {
pub rooms: &'a [&'a str],
}

#[derive(serde::Deserialize, Clone, Hash, Debug)]
pub(crate) struct RoomsTerrainResponse {
ok: i32,
rooms: Option<Vec<InnerResponse>>,
}

/// Structure describing the terrain of a list of rooms
#[derive(Clone, Debug)]
pub struct RoomsTerrain {
/// Rooms
pub rooms: Vec<RoomTerrain>,
}

impl EndpointResult for RoomsTerrain {
type RequestResult = RoomsTerrainResponse;
type ErrorResult = data::ApiError;

fn from_raw(raw: RoomsTerrainResponse) -> Result<RoomsTerrain> {
let RoomsTerrainResponse {
ok,
rooms: terrain_array,
} = raw;

if ok != 1 {
return Err(ApiError::NotOk(ok).into());
}
let terrain_array = match terrain_array {
Some(v) => v,
None => return Err(ApiError::MissingField("rooms").into()),
};

Ok(RoomsTerrain {
rooms: terrain_array
.into_iter()
.map(|i| i.into_terrain().unwrap_or_default())
.collect(),
})
}
}
25 changes: 23 additions & 2 deletions src/endpoints/shards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ pub(crate) struct Response {
}

#[derive(Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
struct ShardResponse {
users: u32,
name: String,
tick: f64,
rooms: u32,
cpu_limit: i32,
last_ticks: Vec<u32>,
}

/// Structure describing information about a single game shard.
Expand All @@ -33,6 +36,10 @@ pub struct ShardInfo {
pub user_count: u32,
/// The average millisecond tick this shard has for some past period of time (TODO: more detail).
pub tick_avg_milliseconds: f64,
/// Cpu limit
pub cpu_limit: i32,
/// Last ticks
pub last_ticks: Vec<u32>,
/// Phantom data in order to allow adding any additional fields in the future.
_non_exhaustive: (),
}
Expand All @@ -43,6 +50,12 @@ impl AsRef<str> for ShardInfo {
}
}

impl Into<String> for ShardInfo {
fn into(self) -> String {
self.name.into()
}
}

impl EndpointResult for Vec<ShardInfo> {
type RequestResult = Response;
type ErrorResult = data::ApiError;
Expand All @@ -62,12 +75,16 @@ impl EndpointResult for Vec<ShardInfo> {
name,
tick,
rooms,
cpu_limit,
last_ticks,
} = response;
ShardInfo {
name: name,
room_count: rooms,
user_count: users,
tick_avg_milliseconds: tick,
cpu_limit,
last_ticks,
_non_exhaustive: (),
}
})
Expand Down Expand Up @@ -95,13 +112,17 @@ mod tests {
"users": 1246,
"rooms": 28858,
"name": "shard0",
"tick": 5726.411601456489
"tick": 5726.411601456489,
"cpuLimit": 20,
"lastTicks":[1111, 2222, 3333],
},
{
"users": 584,
"rooms": 4816,
"name": "shard1",
"tick": 2153.4476171877614
"tick": 2153.4476171877614,
"cpuLimit": 20,
"lastTicks":[],
}
],
"ok": 1
Expand Down
Loading