diff options
| author | Fuwn <[email protected]> | 2021-05-20 17:05:59 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-05-20 17:05:59 +0000 |
| commit | 9dbc613765de8ab7dfa8e1374cf6661dcfd56bc8 (patch) | |
| tree | 8cfff6a23bb72db2660e68c63a8cf9d0539a061f /crates/whirl_server/src/cmd/commands | |
| parent | feat(readme): add sqlfluff as a dev dep (diff) | |
| download | whirl-9dbc613765de8ab7dfa8e1374cf6661dcfd56bc8.tar.xz whirl-9dbc613765de8ab7dfa8e1374cf6661dcfd56bc8.zip | |
refactor(global): move crates around, stricter module isolation
Diffstat (limited to 'crates/whirl_server/src/cmd/commands')
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/action.rs | 26 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/buddy_list.rs | 48 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/mod.rs | 12 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/property/create.rs | 168 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/property/mod.rs | 5 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/property/parse.rs | 14 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/redirect_id.rs | 42 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/room_id_request.rs | 18 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/subscribe_distance.rs | 24 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/subscribe_room.rs | 30 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/teleport.rs | 34 | ||||
| -rw-r--r-- | crates/whirl_server/src/cmd/commands/text.rs | 67 |
12 files changed, 488 insertions, 0 deletions
diff --git a/crates/whirl_server/src/cmd/commands/action.rs b/crates/whirl_server/src/cmd/commands/action.rs new file mode 100644 index 0000000..8d1fb0b --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/action.rs @@ -0,0 +1,26 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +// TODO: of2m-ify +// +// Of2m-ifying isn't much of a priority right now as the whole action ordeal +// hasn't been fully dissected yet. Once more is known about the inner working +// of actions, it will be of2m-ified. + +use bytes::{BufMut, BytesMut}; + +pub fn create_action() -> Vec<u8> { + let mut command = BytesMut::new(); + + command.put_slice(&[ + 0x01, 0x11, 0x00, 0x05, 0x54, 0x52, 0x41, 0x44, 0x45, 0x07, 0x26, 0x7c, 0x2b, 0x69, 0x6e, 0x76, + 0x3e, + ]); + + // Convert to vector and insert the length + let mut command_as_vec = command.to_vec(); + command_as_vec.insert(0, command.len() as u8 + 1); + + // Return bytes + command_as_vec +} diff --git a/crates/whirl_server/src/cmd/commands/buddy_list.rs b/crates/whirl_server/src/cmd/commands/buddy_list.rs new file mode 100644 index 0000000..931db52 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/buddy_list.rs @@ -0,0 +1,48 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use std::str::from_utf8; + +use bytes::{BufMut, BytesMut}; + +use crate::cmd::{ + constants::BUDDYLISTNOTIFY, + extendable::{Creatable, Parsable}, +}; + +#[derive(Clone)] +pub struct BuddyList { + pub buddy: String, + pub add: i8, +} +impl Parsable for BuddyList { + fn parse(data: Vec<u8>) -> Self { + Self { + buddy: from_utf8(&data[4..data[0] as usize - 1]) + .unwrap() + .to_string(), + + // Get the last byte + add: data[data[0] as usize - 1] as i8, + } + } +} +impl Creatable for BuddyList { + fn create(self) -> Vec<u8> { + let mut command = BytesMut::new(); + + // Header + command.put_u8(0x01); // ObjId + command.put_i8(BUDDYLISTNOTIFY as i8); // Type + + // Content + command.put_u8(self.buddy.len() as u8); // Buddy (name) length + command.put_slice(self.buddy.as_bytes()); // Buddy (name) + command.put_u8(self.add as u8); // "Is buddy logged on?" (?) + + let mut command_as_vec = command.to_vec(); + command_as_vec.insert(0, command.len() as u8 + 1); + + command_as_vec + } +} diff --git a/crates/whirl_server/src/cmd/commands/mod.rs b/crates/whirl_server/src/cmd/commands/mod.rs new file mode 100644 index 0000000..49758c2 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/mod.rs @@ -0,0 +1,12 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +pub mod action; +pub mod buddy_list; +pub mod property; +pub mod redirect_id; +pub mod room_id_request; +pub mod subscribe_distance; +pub mod subscribe_room; +pub mod teleport; +pub mod text; diff --git a/crates/whirl_server/src/cmd/commands/property/create.rs b/crates/whirl_server/src/cmd/commands/property/create.rs new file mode 100644 index 0000000..40ec2be --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/property/create.rs @@ -0,0 +1,168 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +// TODO: of2m-ify? + +use whirl_config::Config; + +use crate::{ + cmd::constants::{PROPUPD, SESSINIT}, + net::{ + constants::{ + VAR_APPNAME, + VAR_CHANNEL, + VAR_ERROR, + VAR_EXTERNAL_HTTP_SERVER, + VAR_MAIL_DOMAIN, + VAR_PRIV, + VAR_PROTOCOL, + VAR_SCRIPT_SERVER, + VAR_SERIAL, + VAR_SERVERTYPE, + VAR_SMTP_SERVER, + VAR_UPDATETIME, + }, + converter::property_list_to_bytes, + structure::NetworkProperty, + }, +}; + +pub fn create_property_update_as_distributor() -> Vec<u8> { + property_list_to_bytes( + PROPUPD, + 0xFF, + vec![ + NetworkProperty { + prop_id: VAR_MAIL_DOMAIN, + value: "worlds3d.com".to_string(), + }, + NetworkProperty { + prop_id: VAR_SMTP_SERVER, + value: "mail.worlds.net:25".to_string(), + }, + NetworkProperty { + prop_id: VAR_SCRIPT_SERVER, + value: "http://www-dynamic.us.worlds.net/cgi-bin".to_string(), + }, + NetworkProperty { + prop_id: VAR_EXTERNAL_HTTP_SERVER, + value: "http://www-static.us.worlds.net".to_string(), + }, + NetworkProperty { + prop_id: VAR_SERVERTYPE, + value: "1".to_string(), + }, + NetworkProperty { + prop_id: VAR_PROTOCOL, + value: "24".to_string(), + }, + NetworkProperty { + prop_id: VAR_APPNAME, + value: Config::get().whirlsplash.worldsmaster_username, + }, + ], + ) +} + +pub fn create_property_update_as_hub() -> Vec<u8> { + property_list_to_bytes( + PROPUPD, + 0xFF, + vec![ + NetworkProperty { + prop_id: VAR_UPDATETIME, + value: "1000000".to_string(), + }, + NetworkProperty { + prop_id: VAR_MAIL_DOMAIN, + value: "worlds3d.com".to_string(), + }, + NetworkProperty { + prop_id: VAR_SMTP_SERVER, + value: "mail.worlds.net:25".to_string(), + }, + NetworkProperty { + prop_id: VAR_SCRIPT_SERVER, + value: "http://www-dynamic.us.worlds.net/cgi-bin".to_string(), + }, + NetworkProperty { + prop_id: VAR_EXTERNAL_HTTP_SERVER, + value: "http://www-static.us.worlds.net".to_string(), + }, + NetworkProperty { + prop_id: VAR_SERVERTYPE, + value: "3".to_string(), + }, + NetworkProperty { + prop_id: VAR_PROTOCOL, + value: "24".to_string(), + }, + NetworkProperty { + prop_id: VAR_APPNAME, + value: Config::get().whirlsplash.worldsmaster_username, + }, + ], + ) +} + +pub fn create_property_request_as_distributor() -> Vec<u8> { + property_list_to_bytes( + SESSINIT as i32, + 0x01, + vec![ + NetworkProperty { + prop_id: VAR_ERROR, + value: "0".to_string(), + }, + NetworkProperty { + prop_id: VAR_APPNAME, + value: Config::get().whirlsplash.worldsmaster_username, + }, + NetworkProperty { + prop_id: VAR_PROTOCOL, + value: "24".to_string(), + }, + NetworkProperty { + prop_id: VAR_SERVERTYPE, + value: "1".to_string(), + }, + NetworkProperty { + prop_id: VAR_SERIAL, + value: "DWLV000000000000".to_string(), + }, + NetworkProperty { + prop_id: VAR_PRIV, + value: "0".to_string(), + }, + NetworkProperty { + prop_id: VAR_CHANNEL, + value: "dimension-1".to_string(), + }, + ], + ) +} + +pub fn create_property_request_as_hub() -> Vec<u8> { + property_list_to_bytes( + SESSINIT as i32, + 0x01, + vec![ + NetworkProperty { + prop_id: VAR_ERROR, + value: "0".to_string(), + }, + NetworkProperty { + prop_id: VAR_SERVERTYPE, + value: "3".to_string(), + }, + NetworkProperty { + prop_id: VAR_UPDATETIME, + value: "1000000".to_string(), + }, + NetworkProperty { + prop_id: VAR_PROTOCOL, + value: "24".to_string(), + }, + ], + ) +} diff --git a/crates/whirl_server/src/cmd/commands/property/mod.rs b/crates/whirl_server/src/cmd/commands/property/mod.rs new file mode 100644 index 0000000..83b015b --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/property/mod.rs @@ -0,0 +1,5 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +pub mod create; +pub mod parse; diff --git a/crates/whirl_server/src/cmd/commands/property/parse.rs b/crates/whirl_server/src/cmd/commands/property/parse.rs new file mode 100644 index 0000000..415d19f --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/property/parse.rs @@ -0,0 +1,14 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use crate::net::structure::NetworkProperty; + +pub fn find_property_in_property_list( + property_list: &[NetworkProperty], + property: i32, +) -> &NetworkProperty { + property_list + .iter() + .find(|i| i.prop_id == property) + .unwrap() +} diff --git a/crates/whirl_server/src/cmd/commands/redirect_id.rs b/crates/whirl_server/src/cmd/commands/redirect_id.rs new file mode 100644 index 0000000..8f56c86 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/redirect_id.rs @@ -0,0 +1,42 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use bytes::{BufMut, BytesMut}; +use whirl_config::Config; + +use crate::cmd::{constants::REDIRID, extendable::Creatable}; + +#[derive(Debug)] +pub struct RedirectId { + pub room_name: String, + pub room_number: i8, +} +impl Creatable for RedirectId { + fn create(self) -> Vec<u8> { + let mut command = BytesMut::new(); + + // Header + command.put_u8(0x01); // ObjId + command.put_u8(REDIRID as u8); // Type + + // Content + command.put_u8(self.room_name.len() as u8); // Room name length + command.put_slice(self.room_name.as_bytes()); // Room name + // command.put_u8(0x00); // Unimplemented byte (?) + // command.put_u8(room_id); // Room ID + command.put_u16(self.room_number as u16); // Room ID + + // IP + for byte in Config::get().whirlsplash.ip.split('.') { + command.put_u8(byte.parse::<u8>().unwrap()); + } + command.put_u16(Config::get().hub.port as u16); // Port + + // Length + let mut command_as_vec = command.to_vec(); + command_as_vec.insert(0, command.len() as u8 + 1); + + // Return + command_as_vec + } +} diff --git a/crates/whirl_server/src/cmd/commands/room_id_request.rs b/crates/whirl_server/src/cmd/commands/room_id_request.rs new file mode 100644 index 0000000..cf507fa --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/room_id_request.rs @@ -0,0 +1,18 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use std::str::from_utf8; + +use crate::cmd::extendable::Parsable; + +#[derive(Debug)] +pub struct RoomIdRequest { + pub room_name: String, +} +impl Parsable for RoomIdRequest { + fn parse(data: Vec<u8>) -> Self { + Self { + room_name: from_utf8(&data[4..data[0] as usize]).unwrap().to_string(), + } + } +} diff --git a/crates/whirl_server/src/cmd/commands/subscribe_distance.rs b/crates/whirl_server/src/cmd/commands/subscribe_distance.rs new file mode 100644 index 0000000..d5cbcf6 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/subscribe_distance.rs @@ -0,0 +1,24 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use byteorder::{BigEndian, ReadBytesExt}; +use bytes::{Buf, BytesMut}; + +use crate::cmd::extendable::Parsable; + +#[derive(Debug)] +pub struct SubscribeDistance { + pub distance: i16, + pub room_number: i16, +} +impl Parsable for SubscribeDistance { + fn parse(data: Vec<u8>) -> Self { + // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 + let mut data = BytesMut::from(data.as_slice()).reader(); + + Self { + distance: data.read_i16::<BigEndian>().unwrap(), + room_number: data.read_i16::<BigEndian>().unwrap(), + } + } +} diff --git a/crates/whirl_server/src/cmd/commands/subscribe_room.rs b/crates/whirl_server/src/cmd/commands/subscribe_room.rs new file mode 100644 index 0000000..9e7d732 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/subscribe_room.rs @@ -0,0 +1,30 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use byteorder::{BigEndian, ReadBytesExt}; +use bytes::{Buf, BytesMut}; + +use crate::cmd::extendable::Parsable; + +#[derive(Debug)] +pub struct SubscribeRoom { + pub room_number: i8, + pub x: f32, + pub y: f32, + pub z: f32, + pub distance: f32, +} +impl Parsable for SubscribeRoom { + fn parse(data: Vec<u8>) -> Self { + // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 + let mut data = BytesMut::from(data.as_slice()).reader(); + + Self { + room_number: data.read_i16::<BigEndian>().unwrap() as i8, + x: data.read_i16::<BigEndian>().unwrap() as i8 as f32, + y: data.read_i16::<BigEndian>().unwrap() as i8 as f32, + z: data.read_i16::<BigEndian>().unwrap() as i8 as f32, + distance: data.read_i16::<BigEndian>().unwrap() as i8 as f32, // + 100 + } + } +} diff --git a/crates/whirl_server/src/cmd/commands/teleport.rs b/crates/whirl_server/src/cmd/commands/teleport.rs new file mode 100644 index 0000000..ef8f6b2 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/teleport.rs @@ -0,0 +1,34 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use byteorder::{BigEndian, ReadBytesExt}; +use bytes::{Buf, BytesMut}; + +use crate::cmd::extendable::Parsable; + +#[derive(Debug)] +pub struct Teleport { + pub room_id: i8, + pub exit_type: u8, + pub entry_type: u8, + pub x: f32, // i16 + pub y: f32, + pub z: f32, + pub direction: f32, +} +impl Parsable for Teleport { + fn parse(data: Vec<u8>) -> Self { + // https://stackoverflow.com/questions/41034635/how-do-i-convert-between-string-str-vecu8-and-u8 + let mut data = BytesMut::from(data.as_slice()).reader(); + + Self { + room_id: data.read_u16::<BigEndian>().unwrap() as i8, + exit_type: data.read_u8().unwrap(), + entry_type: data.read_u8().unwrap(), + x: data.read_i16::<BigEndian>().unwrap() as f32, + y: data.read_i16::<BigEndian>().unwrap() as f32, + z: data.read_i16::<BigEndian>().unwrap() as f32, + direction: data.read_i16::<BigEndian>().unwrap() as f32, + } + } +} diff --git a/crates/whirl_server/src/cmd/commands/text.rs b/crates/whirl_server/src/cmd/commands/text.rs new file mode 100644 index 0000000..2bf7e17 --- /dev/null +++ b/crates/whirl_server/src/cmd/commands/text.rs @@ -0,0 +1,67 @@ +// Copyleft (ɔ) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +use std::str::from_utf8; + +use bytes::{BufMut, BytesMut}; + +use crate::cmd::{ + constants::TEXT, + extendable::{Creatable, ParsableWithArguments}, +}; + +pub struct Text { + pub sender: String, + pub content: String, +} +impl Creatable for Text { + fn create(self) -> Vec<u8> { + let mut command = BytesMut::new(); + + // Header + command.put_u8(0x01); + command.put_i8(TEXT as i8); + + // Content + // TODO: Find a way to parse ObjIds. + // + // The below byte is suspected to be the sender's short ObjId. + command.put_i8(0x00); + + command.put_u8(self.sender.len() as u8); + command.put_slice(self.sender.as_bytes()); + command.put_u8(self.content.len() as u8); + command.put_slice(self.content.as_bytes()); + + // Convert to vector and insert the length + let mut command_as_vec = command.to_vec(); + command_as_vec.insert(0, command.len() as u8 + 1); + + // Return bytes + command_as_vec + } +} +impl ParsableWithArguments for Text { + /// The first and only element of `args` *should* be the username of the + /// sender. + /// + /// There isn't anything currently stopping someone from passing some other + /// value so that might be annoying at times. + /// + /// Realistically, this method is mostly static so the username will *always* + /// be passed properly unless someone intentionally commits breaking changes + /// on purpose regarding what is passed to to this method where called. + /// + /// It would be neat to have some sort of ability to statically check if the + /// `args` argument contains x number of elements at compile time or + /// something of the sort but the Rust RFC is probably not focused on that. + /// + /// So, right now, trust is in the developers' hands to make sure to pass the + /// right -- number -- of elements to `args`. + fn parse(data: Vec<u8>, args: &[&str]) -> Self { + Self { + sender: args[0].to_string(), + content: from_utf8(&data[6..]).unwrap().to_string(), + } + } +} |