AAAH MEGA EXTENSIONSSS RUUURH
This commit is contained in:
parent
54d23ed073
commit
1666ef4cf2
@ -1,4 +1,4 @@
|
|||||||
use log::{error, info, warn, debug};
|
use log::{debug, error, info, warn};
|
||||||
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::{
|
||||||
@ -13,7 +13,8 @@ use std::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::AppError,
|
error::AppError,
|
||||||
player::Player,
|
player::Player,
|
||||||
utils::{send_chat_message, write_chat_stream},
|
utils::{send_chat_message, stream_write_short, write_chat_stream},
|
||||||
|
world::World,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Extensions {
|
pub struct Extensions {
|
||||||
@ -88,12 +89,33 @@ impl Extensions {
|
|||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_event(&self, event_type: EventType, event: Event) -> Event {
|
||||||
|
let mut is_cancelled = false;
|
||||||
|
|
||||||
|
for extension in &self.extensions {
|
||||||
|
if let Some(key_value) = extension.event_listeners.get(&event_type) {
|
||||||
|
is_cancelled =
|
||||||
|
match key_value.call::<Event>(&extension.engine, &extension.ast, (event,)) {
|
||||||
|
Ok(result) => result.is_cancelled,
|
||||||
|
Err(err) => {
|
||||||
|
error!("{} raised: {}", extension.metadata.name, err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut response = Event::new();
|
||||||
|
response.is_cancelled = is_cancelled;
|
||||||
|
response
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Extension {
|
pub struct Extension {
|
||||||
ast: AST,
|
ast: AST,
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
commands: HashMap<String, FnPtr>,
|
commands: HashMap<String, FnPtr>,
|
||||||
|
event_listeners: HashMap<EventType, FnPtr>,
|
||||||
metadata: ExtensionMetadata,
|
metadata: ExtensionMetadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,18 +258,69 @@ impl PlayersWrapper {
|
|||||||
|
|
||||||
for i in 0..255 {
|
for i in 0..255 {
|
||||||
if players[i].id != 255 {
|
if players[i].id != 255 {
|
||||||
players[i]
|
players[i].outgoing_data.extend_from_slice(data);
|
||||||
.outgoing_data
|
|
||||||
.extend_from_slice(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn username(self, player: u8) -> String {
|
||||||
|
let players = self.0.lock().unwrap();
|
||||||
|
|
||||||
|
players[player as usize].username.clone()
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
builder.with_fn("send_all", Self::send_all);
|
||||||
|
builder.with_fn("username", Self::username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, CustomType)]
|
||||||
|
#[rhai_type(name = "WorldWrapper", extra=Self::build_extra)]
|
||||||
|
pub struct WorldWrapper(Arc<Mutex<World>>);
|
||||||
|
|
||||||
|
impl WorldWrapper {
|
||||||
|
pub fn new(world: Arc<Mutex<World>>) -> Self {
|
||||||
|
Self(world)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_block(self, players_wrapper: PlayersWrapper, position: Vec3, block_type: u8) {
|
||||||
|
let mut world_dat = self.0.lock().unwrap();
|
||||||
|
|
||||||
|
let world_offset: u32 = position.x as u32
|
||||||
|
+ (position.z as u32 * world_dat.size_x as u32)
|
||||||
|
+ (position.y as u32 * world_dat.size_x as u32 * world_dat.size_z as u32);
|
||||||
|
|
||||||
|
world_dat.data[world_offset as usize] = block_type;
|
||||||
|
|
||||||
|
let mut update_block_bytes: Vec<u8> = Vec::new();
|
||||||
|
update_block_bytes.push(0x06);
|
||||||
|
update_block_bytes.extend_from_slice(&stream_write_short(position.x));
|
||||||
|
update_block_bytes.extend_from_slice(&stream_write_short(position.y));
|
||||||
|
update_block_bytes.extend_from_slice(&stream_write_short(position.z));
|
||||||
|
update_block_bytes.push(block_type);
|
||||||
|
|
||||||
|
let mut players = players_wrapper.0.lock().unwrap();
|
||||||
|
for i in 0..players.len() {
|
||||||
|
if players[i].id != 255 {
|
||||||
|
players[i]
|
||||||
|
.outgoing_data
|
||||||
|
.extend_from_slice(&update_block_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Finish this
|
||||||
|
// pub fn get_block(&self, position: Vec3) -> u8 {
|
||||||
|
// let mut world = self.0.lock().unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn build_extra(builder: &mut TypeBuilder<Self>) {
|
||||||
|
builder.with_fn("set_block", Self::set_block);
|
||||||
|
// builder.with_fn("get_block", Self::get_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,21 +330,21 @@ struct Context {
|
|||||||
#[rhai_type(skip)]
|
#[rhai_type(skip)]
|
||||||
commands: HashMap<String, FnPtr>,
|
commands: HashMap<String, FnPtr>,
|
||||||
#[rhai_type(skip)]
|
#[rhai_type(skip)]
|
||||||
event_listener: HashMap<EventListener, FnPtr>,
|
event_listener: HashMap<EventType, FnPtr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, CustomType)]
|
#[derive(Debug, Clone, Copy, PartialEq, CustomType)]
|
||||||
#[rhai_type(name = "Vec3", extra = Self::build_extra)]
|
#[rhai_type(name = "Vec3", extra = Self::build_extra)]
|
||||||
struct Vec3 {
|
pub struct Vec3 {
|
||||||
x: i64,
|
pub x: i16,
|
||||||
y: i64,
|
pub y: i16,
|
||||||
z: i64,
|
pub z: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom type API
|
// Custom type API
|
||||||
impl Vec3 {
|
impl Vec3 {
|
||||||
fn new(x: i64, y: i64, z: i64) -> Self {
|
fn new(x: i64, y: i64, z: i64) -> Self {
|
||||||
Self { x, y, z }
|
Self { x: x.try_into().unwrap(), y: y.try_into().unwrap(), z: z.try_into().unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_extra(builder: &mut TypeBuilder<Self>) {
|
fn build_extra(builder: &mut TypeBuilder<Self>) {
|
||||||
@ -280,8 +353,38 @@ impl Vec3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||||
enum EventListener {
|
pub enum EventType {
|
||||||
BlockBreak,
|
BlockBreak,
|
||||||
|
PlayerLeave,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, CustomType)]
|
||||||
|
#[rhai_type(name = "Event", extra = Self::build_extra)]
|
||||||
|
pub struct Event {
|
||||||
|
pub player: u8,
|
||||||
|
pub position: Vec3,
|
||||||
|
pub selected_block: u8,
|
||||||
|
pub is_cancelled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Event {
|
||||||
|
pub fn new() -> Event {
|
||||||
|
Event {
|
||||||
|
player: 255,
|
||||||
|
position: (Vec3 { x: 0, y: 0, z: 0 }),
|
||||||
|
selected_block: 0,
|
||||||
|
is_cancelled: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cancel(&mut self) {
|
||||||
|
self.is_cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_extra(builder: &mut TypeBuilder<Self>) {
|
||||||
|
builder.with_fn("Event", Self::new);
|
||||||
|
builder.with_fn("cancel", Self::cancel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
@ -297,9 +400,10 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_event_listener(&mut self, event: &str, callback: FnPtr) {
|
fn add_event_listener(&mut self, event: &str, callback: FnPtr) {
|
||||||
let event_listener: EventListener = match event {
|
let event_listener: EventType = match event {
|
||||||
"block_break" => EventListener::BlockBreak,
|
"block_break" => EventType::BlockBreak,
|
||||||
_ => return,
|
"player_leave" => EventType::PlayerLeave,
|
||||||
|
_ => {warn!("An event listener was created with invalid type: {}", event); return},
|
||||||
};
|
};
|
||||||
self.event_listener.insert(event_listener, callback);
|
self.event_listener.insert(event_listener, callback);
|
||||||
}
|
}
|
||||||
@ -313,7 +417,7 @@ impl Context {
|
|||||||
////// END RHAI DEFINITIONS //////
|
////// END RHAI DEFINITIONS //////
|
||||||
|
|
||||||
impl Extensions {
|
impl Extensions {
|
||||||
pub fn init(players: PlayersWrapper) -> Result<Extensions, AppError> {
|
pub fn init(players: PlayersWrapper, world: WorldWrapper) -> Result<Extensions, AppError> {
|
||||||
if !Path::new("./extensions/").exists() {
|
if !Path::new("./extensions/").exists() {
|
||||||
let _ = fs::create_dir("./extensions/");
|
let _ = fs::create_dir("./extensions/");
|
||||||
}
|
}
|
||||||
@ -333,11 +437,15 @@ impl Extensions {
|
|||||||
info!("Loading extension {}", extension_path.display());
|
info!("Loading extension {}", extension_path.display());
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
engine.set_max_expr_depths(50, 50);
|
||||||
engine.build_type::<Version>();
|
engine.build_type::<Version>();
|
||||||
engine.build_type::<ExtensionMetadata>();
|
engine.build_type::<ExtensionMetadata>();
|
||||||
engine.build_type::<RhaiPlayer>();
|
engine.build_type::<RhaiPlayer>();
|
||||||
engine.build_type::<PlayersWrapper>();
|
engine.build_type::<PlayersWrapper>();
|
||||||
|
engine.build_type::<WorldWrapper>();
|
||||||
engine.build_type::<Context>();
|
engine.build_type::<Context>();
|
||||||
|
engine.build_type::<Vec3>();
|
||||||
|
engine.build_type::<Event>();
|
||||||
engine.register_fn("info", info);
|
engine.register_fn("info", info);
|
||||||
engine.register_fn("warn", warn);
|
engine.register_fn("warn", warn);
|
||||||
engine.register_fn("error", error);
|
engine.register_fn("error", error);
|
||||||
@ -348,9 +456,10 @@ impl Extensions {
|
|||||||
Err(error) => {
|
Err(error) => {
|
||||||
error!(
|
error!(
|
||||||
"Rhai plugin compilation failed for {}, reason: {}",
|
"Rhai plugin compilation failed for {}, reason: {}",
|
||||||
extension_path.display(), error
|
extension_path.display(),
|
||||||
|
error
|
||||||
);
|
);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut scope = Scope::new();
|
let mut scope = Scope::new();
|
||||||
@ -364,7 +473,7 @@ impl Extensions {
|
|||||||
extension_path.display(),
|
extension_path.display(),
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -372,6 +481,7 @@ impl Extensions {
|
|||||||
ast,
|
ast,
|
||||||
engine,
|
engine,
|
||||||
commands: HashMap::new(),
|
commands: HashMap::new(),
|
||||||
|
event_listeners: HashMap::new(),
|
||||||
metadata: extension_metadata,
|
metadata: extension_metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -379,7 +489,10 @@ impl Extensions {
|
|||||||
&mut scope,
|
&mut scope,
|
||||||
¤t_extension.ast,
|
¤t_extension.ast,
|
||||||
"init",
|
"init",
|
||||||
(PlayersWrapper::new(players.0.clone()),),
|
(
|
||||||
|
PlayersWrapper::new(players.0.clone()),
|
||||||
|
WorldWrapper::new(world.0.clone()),
|
||||||
|
),
|
||||||
) {
|
) {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
@ -387,7 +500,7 @@ impl Extensions {
|
|||||||
"Plugin {} failed to init: {}",
|
"Plugin {} failed to init: {}",
|
||||||
current_extension.metadata.name, error
|
current_extension.metadata.name, error
|
||||||
);
|
);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -397,6 +510,12 @@ impl Extensions {
|
|||||||
.insert(key.to_string(), value.clone());
|
.insert(key.to_string(), value.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (key, value) in ctx.event_listener.iter() {
|
||||||
|
current_extension
|
||||||
|
.event_listeners
|
||||||
|
.insert(key.clone(), value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Loaded {} v{}",
|
"Loaded {} v{}",
|
||||||
current_extension.metadata.name, current_extension.metadata.version,
|
current_extension.metadata.name, current_extension.metadata.version,
|
||||||
|
@ -2,42 +2,81 @@ fn metadata() {
|
|||||||
Metadata("fill", "illegitimate-egg", Version("1.0.0")) // Version test util
|
Metadata("fill", "illegitimate-egg", Version("1.0.0")) // Version test util
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(players) {
|
fn init(players, world) {
|
||||||
let ctx = Context();
|
let ctx = Context();
|
||||||
|
|
||||||
let playerData = #{};
|
let playerData = #{};
|
||||||
|
|
||||||
ctx.register_command("fill", |player, argv| {
|
ctx.register_command("fill", |player, argv| {
|
||||||
players.send_message(player, "Break two blocks to select area");
|
players.send_message(player, "Break two blocks to select area");
|
||||||
playerData[player].command_step == 1;
|
playerData[player.to_string()] = #{command_step: 1};
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.add_event_listener("block_break", |event| {
|
ctx.add_event_listener("block_break", |event| {
|
||||||
if playerData[event.player].command_step == () {
|
let player_data = playerData[event.player.to_string()];
|
||||||
playerData[event.player].command_step == 0;
|
if player_data != () {
|
||||||
} else {
|
switch player_data.command_step {
|
||||||
switch playerData[event.player].command_step {
|
|
||||||
0 => {
|
0 => {
|
||||||
// Do nothing, the command isn't in use
|
// Do nothing, the command isn't in use
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
// Record the block position
|
player_data.command_step += 1;
|
||||||
playerData[event.player].firstBlock = event.position;
|
event.cancel();
|
||||||
|
|
||||||
|
player_data.firstBlock = event.position;
|
||||||
|
players.send_message(event.player, "Position 1 {" + event.position.x + ", " + event.position.y + ", " + event.position.z + "}");
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
playerData[event.player].secondBlock = event.position;
|
player_data.command_step = 0;
|
||||||
// TODO: Implement the fill
|
event.cancel();
|
||||||
|
|
||||||
|
player_data.secondBlock = event.position;
|
||||||
|
|
||||||
|
players.send_message(event.player, "Position 2 {" + event.position.x + ", " + event.position.y + ", " + event.position.z + "}");
|
||||||
|
|
||||||
|
if (player_data.firstBlock.x > player_data.secondBlock.x) {
|
||||||
|
let buffer = player_data.firstBlock.x;
|
||||||
|
player_data.firstBlock.x = player_data.secondBlock.x;
|
||||||
|
player_data.secondBlock.x = buffer;
|
||||||
|
}
|
||||||
|
if (player_data.firstBlock.y > player_data.secondBlock.y) {
|
||||||
|
let buffer = player_data.firstBlock.y;
|
||||||
|
player_data.firstBlock.y = player_data.secondBlock.y;
|
||||||
|
player_data.secondBlock.y = buffer;
|
||||||
|
}
|
||||||
|
if (player_data.firstBlock.z > player_data.secondBlock.z) {
|
||||||
|
let buffer = player_data.firstBlock.z;
|
||||||
|
player_data.firstBlock.z = player_data.secondBlock.z;
|
||||||
|
player_data.secondBlock.z = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let filled_blocks = 0;
|
||||||
|
|
||||||
|
for x in (player_data.firstBlock.x.to_int())..=(player_data.secondBlock.x.to_int()) {
|
||||||
|
for y in (player_data.firstBlock.y.to_int())..=(player_data.secondBlock.y.to_int()) {
|
||||||
|
for z in (player_data.firstBlock.z.to_int())..=(player_data.secondBlock.z.to_int()) {
|
||||||
|
world.set_block(players, Vec3(x, y, z), event.selected_block);
|
||||||
|
filled_blocks = filled_blocks + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
players.send_message(event.player, "Filled " + filled_blocks + " blocks");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error("Unreachable reached");
|
error("Unreachable reached");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
playerData[event.player.to_string()] = player_data;
|
||||||
|
return event;
|
||||||
});
|
});
|
||||||
|
|
||||||
// NOTE: Currently this doesn't work, as player_leave isn't implemented
|
// NOTE: Currently this doesn't work, as player_leave isn't implemented
|
||||||
ctx.add_event_listener("player_leave", |event| {
|
ctx.add_event_listener("player_leave", |event| {
|
||||||
playerData[event.player].command_step = 0;
|
playerData[event.player.to_string()].command_step = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx
|
ctx
|
||||||
|
@ -2,7 +2,7 @@ fn metadata() {
|
|||||||
Metadata("ping-pong", "illegitimate-egg", Version("1.0.0"))
|
Metadata("ping-pong", "illegitimate-egg", Version("1.0.0"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(players) {
|
fn init(players, world) {
|
||||||
let ctx = Context();
|
let ctx = Context();
|
||||||
|
|
||||||
ctx.register_command("ping", |player, argv| {
|
ctx.register_command("ping", |player, argv| {
|
||||||
|
@ -2,7 +2,7 @@ fn metadata() {
|
|||||||
Metadata("utils", "illegitimate-egg", Version("1.2.3-testp+testb")) // Version test util
|
Metadata("utils", "illegitimate-egg", Version("1.2.3-testp+testb")) // Version test util
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(players) {
|
fn init(players, world) {
|
||||||
let ctx = Context();
|
let ctx = Context();
|
||||||
|
|
||||||
ctx.register_command("args", |player, argv| {
|
ctx.register_command("args", |player, argv| {
|
||||||
|
@ -12,7 +12,7 @@ mod utils;
|
|||||||
mod world;
|
mod world;
|
||||||
|
|
||||||
use error::AppError;
|
use error::AppError;
|
||||||
use extensions::{Extensions, PlayersWrapper};
|
use extensions::{Extensions, PlayersWrapper, WorldWrapper};
|
||||||
use network::handle_client;
|
use network::handle_client;
|
||||||
use player::{Player, SpecialPlayers};
|
use player::{Player, SpecialPlayers};
|
||||||
use world::World;
|
use world::World;
|
||||||
@ -47,7 +47,10 @@ fn run() -> Result<(), AppError> {
|
|||||||
})
|
})
|
||||||
.expect("Error handling control C, save on exit will not work");
|
.expect("Error handling control C, save on exit will not work");
|
||||||
|
|
||||||
let extensions = Arc::new(Extensions::init(PlayersWrapper::new(players_arc.clone()))?);
|
let extensions = Arc::new(Extensions::init(
|
||||||
|
PlayersWrapper::new(players_arc.clone()),
|
||||||
|
WorldWrapper::new(world_arc.clone()),
|
||||||
|
)?);
|
||||||
|
|
||||||
info!("Server listening on {}", 25565);
|
info!("Server listening on {}", 25565);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use log::{info, warn};
|
use log::{debug, info, warn};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@ -7,7 +7,7 @@ use std::thread::sleep;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::command::handle_command;
|
use crate::command::handle_command;
|
||||||
use crate::extensions::Extensions;
|
use crate::extensions::{Event, EventType, Extensions};
|
||||||
use crate::player::{Player, PlayerStatus, SpecialPlayers};
|
use crate::player::{Player, PlayerStatus, SpecialPlayers};
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
use crate::world::World;
|
use crate::world::World;
|
||||||
@ -115,6 +115,9 @@ pub fn handle_client(
|
|||||||
let mut payload_buffer = [0; 8]; // Short (2) + Short (2) + Short (2) + Byte (1) + Byte (1)
|
let mut payload_buffer = [0; 8]; // Short (2) + Short (2) + Short (2) + Byte (1) + Byte (1)
|
||||||
let _ = stream.read(&mut payload_buffer);
|
let _ = stream.read(&mut payload_buffer);
|
||||||
|
|
||||||
|
let mut is_cancelled = false;
|
||||||
|
let mut previous_block: u8 = 0;
|
||||||
|
|
||||||
let position_x =
|
let position_x =
|
||||||
((payload_buffer[0] as i16) << (8 as i16)) + payload_buffer[1] as i16;
|
((payload_buffer[0] as i16) << (8 as i16)) + payload_buffer[1] as i16;
|
||||||
let position_y =
|
let position_y =
|
||||||
@ -125,6 +128,21 @@ pub fn handle_client(
|
|||||||
let mode = payload_buffer[6];
|
let mode = payload_buffer[6];
|
||||||
let mut block_type = payload_buffer[7];
|
let mut block_type = payload_buffer[7];
|
||||||
{
|
{
|
||||||
|
if mode == 0x00 {
|
||||||
|
// EVENT: BLOCK BREAK
|
||||||
|
let mut event = Event::new();
|
||||||
|
event.player = client_number;
|
||||||
|
event.position.x = position_x;
|
||||||
|
event.position.y = position_y;
|
||||||
|
event.position.z = position_z;
|
||||||
|
event.selected_block = block_type;
|
||||||
|
event = extensions.run_event(EventType::BlockBreak, event);
|
||||||
|
|
||||||
|
is_cancelled = event.is_cancelled;
|
||||||
|
|
||||||
|
block_type = 0x00; // Air
|
||||||
|
}
|
||||||
|
|
||||||
let mut world_dat = world_arc_clone.lock().unwrap();
|
let mut world_dat = world_arc_clone.lock().unwrap();
|
||||||
|
|
||||||
// Sanity check (Stop losers from losing)
|
// Sanity check (Stop losers from losing)
|
||||||
@ -139,32 +157,43 @@ pub fn handle_client(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == 0x00 {
|
|
||||||
block_type = 0x00; // Air
|
|
||||||
}
|
|
||||||
|
|
||||||
let world_offset: u32 = position_x as u32
|
let world_offset: u32 = position_x as u32
|
||||||
+ (position_z as u32 * world_dat.size_x as u32)
|
+ (position_z as u32 * world_dat.size_x as u32)
|
||||||
+ (position_y as u32
|
+ (position_y as u32
|
||||||
* world_dat.size_x as u32
|
* world_dat.size_x as u32
|
||||||
* world_dat.size_z as u32);
|
* world_dat.size_z as u32);
|
||||||
world_dat.data[world_offset as usize] = block_type;
|
if !is_cancelled {
|
||||||
|
world_dat.data[world_offset as usize] = block_type;
|
||||||
|
} else {
|
||||||
|
previous_block = world_dat.data[world_offset as usize];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut update_block_bytes: Vec<u8> = Vec::new();
|
if !is_cancelled {
|
||||||
update_block_bytes.push(0x06);
|
let mut update_block_bytes: Vec<u8> = Vec::new();
|
||||||
update_block_bytes.extend_from_slice(&stream_write_short(position_x));
|
update_block_bytes.push(0x06);
|
||||||
update_block_bytes.extend_from_slice(&stream_write_short(position_y));
|
update_block_bytes.extend_from_slice(&stream_write_short(position_x));
|
||||||
update_block_bytes.extend_from_slice(&stream_write_short(position_z));
|
update_block_bytes.extend_from_slice(&stream_write_short(position_y));
|
||||||
update_block_bytes.push(block_type);
|
update_block_bytes.extend_from_slice(&stream_write_short(position_z));
|
||||||
|
update_block_bytes.push(block_type);
|
||||||
|
|
||||||
let mut players = players_arc_clone.lock().unwrap();
|
let mut players = players_arc_clone.lock().unwrap();
|
||||||
for i in 0..players.len() {
|
for i in 0..players.len() {
|
||||||
if players[i].id != 255 && players[i].id != client_number {
|
if players[i].id != 255 && players[i].id != client_number {
|
||||||
players[i]
|
players[i]
|
||||||
.outgoing_data
|
.outgoing_data
|
||||||
.extend_from_slice(&update_block_bytes);
|
.extend_from_slice(&update_block_bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let mut update_block_bytes: Vec<u8> = Vec::new();
|
||||||
|
update_block_bytes.push(0x06);
|
||||||
|
update_block_bytes.extend_from_slice(&stream_write_short(position_x));
|
||||||
|
update_block_bytes.extend_from_slice(&stream_write_short(position_y));
|
||||||
|
update_block_bytes.extend_from_slice(&stream_write_short(position_z));
|
||||||
|
update_block_bytes.push(previous_block);
|
||||||
|
|
||||||
|
let _ = stream.write(&update_block_bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x08 => {
|
0x08 => {
|
||||||
@ -305,6 +334,9 @@ pub fn handle_client(
|
|||||||
|
|
||||||
current_player.id = SpecialPlayers::SelfPlayer as u8;
|
current_player.id = SpecialPlayers::SelfPlayer as u8;
|
||||||
}
|
}
|
||||||
|
let mut event = Event::new();
|
||||||
|
event.player = client_number;
|
||||||
|
extensions.run_event(EventType::PlayerLeave, event);
|
||||||
info!(
|
info!(
|
||||||
"Client {} disconnected, thread shutting down!",
|
"Client {} disconnected, thread shutting down!",
|
||||||
client_number
|
client_number
|
||||||
|
BIN
src/world.wrld
BIN
src/world.wrld
Binary file not shown.
Loading…
Reference in New Issue
Block a user