diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..ddf12b4e37 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +members = [ + "common", + "client", + "server", +] + +[profile.dev] + +[profile.release] +debug = true diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000000..693699042b --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/client/Cargo.toml b/client/Cargo.toml new file mode 100644 index 0000000000..97b351b96f --- /dev/null +++ b/client/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "veloren-client" +version = "0.1.0" +authors = ["Joshua Barretto "] +edition = "2018" + +[dependencies] +common = { path = "../common" } + +specs = "0.14" diff --git a/client/src/lib.rs b/client/src/lib.rs new file mode 100644 index 0000000000..a6fd9f1afd --- /dev/null +++ b/client/src/lib.rs @@ -0,0 +1,49 @@ +// Standard +use std::time::Duration; + +// Internal +use common::LocalState; + +pub enum ClientErr { + ServerShutdown, + Other(String), +} + +pub struct Input { + // TODO: Use this type to manage client input +} + +pub struct Client { + state: LocalState, + + // TODO: Add "meta" state here +} + +impl Client { + pub fn new() -> Self { + Self { + state: LocalState::new(), + } + } + + /// Execute a single client tick, handle input and update the game state by the given duration + pub fn tick(&mut self, input: Input, dt: Duration) -> Result<(), ClientErr> { + // This tick function is the centre of the Veloren universe. Most client-side things are + // managed from here, and as such it's important that it stays organised. Please consult + // the core developers before making significant changes to this code. Here is the + // approximate order of things. Please update it as this code changes. + // + // 1) Collect input from the frontend, apply input effects to the state of the game + // 2) Go through any events (timer-driven or otherwise) that need handling and apply them + // to the state of the game + // 3) Perform a single LocalState tick (i.e: update the world and entities in the world) + // 4) Go through the terrain update queue and apply all changes to the terrain + // 5) Finish the tick, passing control of the main thread back to the frontend + + // Tick the client's LocalState (step 3) + self.state.tick(dt); + + // Finish the tick, pass control back to the frontend (step 6) + Ok(()) + } +} diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000000..693699042b --- /dev/null +++ b/common/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 0000000000..c2909ab685 --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "common" +version = "0.1.0" +authors = ["Joshua Barretto "] +edition = "2018" + +[dependencies] +specs = "0.14" diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs new file mode 100644 index 0000000000..a3eea3dddd --- /dev/null +++ b/common/src/comp/mod.rs @@ -0,0 +1,6 @@ +// External +use specs::{World as EcsWorld, Builder}; + +pub fn register_local_components(ecs_world: &mut EcsWorld) { + // TODO: Register local components here +} diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 0000000000..86e2b8ce10 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,30 @@ +pub mod comp; + +// Standard +use std::time::Duration; + +// External +use specs::{World as EcsWorld, Builder}; + +// A type used to represent game state stored on both the client and the server. This includes +// things like entity components, terrain data, and global state like weather, time of day, etc. +pub struct LocalState { + ecs_world: EcsWorld +} + +impl LocalState { + pub fn new() -> Self { + let mut ecs_world = EcsWorld::new(); + + comp::register_local_components(&mut ecs_world); + + Self { + ecs_world, + } + } + + // Execute a single tick, simulating the game state by the given duration + pub fn tick(&mut self, dt: Duration) { + println!("Ticked!"); + } +} diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000000..693699042b --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 0000000000..3dbb6308ad --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "server" +version = "0.1.0" +authors = ["Joshua Barretto "] +edition = "2018" + +[dependencies] +common = { path = "../common" } + +specs = "0.14" diff --git a/server/src/lib.rs b/server/src/lib.rs new file mode 100644 index 0000000000..4e44b9f7d6 --- /dev/null +++ b/server/src/lib.rs @@ -0,0 +1,51 @@ +// Standard +use std::time::Duration; + +// Internal +use common::LocalState; + +pub enum ClientErr { + ServerShutdown, + Other(String), +} + +pub struct Input { + // TODO: Use this type to manage server input +} + +pub struct Server { + state: LocalState, + + // TODO: Add "meta" state here +} + +impl Server { + pub fn new() -> Self { + Self { + state: LocalState::new(), + } + } + + /// Execute a single server tick, handle input and update the game state by the given duration + pub fn tick(&mut self, input: Input, dt: Duration) -> Result<(), ClientErr> { + // This tick function is the centre of the Veloren universe. Most server-side things are + // managed from here, and as such it's important that it stays organised. Please consult + // the core developers before making significant changes to this code. Here is the + // approximate order of things. Please update it as this code changes. + // + // 1) Collect input from the frontend, apply input effects to the state of the game + // 2) Go through any events (timer-driven or otherwise) that need handling and apply them + // to the state of the game + // 3) Go through all incoming client network communications, apply them to the game state + // 4) Perform a single LocalState tick (i.e: update the world and entities in the world) + // 5) Go through the terrain update queue and apply all changes to the terrain + // 6) Send relevant state updates to all clients + // 7) Finish the tick, passing control of the main thread back to the frontend + + // Tick the client's LocalState (step 3) + self.state.tick(dt); + + // Finish the tick, pass control back to the frontend (step 6) + Ok(()) + } +}