What does this mean?

This commit is contained in:
illegitimate-egg 2025-03-02 18:49:51 +00:00
parent f4a75deba7
commit 54d23ed073
6 changed files with 182 additions and 33 deletions

View File

@ -15,7 +15,7 @@ pub fn handle_command(
extensions: &Arc<Extensions>, extensions: &Arc<Extensions>,
command_string: &String, command_string: &String,
) -> Result<(), AppError> { ) -> Result<(), AppError> {
let vectorized_command = command_string.split(" ").collect::<Vec<&str>>(); let vectorized_command = command_string.trim().split(" ").collect::<Vec<&str>>();
match vectorized_command[0] { match vectorized_command[0] {
"kick" => { "kick" => {
let mut players = players_arc_clone let mut players = players_arc_clone
@ -54,9 +54,16 @@ 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( let found = match extensions.run_command(
vectorized_command[0].to_string(), vectorized_command[0].to_string(),
client_number, client_number,
vectorized_command_object,
stream, stream,
) { ) {
Ok(result) => result, Ok(result) => result,

View File

@ -1,10 +1,10 @@
use log::{error, info}; use log::{error, info, warn, debug};
use regex::Regex; use regex::Regex;
use rhai::{CustomType, Engine, EvalAltResult, FnPtr, Scope, TypeBuilder, AST}; use rhai::{CustomType, Engine, EvalAltResult, FnPtr, Scope, TypeBuilder, AST};
use std::{ use std::{
collections::HashMap, collections::HashMap,
ffi::OsStr, ffi::OsStr,
fs, fmt, fs,
net::TcpStream, net::TcpStream,
path::Path, path::Path,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
@ -25,6 +25,7 @@ impl Extensions {
&self, &self,
key: String, key: String,
player: u8, player: u8,
argv: Vec<String>,
stream: &mut TcpStream, 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
@ -44,8 +45,7 @@ impl Extensions {
stream, stream,
format!( format!(
"&a{} &bv{}", "&a{} &bv{}",
extension.metadata.name, extension.metadata.name, extension.metadata.version
extension.metadata.version.display()
), ),
); );
} }
@ -61,11 +61,7 @@ impl Extensions {
for command in extension.commands.keys() { for command in extension.commands.keys() {
let _ = write_chat_stream( let _ = write_chat_stream(
stream, stream,
format!( format!("&c{} &a[{}]", command, extension.metadata.name),
"&c{} &a[{}]",
command,
extension.metadata.name
),
); );
} }
} }
@ -75,7 +71,17 @@ impl Extensions {
for extension in &self.extensions { for extension in &self.extensions {
if let Some(key_value) = extension.commands.get(&key) { if let Some(key_value) = extension.commands.get(&key) {
key_value.call::<()>(&extension.engine, &extension.ast, (player,))?; // Vector transfer number 2 (get the shit joke?)
let mut argv_rhai_array: rhai::Array = rhai::Array::new();
for arg in &argv {
argv_rhai_array.push(arg.into());
}
key_value.call::<()>(
&extension.engine,
&extension.ast,
(player, argv_rhai_array),
)?;
return Ok(true); return Ok(true);
} }
} }
@ -92,6 +98,22 @@ pub struct Extension {
} }
////// BEGIN RHAI DEFINITIONS ////// ////// BEGIN RHAI DEFINITIONS //////
fn info(msg: &str) {
info!("{}", msg);
}
fn warn(msg: &str) {
warn!("{}", msg);
}
fn error(msg: &str) {
error!("{}", msg);
}
fn debug(msg: &str) {
debug!("{}", msg);
}
#[derive(Debug, Clone, Eq, PartialEq, CustomType)] #[derive(Debug, Clone, Eq, PartialEq, CustomType)]
#[rhai_type(name = "Version", extra = Self::build_extra)] #[rhai_type(name = "Version", extra = Self::build_extra)]
struct Version { struct Version {
@ -153,16 +175,27 @@ impl Version {
} }
} }
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display())
}
}
#[derive(Debug, Clone, Eq, PartialEq, CustomType)] #[derive(Debug, Clone, Eq, PartialEq, CustomType)]
#[rhai_type(name = "Metadata", extra = Self::build_extra)] #[rhai_type(name = "Metadata", extra = Self::build_extra)]
struct ExtensionMetadata { struct ExtensionMetadata {
name: String, name: String,
author: String,
version: Version, version: Version,
} }
impl ExtensionMetadata { impl ExtensionMetadata {
fn new(name: String, version: Version) -> Self { fn new(name: String, author: String, version: Version) -> Self {
Self { name, version } Self {
name,
author,
version,
}
} }
fn build_extra(builder: &mut TypeBuilder<Self>) { fn build_extra(builder: &mut TypeBuilder<Self>) {
@ -196,8 +229,25 @@ impl PlayersWrapper {
Ok(()) Ok(())
} }
fn send_all(self, message: String) -> Result<(), Box<EvalAltResult>> {
let mut players = self.0.lock().unwrap();
let data = &send_chat_message(255, "".to_string(), message);
for i in 0..255 {
if players[i].id != 255 {
players[i]
.outgoing_data
.extend_from_slice(data);
}
}
Ok(())
}
fn build_extra(builder: &mut TypeBuilder<Self>) { fn build_extra(builder: &mut TypeBuilder<Self>) {
builder.with_fn("send_message", Self::send_message); builder.with_fn("send_message", Self::send_message);
builder.with_fn("send_all", Self::send_all);
} }
} }
@ -206,12 +256,39 @@ impl PlayersWrapper {
struct Context { struct Context {
#[rhai_type(skip)] #[rhai_type(skip)]
commands: HashMap<String, FnPtr>, commands: HashMap<String, FnPtr>,
#[rhai_type(skip)]
event_listener: HashMap<EventListener, FnPtr>,
}
#[derive(Debug, Clone, PartialEq, CustomType)]
#[rhai_type(name = "Vec3", extra = Self::build_extra)]
struct Vec3 {
x: i64,
y: i64,
z: i64,
}
// Custom type API
impl Vec3 {
fn new(x: i64, y: i64, z: i64) -> Self {
Self { x, y, z }
}
fn build_extra(builder: &mut TypeBuilder<Self>) {
builder.with_fn("Vec3", Self::new);
}
}
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
enum EventListener {
BlockBreak,
} }
impl Context { impl Context {
fn new() -> Self { fn new() -> Self {
Self { Self {
commands: HashMap::new(), commands: HashMap::new(),
event_listener: HashMap::new(),
} }
} }
@ -219,9 +296,18 @@ impl Context {
self.commands.insert(name, callback); self.commands.insert(name, callback);
} }
fn add_event_listener(&mut self, event: &str, callback: FnPtr) {
let event_listener: EventListener = match event {
"block_break" => EventListener::BlockBreak,
_ => return,
};
self.event_listener.insert(event_listener, callback);
}
fn build_extra(builder: &mut TypeBuilder<Self>) { fn build_extra(builder: &mut TypeBuilder<Self>) {
builder.with_fn("Context", Self::new); builder.with_fn("Context", Self::new);
builder.with_fn("register_command", Self::register_command); builder.with_fn("register_command", Self::register_command);
builder.with_fn("add_event_listener", Self::add_event_listener);
} }
} }
////// END RHAI DEFINITIONS ////// ////// END RHAI DEFINITIONS //////
@ -252,8 +338,21 @@ impl Extensions {
engine.build_type::<RhaiPlayer>(); engine.build_type::<RhaiPlayer>();
engine.build_type::<PlayersWrapper>(); engine.build_type::<PlayersWrapper>();
engine.build_type::<Context>(); engine.build_type::<Context>();
engine.register_fn("info", info);
engine.register_fn("warn", warn);
engine.register_fn("error", error);
engine.register_fn("debug", debug);
let ast = engine.compile_file(extension_path.clone().into())?; let ast = match engine.compile_file(extension_path.clone().into()) {
Ok(result) => result,
Err(error) => {
error!(
"Rhai plugin compilation failed for {}, reason: {}",
extension_path.display(), error
);
break;
}
};
let mut scope = Scope::new(); let mut scope = Scope::new();
let extension_metadata = let extension_metadata =
@ -300,8 +399,7 @@ impl Extensions {
info!( info!(
"Loaded {} v{}", "Loaded {} v{}",
current_extension.metadata.name, current_extension.metadata.name, current_extension.metadata.version,
current_extension.metadata.version.display()
); );
extensions.extensions.push(current_extension); extensions.extensions.push(current_extension);
@ -311,9 +409,7 @@ impl Extensions {
for command_name in extension.commands.keys() { for command_name in extension.commands.keys() {
info!( info!(
"Extension {} v{} has reserved command: {}", "Extension {} v{} has reserved command: {}",
extension.metadata.name, extension.metadata.name, extension.metadata.version, command_name
extension.metadata.version.display(),
command_name
); );
} }
} }

44
src/extensions/fill.rhai Normal file
View File

@ -0,0 +1,44 @@
fn metadata() {
Metadata("fill", "illegitimate-egg", Version("1.0.0")) // Version test util
}
fn init(players) {
let ctx = Context();
let playerData = #{};
ctx.register_command("fill", |player, argv| {
players.send_message(player, "Break two blocks to select area");
playerData[player].command_step == 1;
});
ctx.add_event_listener("block_break", |event| {
if playerData[event.player].command_step == () {
playerData[event.player].command_step == 0;
} else {
switch playerData[event.player].command_step {
0 => {
// Do nothing, the command isn't in use
}
1 => {
// Record the block position
playerData[event.player].firstBlock = event.position;
}
2 => {
playerData[event.player].secondBlock = event.position;
// TODO: Implement the fill
}
_ => {
error("Unreachable reached");
}
}
}
});
// NOTE: Currently this doesn't work, as player_leave isn't implemented
ctx.add_event_listener("player_leave", |event| {
playerData[event.player].command_step = 0;
});
ctx
}

View File

@ -1,11 +0,0 @@
fn metadata() {
Metadata("jimmy", Version("2.0.0-balls+tweaking"))
}
fn init(players) {
let ctx = Context();
ctx.register_command("jimmy", |player| {
players.send_message(player, "He's dead")
});
ctx
}

View File

@ -1,14 +1,14 @@
fn metadata() { fn metadata() {
Metadata("ping-pong", Version("1.0.0")) Metadata("ping-pong", "illegitimate-egg", Version("1.0.0"))
} }
fn init(players) { fn init(players) {
let ctx = Context(); let ctx = Context();
ctx.register_command("ping", |player| { ctx.register_command("ping", |player, argv| {
players.send_message(player, "pong") players.send_message(player, "pong")
}); });
ctx.register_command("foo", |player| { ctx.register_command("foo", |player, argv| {
players.send_message(player, "bar") players.send_message(player, "bar")
}); });

13
src/extensions/utils.rhai Normal file
View File

@ -0,0 +1,13 @@
fn metadata() {
Metadata("utils", "illegitimate-egg", Version("1.2.3-testp+testb")) // Version test util
}
fn init(players) {
let ctx = Context();
ctx.register_command("args", |player, argv| {
players.send_message(player, "" + argv)
});
ctx
}