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"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -182,6 +188,7 @@ dependencies = [
"log",
"regex",
"rhai",
"rhai-rand",
"simple_logger",
]
@ -266,6 +273,15 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "proc-macro2"
version = "1.0.93"
@ -284,6 +300,36 @@ dependencies = [
"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]]
name = "regex"
version = "1.11.1"
@ -331,6 +377,18 @@ dependencies = [
"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]]
name = "rhai_codegen"
version = "2.2.0"
@ -342,6 +400,12 @@ dependencies = [
"syn",
]
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "serde"
version = "1.0.218"
@ -362,6 +426,18 @@ dependencies = [
"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]]
name = "simple_logger"
version = "5.0.0"
@ -625,6 +701,7 @@ version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]

View File

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

View File

@ -71,38 +71,47 @@ pub fn handle_command(
}
_ => {
let mut vectorized_command_object: Vec<String> = Vec::new();
for arg in &vectorized_command {
vectorized_command_object.push(arg.to_string());
}
let found = match extensions.run_command(
vectorized_command[0].to_string(),
client_number,
vectorized_command_object,
stream,
) {
Ok(result) => result,
Err(error) => {
error!("Rhai plugin error: {}", error);
let _ = &mut stream.write(&send_chat_message(
SpecialPlayers::SelfPlayer as u8,
"".to_string(),
"&cAn internal error occured while processing this command".to_string(),
));
return Ok(());
let extensions_clone = Arc::clone(extensions);
let players_clone = Arc::clone(players_arc_clone);
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,
);
match result {
Ok(found) => {
if !found {
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,
"".to_string(),
"&cUnknown command!".to_string(),
));
}
}
Err(err) => {
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,
"".to_string(),
"&cCommand failed".to_string(),
));
}
}
};
if found {
return Ok(());
}
let _ = &mut stream.write(&send_chat_message(
SpecialPlayers::SelfPlayer as u8,
"".to_string(),
"&cUnkown command!".to_string(),
));
});
}
}
Ok(())

View File

@ -1,11 +1,11 @@
use log::{debug, error, info, warn};
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::{
collections::HashMap,
ffi::OsStr,
fmt, fs,
net::TcpStream,
path::Path,
sync::{Arc, Mutex},
};
@ -19,6 +19,7 @@ use crate::{
pub struct Extensions {
extensions: Vec<Extension>,
players: PlayersWrapper,
}
impl Extensions {
@ -27,7 +28,6 @@ impl Extensions {
key: String,
player: u8,
argv: Vec<String>,
stream: &mut TcpStream,
) -> Result<bool, AppError> {
// 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
@ -39,51 +39,46 @@ impl Extensions {
// Reserve extension listing command
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 {
let _ = write_chat_stream(
stream,
format!(
"&a{} &bv{}",
extension.metadata.name, extension.metadata.version
),
);
res_data.extend_from_slice(&write_chat_stream(format!(
"&a{} &bv{}",
extension.metadata.name, extension.metadata.version
)));
}
self.players.0.lock().unwrap()[player as usize]
.outgoing_data
.extend_from_slice(&res_data);
return Ok(true);
}
// Reserve command listing command
if &key == "help" {
let _ = write_chat_stream(stream, "Command listing".to_string());
let mut res_data: Vec<u8> = Vec::new();
let _ = write_chat_stream(
stream,
format!("&c{} &a[{}]", "help", "Builtin"),
);
let _ = write_chat_stream(
stream,
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"),
);
res_data.extend_from_slice(&write_chat_stream("Command listing".to_string()));
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")));
res_data.extend_from_slice(&write_chat_stream(format!("&c{} &a[{}]", "kick", "Builtin")));
res_data.extend_from_slice(&write_chat_stream(format!("&c{} &a[{}]", "tp", "Builtin")));
for extension in &self.extensions {
for command in extension.commands.keys() {
let _ = write_chat_stream(
stream,
res_data.extend_from_slice(&write_chat_stream(
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);
}
@ -450,6 +445,7 @@ impl Extensions {
let mut extensions = Extensions {
extensions: Vec::new(),
players: players.clone(),
};
for extension in extensions_listing {
@ -461,6 +457,8 @@ impl Extensions {
info!("Loading extension {}", extension_path.display());
let mut engine = Engine::new();
let random = RandomPackage::new();
random.register_into_engine(&mut engine);
engine.set_max_expr_depths(50, 50);
engine.build_type::<Version>();
engine.build_type::<ExtensionMetadata>();

View File

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

View File

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