diff --git a/Cargo.toml b/Cargo.toml index 9988a01e..2fcb1e4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ bedrockrs_shared = { path = "crates/shared" } bedrockrs_proto = { path = "crates/proto", optional = true } bedrockrs_proto_core = { path = "crates/proto_core", optional = true } + +bedrockrs_server = { path = "crates/server", optional = true } + bedrockrs_macros = { path = "crates/macros", optional = true } bedrockrs_addon = { path = "crates/addon", optional = true } @@ -27,10 +30,11 @@ tokio = { version = "1.40", features = ["full"] } nbtx = { git = "https://github.com/bedrock-crustaceans/nbtx" } [features] -full = ["addon", "proto", "world"] +full = ["addons", "world", "proto", "server"] -addon = ["dep:bedrockrs_addon"] +addons = ["dep:bedrockrs_addon"] proto = ["dep:bedrockrs_proto", "dep:bedrockrs_proto_core", "dep:bedrockrs_macros"] +server = ["dep:bedrockrs_server"] world = ["dep:bedrockrs_world", "dep:bedrockrs_paletted_storage"] [[example]] diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml new file mode 100644 index 00000000..8e0bdaea --- /dev/null +++ b/crates/server/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "bedrockrs_server" +version = "0.1.0" +edition = "2021" + +[dependencies] +thiserror = "2.0" + +bedrockrs_core = { path = "../core" } +bedrockrs_shared = { path = "../shared" } +bedrockrs_proto = { path = "../proto" } + +tokio = { version = "1.40", features = ["full", "tracing"] } +shipyard = { version = "0.7", features = ["parallel", "proc", "rayon", "tracing"]} +rayon = "1.10" +vek = "0.17" + +xuid = "1.0" + +[features] +scoreboard = [] +forms = [] +visibility = [] diff --git a/crates/server/src/ecs/components/connected.rs b/crates/server/src/ecs/components/connected.rs new file mode 100644 index 00000000..00440c82 --- /dev/null +++ b/crates/server/src/ecs/components/connected.rs @@ -0,0 +1,8 @@ +use shipyard::Component; +use bedrockrs_proto::connection::shard::arc::ConnectionShared; +use bedrockrs_proto::helper::ProtoHelper; + +#[derive(Component)] +pub struct Connected where ::GamePacketType: Sync { + pub connection: ConnectionShared, +} diff --git a/crates/server/src/ecs/components/damage.rs b/crates/server/src/ecs/components/damage.rs new file mode 100644 index 00000000..42ab4d12 --- /dev/null +++ b/crates/server/src/ecs/components/damage.rs @@ -0,0 +1,6 @@ +use shipyard::Component; + +#[derive(Component)] +pub struct Damage { + pub damage: f32, +} diff --git a/crates/server/src/ecs/components/health.rs b/crates/server/src/ecs/components/health.rs new file mode 100644 index 00000000..d73da8ba --- /dev/null +++ b/crates/server/src/ecs/components/health.rs @@ -0,0 +1,8 @@ +use shipyard::Component; + +#[derive(Component)] +pub struct Health { + pub current: f32, + pub min: f32, + pub max: f32, +} diff --git a/crates/server/src/ecs/components/mod.rs b/crates/server/src/ecs/components/mod.rs new file mode 100644 index 00000000..27172945 --- /dev/null +++ b/crates/server/src/ecs/components/mod.rs @@ -0,0 +1,5 @@ +pub mod connected; +pub mod position; +pub mod velocity; +mod health; +mod damage; diff --git a/crates/server/src/ecs/components/position.rs b/crates/server/src/ecs/components/position.rs new file mode 100644 index 00000000..b761062b --- /dev/null +++ b/crates/server/src/ecs/components/position.rs @@ -0,0 +1,5 @@ +use shipyard::Component; +use vek::Vec3; + +#[derive(Component)] +pub struct Pos(pub Vec3); diff --git a/crates/server/src/ecs/components/velocity.rs b/crates/server/src/ecs/components/velocity.rs new file mode 100644 index 00000000..61303a2d --- /dev/null +++ b/crates/server/src/ecs/components/velocity.rs @@ -0,0 +1,5 @@ +use shipyard::Component; +use vek::Vec3; + +#[derive(Component)] +pub struct Vel(pub Vec3); diff --git a/crates/server/src/ecs/mod.rs b/crates/server/src/ecs/mod.rs new file mode 100644 index 00000000..621600aa --- /dev/null +++ b/crates/server/src/ecs/mod.rs @@ -0,0 +1,2 @@ +pub mod components; +pub mod systems; diff --git a/crates/server/src/ecs/systems/death.rs b/crates/server/src/ecs/systems/death.rs new file mode 100644 index 00000000..d3c211d1 --- /dev/null +++ b/crates/server/src/ecs/systems/death.rs @@ -0,0 +1,5 @@ +use shipyard::World; + +pub fn death() { + +} diff --git a/crates/server/src/ecs/systems/mod.rs b/crates/server/src/ecs/systems/mod.rs new file mode 100644 index 00000000..2ea13551 --- /dev/null +++ b/crates/server/src/ecs/systems/mod.rs @@ -0,0 +1 @@ +pub mod death; diff --git a/crates/server/src/error.rs b/crates/server/src/error.rs new file mode 100644 index 00000000..a5620ed8 --- /dev/null +++ b/crates/server/src/error.rs @@ -0,0 +1,20 @@ +use std::error::Error; +use thiserror::Error; +use bedrockrs_proto::error::ConnectionError; + +pub enum StartError { + +} + +#[derive(Error, Debug)] +pub enum LoginError { + #[error("Connection Error: {0}")] + ConnectionError(#[from] ConnectionError), + #[error("Login aborted, reason: {reason}")] + Abort { reason: String }, + #[error("Wrong protocol version (client: {client}, server: {server:?})")] + WrongProtocolVersion { client: i32, server: Vec }, + #[error("Format Error: {0}")] + FormatError(String), +} + diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs new file mode 100644 index 00000000..2646c136 --- /dev/null +++ b/crates/server/src/lib.rs @@ -0,0 +1,4 @@ +pub mod server; +pub mod login; +pub mod error; +pub mod ecs; diff --git a/crates/server/src/login/handler.rs b/crates/server/src/login/handler.rs new file mode 100644 index 00000000..7fb22c0b --- /dev/null +++ b/crates/server/src/login/handler.rs @@ -0,0 +1,3 @@ +pub trait LoginHandler { + +} diff --git a/crates/server/src/login/mod.rs b/crates/server/src/login/mod.rs new file mode 100644 index 00000000..a0a1cbbf --- /dev/null +++ b/crates/server/src/login/mod.rs @@ -0,0 +1,14 @@ +mod handler; + +use bedrockrs_proto::connection::Connection; +use shipyard::World; +use bedrockrs_proto::connection::shard::arc::{ConnectionShared, shard}; +use bedrockrs_proto::version::v729::helper::ProtoHelperV729; +use crate::error::LoginError; +use crate::login::handler::LoginHandler; + +pub async fn login(connection: Connection, world: &mut World, login_handler: impl LoginHandler) -> Result<(), LoginError> { + let mut shard = shard::(connection); + + todo!() +} \ No newline at end of file diff --git a/crates/server/src/server/builder.rs b/crates/server/src/server/builder.rs new file mode 100644 index 00000000..825a5108 --- /dev/null +++ b/crates/server/src/server/builder.rs @@ -0,0 +1,69 @@ +use crate::server::Server; +use bedrockrs_proto::listener::Listener; +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + +pub struct ServerBuilder { + name: String, + sub_name: String, + listeners_info: Vec, + max_player: u32, +} + +impl ServerBuilder { + pub fn new() -> ServerBuilder { + Self::default() + } + + pub fn name(mut self, name: &str) -> ServerBuilder { + self.name = name.to_owned(); + self + } + + pub fn sub_name(mut self, sub_name: &str) -> ServerBuilder { + self.sub_name = sub_name.to_owned(); + self + } + + pub fn listener(mut self, addr: SocketAddr) -> ServerBuilder { + self.listeners_info.push(addr); + self + } + + pub async fn build(mut self) -> Server { + if self.listeners_info.is_empty() { + self.listeners_info.push(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 0)), 19132)); + } + + let mut listeners = Vec::with_capacity(self.listeners_info.len()); + + for addr in self.listeners_info { + listeners.push(Listener::new_raknet( + self.name.clone(), + self.sub_name.clone(), + String::from("1.21.0"), + self.max_player, + 0, + addr, + false, + ).await.unwrap()) + }; + + Server { + listeners, + name: self.name, + sub_name: self.sub_name, + world: Default::default(), + } + } +} + +impl Default for ServerBuilder { + fn default() -> Self { + Self { + name: "bedrock-server".to_string(), + sub_name: "bedrock-rs".to_string(), + listeners_info: vec![], + max_player: 100, + } + } +} diff --git a/crates/server/src/server/mod.rs b/crates/server/src/server/mod.rs new file mode 100644 index 00000000..dae271e7 --- /dev/null +++ b/crates/server/src/server/mod.rs @@ -0,0 +1,34 @@ +use std::error::Error; +use bedrockrs_proto::listener::Listener; +use shipyard::World; +use crate::error::LoginError; +use crate::login::login; + +pub mod builder; + +pub struct Server { + listeners: Vec, + name: String, + sub_name: String, + pub world: World, +} + +impl Server { + pub async fn start(&mut self) { + for listener in &mut self.listeners { + listener.start().await.unwrap(); + } + + self.world.run_default_workload().unwrap() + } + + pub async fn stop(&mut self) { + for listener in &mut self.listeners { + listener.stop().await.expect("TODO: panic message"); + } + } + + pub async fn accept(&mut self) -> Result<(), LoginError> { + todo!() + } +} diff --git a/examples/proto/server.rs b/examples/proto/server.rs index d128d401..c3447078 100644 --- a/examples/proto/server.rs +++ b/examples/proto/server.rs @@ -46,7 +46,7 @@ async fn main() { "1.0".to_string(), 100, 10, - SocketAddr::V4(SocketAddrV4::from_str("127.0.0.1:19132").unwrap()), + "127.0.0.1:19132".parse().unwrap(), false, ) .await @@ -124,12 +124,12 @@ async fn handle_login(mut conn: Connection) { println!("{:#?}", conn.recv::().await.unwrap()); println!("ResourcePackClientResponse"); - conn.send::(&[GamePackets::DisconnectPlayer(DisconnectPlayerPacket { - reason: DisconnectReason::Unknown, - message: Some(String::from("IDK")), - })]) - .await - .unwrap(); + // conn.send::(&[GamePackets::DisconnectPlayer(DisconnectPlayerPacket { + // reason: DisconnectReason::Unknown, + // message: Some(String::from("IDK")), + // })]) + // .await + // .unwrap(); // let packet1 = StartGamePacket { // target_actor_id: ActorUniqueID(609),