Allow extension commands to be thread blocking (☹)

This commit is contained in:
illegitimate-egg 2025-03-03 22:32:09 +00:00
parent 6a06e0bb13
commit 8669913e4d
6 changed files with 147 additions and 61 deletions

77
Cargo.lock generated
View File

@ -43,6 +43,12 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -182,6 +188,7 @@ dependencies = [
"log", "log",
"regex", "regex",
"rhai", "rhai",
"rhai-rand",
"simple_logger", "simple_logger",
] ]
@ -266,6 +273,15 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.93" version = "1.0.93"
@ -284,6 +300,36 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.11.1"
@ -331,6 +377,18 @@ dependencies = [
"thin-vec", "thin-vec",
] ]
[[package]]
name = "rhai-rand"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4314e7e2a1f5d5de224ae3bc9ce2af4c0146d07d3c3aadf9840f08d80ef28800"
dependencies = [
"rand",
"rhai",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "rhai_codegen" name = "rhai_codegen"
version = "2.2.0" version = "2.2.0"
@ -342,6 +400,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.218" version = "1.0.218"
@ -362,6 +426,18 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "serde_json"
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]] [[package]]
name = "simple_logger" name = "simple_logger"
version = "5.0.0" version = "5.0.0"
@ -625,6 +701,7 @@ version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [ dependencies = [
"byteorder",
"zerocopy-derive", "zerocopy-derive",
] ]

View File

@ -8,6 +8,7 @@ ctrlc = "3.4.5"
flate2 = "1.0.30" flate2 = "1.0.30"
log = "0.4.26" log = "0.4.26"
regex = "1.11.1" regex = "1.11.1"
rhai-rand = "0.1.6"
[dependencies.simple_logger] [dependencies.simple_logger]
version = "5.0.0" version = "5.0.0"

View File

@ -71,39 +71,48 @@ pub fn handle_command(
} }
_ => { _ => {
let mut vectorized_command_object: Vec<String> = Vec::new(); let mut vectorized_command_object: Vec<String> = Vec::new();
for arg in &vectorized_command { for arg in &vectorized_command {
vectorized_command_object.push(arg.to_string()); vectorized_command_object.push(arg.to_string());
} }
let found = match extensions.run_command( let extensions_clone = Arc::clone(extensions);
vectorized_command[0].to_string(), let players_clone = Arc::clone(players_arc_clone);
client_number, let command_key = vectorized_command[0].to_string();
let client_number_copy = client_number;
// Async thread commands
std::thread::spawn(move || {
let result = extensions_clone.run_command(
command_key,
client_number_copy,
vectorized_command_object, vectorized_command_object,
stream, );
) {
Ok(result) => result, match result {
Err(error) => { Ok(found) => {
error!("Rhai plugin error: {}", error); if !found {
let _ = &mut stream.write(&send_chat_message( let mut players = players_clone.lock().unwrap();
let player = &mut players[client_number_copy as usize];
player.outgoing_data.extend_from_slice(&send_chat_message(
SpecialPlayers::SelfPlayer as u8, SpecialPlayers::SelfPlayer as u8,
"".to_string(), "".to_string(),
"&cAn internal error occured while processing this command".to_string(), "&cUnknown command!".to_string(),
)); ));
return Ok(());
} }
};
if found {
return Ok(());
} }
Err(err) => {
let _ = &mut stream.write(&send_chat_message( error!("Command error: {}", err);
let mut players = players_clone.lock().unwrap();
let player = &mut players[client_number_copy as usize];
player.outgoing_data.extend_from_slice(&send_chat_message(
SpecialPlayers::SelfPlayer as u8, SpecialPlayers::SelfPlayer as u8,
"".to_string(), "".to_string(),
"&cUnkown command!".to_string(), "&cCommand failed".to_string(),
)); ));
} }
} }
});
}
}
Ok(()) Ok(())
} }

View File

@ -1,11 +1,11 @@
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use regex::Regex; use regex::Regex;
use rhai::{CustomType, Engine, EvalAltResult, FnPtr, Scope, TypeBuilder, AST}; use rhai::{packages::Package, CustomType, Engine, EvalAltResult, FnPtr, Scope, TypeBuilder, AST};
use rhai_rand::RandomPackage;
use std::{ use std::{
collections::HashMap, collections::HashMap,
ffi::OsStr, ffi::OsStr,
fmt, fs, fmt, fs,
net::TcpStream,
path::Path, path::Path,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@ -19,6 +19,7 @@ use crate::{
pub struct Extensions { pub struct Extensions {
extensions: Vec<Extension>, extensions: Vec<Extension>,
players: PlayersWrapper,
} }
impl Extensions { impl Extensions {
@ -27,7 +28,6 @@ impl Extensions {
key: String, key: String,
player: u8, player: u8,
argv: Vec<String>, argv: Vec<String>,
stream: &mut TcpStream,
) -> Result<bool, AppError> { ) -> Result<bool, AppError> {
// Here I'm calling write_chat_stream multiple times. This is because the stock minecraft // Here I'm calling write_chat_stream multiple times. This is because the stock minecraft
// chat has a length limit of 64 characters, which is pathetically small. There is a // chat has a length limit of 64 characters, which is pathetically small. There is a
@ -39,51 +39,46 @@ impl Extensions {
// Reserve extension listing command // Reserve extension listing command
if &key == "extensions" { if &key == "extensions" {
let _ = write_chat_stream(stream, "Extension listing".to_string()); let mut res_data: Vec<u8> = Vec::new();
res_data.extend_from_slice(&write_chat_stream("Extension listing".to_string()));
for extension in &self.extensions { for extension in &self.extensions {
let _ = write_chat_stream( res_data.extend_from_slice(&write_chat_stream(format!(
stream,
format!(
"&a{} &bv{}", "&a{} &bv{}",
extension.metadata.name, extension.metadata.version extension.metadata.name, extension.metadata.version
), )));
);
} }
self.players.0.lock().unwrap()[player as usize]
.outgoing_data
.extend_from_slice(&res_data);
return Ok(true); return Ok(true);
} }
// Reserve command listing command // Reserve command listing command
if &key == "help" { if &key == "help" {
let _ = write_chat_stream(stream, "Command listing".to_string()); let mut res_data: Vec<u8> = Vec::new();
let _ = write_chat_stream( res_data.extend_from_slice(&write_chat_stream("Command listing".to_string()));
stream,
format!("&c{} &a[{}]", "help", "Builtin"), res_data.extend_from_slice(&write_chat_stream(format!("&c{} &a[{}]", "help", "Builtin")));
); res_data.extend_from_slice(&write_chat_stream(format!("&c{} &a[{}]", "extensions", "Builtin")));
let _ = write_chat_stream( res_data.extend_from_slice(&write_chat_stream(format!("&c{} &a[{}]", "kick", "Builtin")));
stream, res_data.extend_from_slice(&write_chat_stream(format!("&c{} &a[{}]", "tp", "Builtin")));
format!("&c{} &a[{}]", "extensions", "Builtin"),
);
let _ = write_chat_stream(
stream,
format!("&c{} &a[{}]", "kick", "Builtin"),
);
let _ = write_chat_stream(
stream,
format!("&c{} &a[{}]", "tp", "Builtin"),
);
for extension in &self.extensions { for extension in &self.extensions {
for command in extension.commands.keys() { for command in extension.commands.keys() {
let _ = write_chat_stream( res_data.extend_from_slice(&write_chat_stream(
stream,
format!("&c{} &a[{}]", command, extension.metadata.name), format!("&c{} &a[{}]", command, extension.metadata.name),
); ));
} }
} }
self.players.0.lock().unwrap()[player as usize]
.outgoing_data
.extend_from_slice(&res_data);
return Ok(true); return Ok(true);
} }
@ -450,6 +445,7 @@ impl Extensions {
let mut extensions = Extensions { let mut extensions = Extensions {
extensions: Vec::new(), extensions: Vec::new(),
players: players.clone(),
}; };
for extension in extensions_listing { for extension in extensions_listing {
@ -461,6 +457,8 @@ impl Extensions {
info!("Loading extension {}", extension_path.display()); info!("Loading extension {}", extension_path.display());
let mut engine = Engine::new(); let mut engine = Engine::new();
let random = RandomPackage::new();
random.register_into_engine(&mut engine);
engine.set_max_expr_depths(50, 50); engine.set_max_expr_depths(50, 50);
engine.build_type::<Version>(); engine.build_type::<Version>();
engine.build_type::<ExtensionMetadata>(); engine.build_type::<ExtensionMetadata>();

View File

@ -77,6 +77,7 @@ fn init(players, world) {
if playerData[event.player.to_string()] != () { if playerData[event.player.to_string()] != () {
playerData[event.player.to_string()].command_step = 0; playerData[event.player.to_string()].command_step = 0;
} }
event
}); });
ctx ctx

View File

@ -123,12 +123,12 @@ pub fn send_chat_message(
ret_val ret_val
} }
pub fn write_chat_stream(stream: &mut TcpStream, message: String) { pub fn write_chat_stream(message: String) -> Vec<u8> {
let _ = stream.write(&send_chat_message( send_chat_message(
SpecialPlayers::SelfPlayer as u8, SpecialPlayers::SelfPlayer as u8,
"".to_string(), "".to_string(),
message, message,
)); )
} }
pub fn set_position_and_orientation( pub fn set_position_and_orientation(