Base data structures
This commit is contained in:
commit
f2b9e6ccb3
|
@ -0,0 +1 @@
|
|||
**/target
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1" }
|
||||
serde_derive = { version = "1" }
|
||||
thiserror = { version = "1" }
|
|
@ -0,0 +1,12 @@
|
|||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
pub mod types;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("Tier out of range {0}")]
|
||||
TierOutOfRange(u8),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum Type {
|
||||
Arkus,
|
||||
Delve,
|
||||
Glaive,
|
||||
Jack,
|
||||
Nano,
|
||||
Wright,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum StatType {
|
||||
Might,
|
||||
Speed,
|
||||
Intellect,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum Cost {
|
||||
Nothing,
|
||||
Constant { stat: StatType, cost: u8 },
|
||||
Variable(StatType),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Tier(u8);
|
||||
|
||||
impl Tier {
|
||||
pub fn new(val: u8) -> Result<Tier, Error> {
|
||||
if val < 1 || val > 6 {
|
||||
Err(Error::TierOutOfRange(val))
|
||||
} else {
|
||||
Ok(Tier(val))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Stat {
|
||||
current: u8,
|
||||
max: u8,
|
||||
edge: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Stats {
|
||||
might: Stat,
|
||||
speed: Stat,
|
||||
intellect: Stat,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SpecialAbility {
|
||||
name: String,
|
||||
cost: Cost,
|
||||
description: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum SkillRank {
|
||||
Inability,
|
||||
Trained,
|
||||
Specialized,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Skill {
|
||||
skill: String,
|
||||
rank: SkillRank,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum Range {
|
||||
Immediate,
|
||||
Short,
|
||||
Long,
|
||||
VeryLong,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Attack {
|
||||
weapon: String,
|
||||
damage: u8,
|
||||
range: Range,
|
||||
ammo: Option<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Defense {
|
||||
armor: String,
|
||||
defense: u8,
|
||||
speed_cost: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct CharacterSheet {
|
||||
name: String,
|
||||
descriptor: String,
|
||||
type_: Type,
|
||||
focus: String,
|
||||
tier: Tier,
|
||||
pools: Stats,
|
||||
effort: u8,
|
||||
cypher_limit: u8,
|
||||
special_abilities: Vec<SpecialAbility>,
|
||||
skills: Vec<Skill>,
|
||||
attacks: Vec<Attack>,
|
||||
defenses: Vec<Defense>,
|
||||
equipment: Vec<String>,
|
||||
cyphers: Vec<Cypher>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Cypher {
|
||||
name: String,
|
||||
level: u8,
|
||||
form: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test_data"))]
|
||||
mod test_data {
|
||||
use super::*;
|
||||
|
||||
fn opal() -> CharacterSheet {
|
||||
CharacterSheet {
|
||||
name: "Opal".to_owned(),
|
||||
descriptor: "Adaptable".to_owned(),
|
||||
type_: Type::Jack,
|
||||
focus: "Speaks with a Silver Tongue".to_owned(),
|
||||
tier: Tier::new(1).unwrap(),
|
||||
pools: Stats {
|
||||
might: Stat {
|
||||
current: 11,
|
||||
max: 11,
|
||||
edge: 0,
|
||||
},
|
||||
speed: Stat {
|
||||
current: 12,
|
||||
max: 12,
|
||||
edge: 0,
|
||||
},
|
||||
intellect: Stat {
|
||||
current: 13,
|
||||
max: 13,
|
||||
edge: 1,
|
||||
},
|
||||
},
|
||||
effort: 1,
|
||||
cypher_limit: 3,
|
||||
special_abilities: vec![
|
||||
SpecialAbility { name: "Versatile".to_owned(),
|
||||
cost: Cost::Nothing,
|
||||
description: "+2 to any pool. It can be reassigned after each ten-hour recovery roll.".to_owned() },
|
||||
SpecialAbility { name: "Flex Skill".to_owned(),
|
||||
cost: Cost::Nothing,
|
||||
description: "at the beginning of each day, choose one skill (other than attack or defense). For the rest of the day, you are trained in that skill.".to_owned() },
|
||||
SpecialAbility{ name: "Face Morph".to_owned(),
|
||||
cost: Cost::Constant { stat: StatType::Intellect, cost: 2 },
|
||||
description: "You alter your features and coloration for one hour.".to_owned() },
|
||||
],
|
||||
skills: vec![
|
||||
Skill{ skill: "Perception".to_owned(), rank: SkillRank::Trained },
|
||||
Skill{ skill: "Resilient".to_owned(), rank: SkillRank::Trained },
|
||||
Skill{ skill: "Social interactions".to_owned(), rank: SkillRank::Trained },
|
||||
Skill{ skill: "Pleasant social interactiosn".to_owned(), rank: SkillRank::Specialized },
|
||||
],
|
||||
attacks: vec![
|
||||
Attack { weapon: "Crank Crossbow".to_owned(), damage: 4, range: Range::Long, ammo: Some(25), },
|
||||
Attack { weapon: "Rapier".to_owned(), damage: 2, range: Range::Immediate, ammo: None, },
|
||||
],
|
||||
defenses: vec![
|
||||
Defense {
|
||||
armor: "Brigandine".to_owned(),
|
||||
defense: 2,
|
||||
speed_cost: 2,
|
||||
}
|
||||
],
|
||||
equipment: vec![
|
||||
"A book for recording favorite words, inspiration stories, and speech anecdotes.".to_owned(),
|
||||
"Explorer's pack".to_owned(),
|
||||
],
|
||||
cyphers: vec![
|
||||
Cypher {
|
||||
name: "Flying Cap".to_owned(),
|
||||
level: 3,
|
||||
form: "Hat".to_owned(),
|
||||
description: "Whatever".to_owned(),
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# Tasks
|
||||
|
||||
- Players
|
||||
- need to be able to see their character sheets
|
||||
- need to be able to edit their character sheets
|
||||
- need to record damage
|
||||
- need to mark abilities as used
|
||||
- need to see active status effects ("flex skill")
|
||||
- need to trigger recovery (regain pool points, reset skills that reset on recovery)
|
||||
- need to mark artifacts as depleted
|
||||
- need to expend cyphers
|
||||
- GM
|
||||
- needs to see all character sheet
|
||||
- needs to send items to players
|
||||
- needs a pool of potential cyphers
|
||||
- Other
|
||||
- all actions must be undoable
|
||||
|
||||
Cypher:
|
||||
- name
|
||||
- level
|
||||
- form
|
||||
- description
|
||||
|
||||
Character Sheet
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "datasphere-server"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
warp = { version = "0.3.1" }
|
|
@ -0,0 +1,46 @@
|
|||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use warp::Filter;
|
||||
|
||||
fn gm_paths() -> impl Filter {
|
||||
let base = warp::path("gm").and(warp::header("authentication"));
|
||||
|
||||
let character_sheet = base
|
||||
.clone()
|
||||
.and(warp::path!("character" / String))
|
||||
.map(|auth: String, name| format!("name: {}", name));
|
||||
let send_item = base
|
||||
.clone()
|
||||
.and(warp::path("send_item"))
|
||||
.map(|auth| format!("send_item"));
|
||||
let send_resource = base
|
||||
.clone()
|
||||
.and(warp::path("send_resource"))
|
||||
.map(|auth| format!("send_resource"));
|
||||
|
||||
character_sheet.or(send_item).or(send_resource)
|
||||
}
|
||||
|
||||
fn player_paths() -> impl Filter {
|
||||
let base = warp::path("player").and(warp::header("authentication"));
|
||||
let character_sheet = base
|
||||
.and(warp::path!("character" / String))
|
||||
.map(|authentication: String, name: String| format!("name: {}", name));
|
||||
|
||||
character_sheet
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
let hi = warp::path!("hello" / String)
|
||||
.and(warp::header("user-agent"))
|
||||
.map(|param: String, agent: String| format!("Saluton! {}, {}", param, agent));
|
||||
let bye = warp::path!("goodbye").map(|| "Goodbye!");
|
||||
|
||||
let server = warp::serve(hi.or(bye));
|
||||
server
|
||||
.run(SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
|
||||
8000,
|
||||
))
|
||||
.await;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
let
|
||||
rust_overlay = import (builtins.fetchTarball "https://github.com/oxalica/rust-overlay/archive/master.tar.gz");
|
||||
pkgs = import <pkgs-21.05> { overlays = [ rust_overlay ]; };
|
||||
unstable = import <unstable> {};
|
||||
rust = pkgs.rust-bin.stable."1.54.0".default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
};
|
||||
|
||||
in pkgs.mkShell {
|
||||
name = "datasphere";
|
||||
|
||||
nativeBuildInputs = [
|
||||
rust
|
||||
unstable.rust-analyzer
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
if [ -e ~/.nixpkgs/shellhook.sh ]; then . ~/.nixpkgs/shellhook.sh; fi
|
||||
'';
|
||||
}
|
Loading…
Reference in New Issue