more things
This commit is contained in:
parent
e1ccb6ec7d
commit
162d337769
12 changed files with 407 additions and 110 deletions
226
Cargo.lock
generated
226
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
33
src/main.rs
33
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<NetworkClient>) {
|
||||
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<u8> = 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(())
|
||||
}
|
||||
|
||||
|
|
70
src/plugins/init_lua.rs
Normal file
70
src/plugins/init_lua.rs
Normal file
|
@ -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(())
|
||||
}
|
|
@ -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<Plugin<'lua>>
|
||||
|
@ -18,47 +31,7 @@ pub struct Plugins<'lua> {
|
|||
|
||||
impl <'lua> Plugins<'lua> {
|
||||
pub fn new(lua: &'lua Lua) -> Result<Self, mlua::Error> {
|
||||
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<Response> {
|
||||
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 },
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{path::{PathBuf, Path}, str::FromStr};
|
||||
use std::path::Path;
|
||||
|
||||
use mlua::{Function, Table, Lua};
|
||||
|
||||
|
|
|
@ -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<u8> {
|
||||
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)
|
||||
|
|
|
@ -136,6 +136,7 @@ pub struct PacketDecoder {
|
|||
packet_id: i32,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
impl PacketDecoder {
|
||||
pub fn decode(read: &mut impl Read) -> Result<PacketDecoder, std::io::Error> {
|
||||
let size = read_varint(read)? as usize;
|
||||
|
|
|
@ -31,7 +31,7 @@ pub struct SigData {
|
|||
pub struct LoginStart {
|
||||
pub name: String,
|
||||
pub sig_data: Option<SigData>,
|
||||
pub uuid: Option<Uuid>,
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue