Add extension information commands
This commit is contained in:
parent
7ab11f7f54
commit
a58b1c9afe
@ -54,7 +54,11 @@ pub fn handle_command(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let found = match extensions.run_command(vectorized_command[0].to_string(), client_number) {
|
let found = match extensions.run_command(
|
||||||
|
vectorized_command[0].to_string(),
|
||||||
|
client_number,
|
||||||
|
stream,
|
||||||
|
) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
error!("Rhai plugin error: {}", error);
|
error!("Rhai plugin error: {}", error);
|
||||||
|
@ -5,19 +5,74 @@ use std::{
|
|||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
fs,
|
fs,
|
||||||
|
net::TcpStream,
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{error::AppError, player::Player, utils::send_chat_message};
|
use crate::{
|
||||||
|
error::AppError,
|
||||||
|
player::Player,
|
||||||
|
utils::{send_chat_message, write_chat_stream},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Extensions {
|
pub struct Extensions {
|
||||||
extensions: Vec<Extension>,
|
extensions: Vec<Extension>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extensions {
|
impl Extensions {
|
||||||
pub fn run_command(&self, key: String, player: u8) -> Result<bool, AppError> {
|
pub fn run_command(
|
||||||
// Bool success
|
&self,
|
||||||
|
key: String,
|
||||||
|
player: u8,
|
||||||
|
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
|
||||||
|
// classic extension to support an unlimited number of characters, but it's not guaranteed
|
||||||
|
// that the client will support it, so the next best option is to just send multiple
|
||||||
|
// messages, they're newline seperated anyway. I am aware that repeated stream writes are
|
||||||
|
// not the best option however, and that at some point I should switch to buffered streams.
|
||||||
|
// TODO: Use buffered streams (That's everywhere not just here)
|
||||||
|
|
||||||
|
// Reserve extension listing command
|
||||||
|
if &key == "extensions" {
|
||||||
|
let _ = write_chat_stream(stream, "Extension listing".to_string());
|
||||||
|
|
||||||
|
for extension in &self.extensions {
|
||||||
|
let _ = write_chat_stream(
|
||||||
|
stream,
|
||||||
|
format!(
|
||||||
|
"&a{} &bv{}",
|
||||||
|
extension.metadata.name,
|
||||||
|
extension.metadata.version.display()
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve command listing command
|
||||||
|
if &key == "commands" {
|
||||||
|
let _ = write_chat_stream(stream, "Command listing".to_string());
|
||||||
|
|
||||||
|
for extension in &self.extensions {
|
||||||
|
for command in extension.commands.keys() {
|
||||||
|
let _ = write_chat_stream(
|
||||||
|
stream,
|
||||||
|
format!(
|
||||||
|
"&c{} &a[{}]",
|
||||||
|
command,
|
||||||
|
extension.metadata.name
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
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,))?;
|
key_value.call::<()>(&extension.engine, &extension.ast, (player,))?;
|
||||||
@ -233,7 +288,7 @@ impl Extensions {
|
|||||||
&mut scope,
|
&mut scope,
|
||||||
¤t_extension.ast,
|
¤t_extension.ast,
|
||||||
"init",
|
"init",
|
||||||
(PlayersWrapper::new(players.0.clone()),)
|
(PlayersWrapper::new(players.0.clone()),),
|
||||||
) {
|
) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
16
src/extensions/ping-pong.rhai
Normal file
16
src/extensions/ping-pong.rhai
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
fn metadata() {
|
||||||
|
Metadata("ping-pong", Version("1.0.0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(players) {
|
||||||
|
let ctx = Context(players);
|
||||||
|
|
||||||
|
ctx.register_command("ping", |player| {
|
||||||
|
players.send_message(player, "pong")
|
||||||
|
});
|
||||||
|
ctx.register_command("foo", |player| {
|
||||||
|
players.send_message(player, "bar")
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx
|
||||||
|
}
|
23
src/utils.rs
23
src/utils.rs
@ -6,9 +6,9 @@ use std::net::TcpStream;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::error::AppError;
|
use crate::error::AppError;
|
||||||
use crate::World;
|
|
||||||
use crate::SpecialPlayers;
|
|
||||||
use crate::Player;
|
use crate::Player;
|
||||||
|
use crate::SpecialPlayers;
|
||||||
|
use crate::World;
|
||||||
|
|
||||||
pub fn to_mc_string(text: &str) -> [u8; 64] {
|
pub fn to_mc_string(text: &str) -> [u8; 64] {
|
||||||
let text_vec: Vec<char> = text.chars().take(64).collect();
|
let text_vec: Vec<char> = text.chars().take(64).collect();
|
||||||
@ -104,7 +104,11 @@ pub fn despawn_player(player_id: u8) -> Vec<u8> {
|
|||||||
[0x0C, player_id].to_vec()
|
[0x0C, player_id].to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_chat_message(source_id: u8, mut source_username: String, mut message: String) -> Vec<u8> {
|
pub fn send_chat_message(
|
||||||
|
source_id: u8,
|
||||||
|
mut source_username: String,
|
||||||
|
mut message: String,
|
||||||
|
) -> Vec<u8> {
|
||||||
let mut ret_val: Vec<u8> = vec![];
|
let mut ret_val: Vec<u8> = vec![];
|
||||||
ret_val.push(0x0D);
|
ret_val.push(0x0D);
|
||||||
|
|
||||||
@ -119,6 +123,14 @@ pub fn send_chat_message(source_id: u8, mut source_username: String, mut message
|
|||||||
ret_val
|
ret_val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_chat_stream(stream: &mut TcpStream, message: String) {
|
||||||
|
let _ = stream.write(&send_chat_message(
|
||||||
|
SpecialPlayers::SelfPlayer as u8,
|
||||||
|
"".to_string(),
|
||||||
|
message,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_position_and_orientation(
|
pub fn set_position_and_orientation(
|
||||||
player_id: u8,
|
player_id: u8,
|
||||||
pos_x: i16,
|
pos_x: i16,
|
||||||
@ -189,9 +201,7 @@ pub fn send_level_data(world_arc_clone: &Arc<Mutex<World>>) -> Result<Vec<u8>, A
|
|||||||
if remaining_chunk_size > 0 {
|
if remaining_chunk_size > 0 {
|
||||||
ret_val.push(0x03);
|
ret_val.push(0x03);
|
||||||
|
|
||||||
ret_val.append(&mut stream_write_short(
|
ret_val.append(&mut stream_write_short(remaining_chunk_size.try_into()?));
|
||||||
remaining_chunk_size.try_into()?,
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut remaining_data_buffer = [0u8; 1024];
|
let mut remaining_data_buffer = [0u8; 1024];
|
||||||
for i in 0..remaining_chunk_size {
|
for i in 0..remaining_chunk_size {
|
||||||
@ -238,4 +248,3 @@ pub fn bomb_server_details(
|
|||||||
let _ = stream.write(&compound_data);
|
let _ = stream.write(&compound_data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ use std::fs::{self, File};
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use log::info;
|
||||||
|
|
||||||
use crate::error::AppError;
|
use crate::error::AppError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -61,8 +63,10 @@ impl World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
world.data = world_data_raw[6..].to_vec();
|
world.data = world_data_raw[6..].to_vec();
|
||||||
|
info!("Loaded world {}", "world.wrld");
|
||||||
Ok(world)
|
Ok(world)
|
||||||
} else {
|
} else {
|
||||||
|
info!("Creating word {}", "world.wrld");
|
||||||
Ok(World {
|
Ok(World {
|
||||||
size_x: 64,
|
size_x: 64,
|
||||||
size_y: 32,
|
size_y: 32,
|
||||||
@ -75,7 +79,9 @@ impl World {
|
|||||||
pub fn save(world_arc_clone: Arc<Mutex<World>>) -> Result<(), AppError> {
|
pub fn save(world_arc_clone: Arc<Mutex<World>>) -> Result<(), AppError> {
|
||||||
let mut to_write: Vec<u8> = Vec::new();
|
let mut to_write: Vec<u8> = Vec::new();
|
||||||
{
|
{
|
||||||
let mut world_dat = world_arc_clone.lock().map_err(|e| AppError::MutexPoisoned(e.to_string()))?;
|
let mut world_dat = world_arc_clone
|
||||||
|
.lock()
|
||||||
|
.map_err(|e| AppError::MutexPoisoned(e.to_string()))?;
|
||||||
|
|
||||||
to_write.push((world_dat.size_x >> 8) as u8);
|
to_write.push((world_dat.size_x >> 8) as u8);
|
||||||
to_write.push((world_dat.size_x & 0xFF) as u8);
|
to_write.push((world_dat.size_x & 0xFF) as u8);
|
||||||
|
Loading…
Reference in New Issue
Block a user