From 162d337769748aab21a087879d7c16246ee60007 Mon Sep 17 00:00:00 2001 From: TriMill Date: Mon, 5 Dec 2022 11:31:45 -0500 Subject: [PATCH] more things --- Cargo.lock | 226 ++++++++++++++++++++++++++++++ Cargo.toml | 1 + plugins/{chat => mcchat}/main.lua | 6 +- src/main.rs | 33 ++++- src/network/client.rs | 4 +- src/network/server.rs | 62 ++++---- src/plugins/init_lua.rs | 70 +++++++++ src/plugins/mod.rs | 79 +++-------- src/plugins/plugin.rs | 2 +- src/protocol/clientbound.rs | 22 ++- src/protocol/data.rs | 1 + src/protocol/serverbound.rs | 11 +- 12 files changed, 407 insertions(+), 110 deletions(-) rename plugins/{chat => mcchat}/main.lua (91%) create mode 100644 src/plugins/init_lua.rs diff --git a/Cargo.lock b/Cargo.lock index e795d96..32b63f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -38,6 +47,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + [[package]] name = "byteorder" version = "1.4.3" @@ -62,6 +77,37 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "crc32fast" version = "1.3.2" @@ -71,6 +117,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cxx" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" version = "1.8.0" @@ -157,6 +247,30 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "io-lifetimes" version = "1.0.3" @@ -194,12 +308,30 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "linux-raw-sys" version = "0.1.3" @@ -262,6 +394,16 @@ dependencies = [ "syn", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -320,6 +462,7 @@ dependencies = [ name = "quectocraft" version = "0.1.0" dependencies = [ + "chrono", "env_logger", "hematite-nbt", "log", @@ -381,6 +524,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "serde" version = "1.0.148" @@ -432,12 +581,29 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", +] + [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "uuid" version = "1.2.2" @@ -450,6 +616,66 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 299883d..197d20f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ mlua = { version = "0.8", features = ["lua54", "macros", "serialize"] } uuid = "1.2" log = "0.4.0" env_logger = "0.10.0" +chrono = "0.4" diff --git a/plugins/chat/main.lua b/plugins/mcchat/main.lua similarity index 91% rename from plugins/chat/main.lua rename to plugins/mcchat/main.lua index 8cd727e..7b4733c 100644 --- a/plugins/chat/main.lua +++ b/plugins/mcchat/main.lua @@ -1,6 +1,6 @@ local plugin = { - id = "chat", - name = "Chat", + id = "mcchat", + name = "MCChat", description = "Provides Minecraft-style chat. Messages sent by one client will be broadcasted to every client.", authors = { "trimill" }, version = "0.1.0", @@ -10,7 +10,7 @@ local logger = nil function plugin.init() logger = server.initLogger(plugin) - logger.info("Loaded chat") + logger.info("MCChat version " .. plugin.version) end function plugin.playerJoin(name) diff --git a/src/main.rs b/src/main.rs index 92a757a..e6ea2ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ -use std::time::{Duration, SystemTime}; +use std::borrow::Cow; +use std::time::Duration; +use std::io::Write; +use chrono::Utc; use env_logger::Env; use log::info; use mlua::Lua; @@ -13,16 +16,34 @@ mod network; pub const VERSION: &'static str = std::env!("CARGO_PKG_VERSION"); fn main() { - env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); + env_logger::Builder::from_env( + Env::default().default_filter_or("info") + ).format(|buf, record| { - info!("quectocraft version {}", VERSION); + let now = Utc::now().format("%Y-%m-%d %H:%M:%S"); + let mut target = Cow::Borrowed(record.target()); + if target.starts_with("quectocraft") { + target = Cow::Owned(record.target().replacen("quectocraft", "qc", 1)); + } + + let color = match record.level() { + log::Level::Error => "\x1b[31m", + log::Level::Warn => "\x1b[33m", + log::Level::Info => "\x1b[32m", + log::Level::Debug => "\x1b[37m", + log::Level::Trace => "\x1b[37m", + }; + + writeln!(buf, "\x1b[90m[\x1b[37m{} {color}{}\x1b[37m {}\x1b[90m]\x1b[0m {}", now, record.level(), target, record.args()) + }).init(); + + + info!("Starting Quectocraft version {}", VERSION); let lua = Lua::new(); let mut plugins = Plugins::new(&lua).expect("Error initializing lua environment"); - std::fs::create_dir_all("plugins").expect("couldn't create the plugins directory"); + std::fs::create_dir_all("plugins").expect("Couldn't create the plugins directory"); plugins.load_plugins(); - - info!("{} plugins loaded", plugins.count()); let mut server = NetworkServer::new("127.0.0.1:25565".to_owned(), plugins); let sleep_dur = Duration::from_millis(5); diff --git a/src/network/client.rs b/src/network/client.rs index 79ce48f..eb7bd0d 100644 --- a/src/network/client.rs +++ b/src/network/client.rs @@ -1,6 +1,6 @@ use std::{net::{TcpStream, Shutdown}, thread, io::Write, sync::mpsc::{Receiver, Sender, TryRecvError}, time::Duration}; -use log::info; +use log::debug; use crate::{protocol::{data::{PacketDecoder}, serverbound::*, clientbound::*, NetworkState}}; @@ -49,7 +49,7 @@ impl NetworkClient { } pub fn close(&mut self) { - info!("closed connection id {}", self.id); + debug!("Closed connection id {}", self.id); let _ = self.stream.shutdown(Shutdown::Both); self.closed = true; } diff --git a/src/network/server.rs b/src/network/server.rs index 88f26dd..2fcb0da 100644 --- a/src/network/server.rs +++ b/src/network/server.rs @@ -1,6 +1,7 @@ use std::{net::TcpListener, thread, sync::mpsc::{Receiver, Sender, channel}, collections::HashSet}; -use log::{info, warn, trace, debug, error}; +use log::{info, warn, debug}; +use serde_json::json; use crate::{protocol::{data::PacketEncoder, serverbound::*, clientbound::*}, plugins::{Plugins, Response}, VERSION}; @@ -15,7 +16,7 @@ pub struct NetworkServer<'lua> { impl <'lua> NetworkServer<'lua> { pub fn new(addr: String, plugins: Plugins<'lua>) -> Self { let (send, recv) = channel(); - info!("initializing plugins"); + info!("Initializing plugins"); plugins.init(); thread::spawn(move || Self::listen(&addr, send)); Self { @@ -26,11 +27,11 @@ impl <'lua> NetworkServer<'lua> { } fn listen(addr: &str, send_clients: Sender) { - info!("listening on {}", addr); + info!("Listening on {}", addr); let listener = TcpListener::bind(addr).unwrap(); for (id, stream) in listener.incoming().enumerate() { let stream = stream.unwrap(); - info!("connection from {} (id {})", stream.peer_addr().unwrap(), id); + debug!("Connection from {} (id {})", stream.peer_addr().unwrap(), id); let stream_2 = stream.try_clone().unwrap(); let (send, recv) = channel(); thread::spawn(|| NetworkClient::listen(stream_2, send)); @@ -97,16 +98,6 @@ impl <'lua> NetworkServer<'lua> { fn handle_plugin_response(&mut self, response: Response) -> std::io::Result<()> { match response { - Response::Log { level, origin, message } => { - match level { - 0 => trace!(target: &origin, "{}", message), - 1 => debug!(target: &origin, "{}", message), - 2 => info!(target: &origin, "{}", message), - 3 => warn!(target: &origin, "{}", message), - 4 => error!(target: &origin, "{}", message), - _ => warn!("unknown log level: {}", level) - } - }, Response::Message { player, message } => { for client in self.clients.iter_mut() { if let Some(p) = &client.player { @@ -124,6 +115,15 @@ impl <'lua> NetworkServer<'lua> { } } }, + Response::Disconnect { player, reason } => { + for client in self.clients.iter_mut() { + if let Some(pl) = &client.player { + if pl.name == player || pl.uuid.to_string() == player { + client.send_packet(ClientBoundPacket::Disconnect(reason.clone()))?; + } + } + } + } } Ok(()) } @@ -131,7 +131,7 @@ impl <'lua> NetworkServer<'lua> { fn handle_packet(&mut self, client: &mut NetworkClient, packet: ServerBoundPacket) -> std::io::Result<()> { match packet { ServerBoundPacket::Ignored(_) => (), - ServerBoundPacket::Unknown(id) => warn!("unknown: {}", id), + ServerBoundPacket::Unknown(id) => warn!("Unknown packet: {}", id), ServerBoundPacket::Handshake(_) => (), ServerBoundPacket::StatusRequest() => client.send_packet(ClientBoundPacket::StatusResponse( @@ -142,17 +142,22 @@ impl <'lua> NetworkServer<'lua> { client.close(); } ServerBoundPacket::LoginStart(login_start) => { - client.player = Some(Player { - name: login_start.name.clone(), - uuid: login_start.uuid.unwrap(), - }); - client.play = true; - client.send_packet(ClientBoundPacket::LoginSuccess(LoginSuccess { - name: login_start.name, - uuid: login_start.uuid.unwrap(), - }))?; - self.plugins.player_join(client.player.as_ref().unwrap()); - self.post_login(client)?; + if self.clients.iter().filter_map(|x| x.player.as_ref()).any(|x| x.uuid == login_start.uuid) { + client.send_packet(ClientBoundPacket::LoginDisconnect(json!({"translate": "multiplayer.disconnect.duplicate_login"})))?; + client.close(); + } else { + client.player = Some(Player { + name: login_start.name.clone(), + uuid: login_start.uuid, + }); + client.play = true; + client.send_packet(ClientBoundPacket::LoginSuccess(LoginSuccess { + name: login_start.name, + uuid: login_start.uuid, + }))?; + self.plugins.player_join(client.player.as_ref().unwrap()); + self.post_login(client)?; + } } ServerBoundPacket::ChatMessage(msg) => { self.plugins.chat_message(client.player.as_ref().unwrap(), &msg.message); @@ -187,11 +192,10 @@ impl <'lua> NetworkServer<'lua> { channel: "minecraft:brand".to_owned(), data: { let mut data = Vec::new(); - data.write_string(32767, &format!("quectocraft {}", VERSION)); + data.write_string(32767, &format!("Quectocraft {}", VERSION)); data } }))?; - client.send_packet(ClientBoundPacket::PlayerAbilities(0x0d, 0.05, 0.1))?; let mut chunk_data: Vec = Vec::new(); for _ in 0..(384 / 16) { // number of non-air blocks @@ -224,6 +228,8 @@ impl <'lua> NetworkServer<'lua> { teleport_id: 0, dismount: false }))?; + // TODO why doesn't this work with quilt? + // client.send_packet(ClientBoundPacket::PlayerAbilities(0x0f, 0.05, 0.1))?; Ok(()) } diff --git a/src/plugins/init_lua.rs b/src/plugins/init_lua.rs new file mode 100644 index 0000000..0a115a2 --- /dev/null +++ b/src/plugins/init_lua.rs @@ -0,0 +1,70 @@ +use log::{info, warn, trace, error, debug}; +use mlua::{Lua, chunk}; + + +pub fn init<'lua>(lua: &'lua Lua) -> Result<(), mlua::Error> { + macro_rules! log_any { + ($level:tt) => { + lua.create_function(|_, args: (String, String)| { + $level!(target: &args.0, "{}", args.1); + Ok(()) + }) + } + } + let log_trace = log_any!(trace)?; + let log_debug = log_any!(debug)?; + let log_info = log_any!(info)?; + let log_warn = log_any!(warn)?; + let log_error = log_any!(error)?; + lua.load(chunk!{ + server = { players = {} } + _qc = { responses = {} } + function server.initLogger(plugin) + local id = "pl::" .. assert(plugin["id"]) + return { + trace = function(msg) $log_trace(id, msg) end, + debug = function(msg) $log_debug(id, msg) end, + info = function(msg) $log_info(id, msg) end, + warn = function(msg) $log_warn(id, msg) end, + error = function(msg) $log_error(id, msg) end, + } + end + + local function to_chat(message, default) + if message == nil then + if default ~= nil then + return default + else + error("message must be a string or table") + end + elseif type(message) == "table" then + return message + elseif type(message) == "string" then + return { text = message } + elseif default == nil then + error("message must be a string or table") + else + error("message must be a string, table, or nil for the default message") + end + end + + function server.sendMessage(player, message) + if type(player) ~= "string" then + error("player must be a string") + end + local message = assert(to_chat(message)) + table.insert(_qc.responses, {type = "message", player = player, message = message}) + end + + function server.broadcast(message) + local message = assert(to_chat(message)) + table.insert(_qc.responses, { type = "broadcast", message = message }) + end + + function server.disconnect(player, reason) + local reason = assert(to_chat(reason, { translate = "multiplayer.disconnect.generic" })) + table.insert(_qc.responses, { type = "disconnect", player = player, reason = reason }) + end + }).exec()?; + Ok(()) +} diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index f092a71..0dad724 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -1,7 +1,7 @@ -use std::{path::Path, fs::{self, read_dir}}; +use std::fs::read_dir; -use log::warn; -use mlua::{Lua, Table, chunk, LuaSerdeExt}; +use log::{warn, info}; +use mlua::{Lua, Table, LuaSerdeExt}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -9,8 +9,21 @@ use crate::network::Player; use self::plugin::Plugin; +mod init_lua; mod plugin; +#[derive(Serialize, Deserialize)] +#[serde(tag="type")] +pub enum Response { + #[serde(rename = "message")] + Message { player: String, message: serde_json::Value }, + #[serde(rename = "broadcast")] + Broadcast { message: serde_json::Value }, + #[serde(rename = "disconnect")] + Disconnect { player: String, reason: serde_json::Value }, +} + + pub struct Plugins<'lua> { lua: &'lua Lua, plugins: Vec> @@ -18,47 +31,7 @@ pub struct Plugins<'lua> { impl <'lua> Plugins<'lua> { pub fn new(lua: &'lua Lua) -> Result { - lua.load(chunk!{ - server = { players = {} } - _qc = { responses = {} } - function server.sendMessage(player, message) - if type(player) ~= "string" then - error("player must be a string") - end - if type(message) == "table" then - table.insert(_qc.responses, {type = "message", player = player, message = message}) - elseif type(message) == "string" then - table.insert(_qc.responses, {type = "message", player = player, message = { text = message}}) - else - error("message must be a string or table") - end - end - function server.broadcast(message) - if type(message) == "table" then - table.insert(_qc.responses, { type = "broadcast", message = message }) - elseif type(message) == "string" then - table.insert(_qc.responses, { type = "broadcast", message = { text = message } }) - else - error("message must be a string or table") - end - end - function server.initLogger(plugin) - local function log_for(level) - return function(message) - table.insert(_qc.responses, { - type = "log", origin = plugin.id, message = message, level = level - }) - end - end - return { - trace = log_for(0), - debug = log_for(1), - info = log_for(2), - warn = log_for(3), - error = log_for(4), - } - end - }).exec()?; + init_lua::init(lua)?; Ok(Self { lua, plugins: Vec::new(), @@ -78,18 +51,15 @@ impl <'lua> Plugins<'lua> { }; let pl = Plugin::load(&path, &self.lua).expect("error loading plugin"); self.plugins.push(pl); + info!("Loaded plugin '{}'", file.file_name().to_string_lossy()); } } - pub fn count(&self) -> usize { - self.plugins.len() - } - pub fn get_responses(&self) -> Vec { match self.get_responses_inner() { Ok(x) => x, Err(e) => { - warn!("error getting responses: {}", e); + warn!("Error getting responses: {}", e); Vec::new() } } @@ -164,14 +134,3 @@ impl <'lua> Plugins<'lua> { } } } - -#[derive(Serialize, Deserialize)] -#[serde(tag="type")] -pub enum Response { - #[serde(rename = "log")] - Log { level: i32, origin: String, message: String }, - #[serde(rename = "message")] - Message { player: String, message: serde_json::Value }, - #[serde(rename = "broadcast")] - Broadcast { message: serde_json::Value }, -} diff --git a/src/plugins/plugin.rs b/src/plugins/plugin.rs index 81779f1..1ab508f 100644 --- a/src/plugins/plugin.rs +++ b/src/plugins/plugin.rs @@ -1,4 +1,4 @@ -use std::{path::{PathBuf, Path}, str::FromStr}; +use std::path::Path; use mlua::{Function, Table, Lua}; diff --git a/src/protocol/clientbound.rs b/src/protocol/clientbound.rs index 2b3f24f..c9740c5 100644 --- a/src/protocol/clientbound.rs +++ b/src/protocol/clientbound.rs @@ -135,6 +135,7 @@ impl ChunkData { } } +#[allow(unused)] #[derive(Debug)] pub enum ClientBoundPacket { // status @@ -142,6 +143,7 @@ pub enum ClientBoundPacket { PingResponse(i64), // login LoginSuccess(LoginSuccess), + LoginDisconnect(serde_json::Value), // play LoginPlay(LoginPlay), PluginMessage(PluginMessage), @@ -149,6 +151,7 @@ pub enum ClientBoundPacket { ChunkData(ChunkData), KeepAlive(i64), PlayerAbilities(i8, f32, f32), + Disconnect(serde_json::Value), SystemChatMessage(serde_json::Value, bool), } @@ -156,6 +159,7 @@ impl ClientBoundPacket { pub fn encode(self) -> Vec { let mut packet = Vec::new(); match self { + // Status Self::StatusResponse(status) => { packet.write_string(32767, &status); finalize_packet(packet, 0) @@ -164,10 +168,24 @@ impl ClientBoundPacket { packet.write_long(n); finalize_packet(packet, 1) }, + // Login + Self::LoginDisconnect(message) => { + packet.write_string(262144, &message.to_string()); + finalize_packet(packet, 0) + } Self::LoginSuccess(login_success) => { login_success.encode(&mut packet); finalize_packet(packet, 2) } + // Play + Self::Disconnect(message) => { + packet.write_string(262144, &message.to_string()); + finalize_packet(packet, 25) + } + Self::LoginPlay(login_play) => { + login_play.encode(&mut packet); + finalize_packet(packet, 37) + } Self::PluginMessage(plugin_message) => { plugin_message.encode(&mut packet); finalize_packet(packet, 22) @@ -176,10 +194,6 @@ impl ClientBoundPacket { sync_player_position.encode(&mut packet); finalize_packet(packet, 57) } - Self::LoginPlay(login_play) => { - login_play.encode(&mut packet); - finalize_packet(packet, 37) - } Self::ChunkData(chunk_data) => { chunk_data.encode(&mut packet); finalize_packet(packet, 33) diff --git a/src/protocol/data.rs b/src/protocol/data.rs index 4e13084..1e35605 100644 --- a/src/protocol/data.rs +++ b/src/protocol/data.rs @@ -136,6 +136,7 @@ pub struct PacketDecoder { packet_id: i32, } +#[allow(unused)] impl PacketDecoder { pub fn decode(read: &mut impl Read) -> Result { let size = read_varint(read)? as usize; diff --git a/src/protocol/serverbound.rs b/src/protocol/serverbound.rs index ce6f599..0c105a3 100644 --- a/src/protocol/serverbound.rs +++ b/src/protocol/serverbound.rs @@ -31,7 +31,7 @@ pub struct SigData { pub struct LoginStart { pub name: String, pub sig_data: Option, - pub uuid: Option, + pub uuid: Uuid, } impl LoginStart { @@ -49,11 +49,10 @@ impl LoginStart { None }; let has_uuid = decoder.read_bool(); - let uuid = if has_uuid { - Some(decoder.read_uuid()) - } else { - None - }; + if !has_uuid { + panic!("Client didn't supply UUID"); + } + let uuid = decoder.read_uuid(); Self { name, sig_data, uuid } } }