aboutsummaryrefslogtreecommitdiff
path: root/crates/whirl_server/src/cmd/commands
diff options
context:
space:
mode:
authorFuwn <[email protected]>2021-05-20 17:05:59 +0000
committerFuwn <[email protected]>2021-05-20 17:05:59 +0000
commit9dbc613765de8ab7dfa8e1374cf6661dcfd56bc8 (patch)
tree8cfff6a23bb72db2660e68c63a8cf9d0539a061f /crates/whirl_server/src/cmd/commands
parentfeat(readme): add sqlfluff as a dev dep (diff)
downloadwhirl-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.rs26
-rw-r--r--crates/whirl_server/src/cmd/commands/buddy_list.rs48
-rw-r--r--crates/whirl_server/src/cmd/commands/mod.rs12
-rw-r--r--crates/whirl_server/src/cmd/commands/property/create.rs168
-rw-r--r--crates/whirl_server/src/cmd/commands/property/mod.rs5
-rw-r--r--crates/whirl_server/src/cmd/commands/property/parse.rs14
-rw-r--r--crates/whirl_server/src/cmd/commands/redirect_id.rs42
-rw-r--r--crates/whirl_server/src/cmd/commands/room_id_request.rs18
-rw-r--r--crates/whirl_server/src/cmd/commands/subscribe_distance.rs24
-rw-r--r--crates/whirl_server/src/cmd/commands/subscribe_room.rs30
-rw-r--r--crates/whirl_server/src/cmd/commands/teleport.rs34
-rw-r--r--crates/whirl_server/src/cmd/commands/text.rs67
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(),
+ }
+ }
+}