From 18b2641d66227b364d3c8a00f759e978abf901c8 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Mon, 24 Oct 2022 16:03:56 +0000 Subject: [PATCH] Send correct dig packet for each version --- protocol/src/protocol/mod.rs | 35 +++++++++++++++++------ src/entity/mod.rs | 1 - src/entity/systems.rs | 55 +++++++++++++++++++++++++++--------- src/server/mod.rs | 41 ++++++++++++--------------- 4 files changed, 86 insertions(+), 46 deletions(-) diff --git a/protocol/src/protocol/mod.rs b/protocol/src/protocol/mod.rs index 043d180..33377f5 100644 --- a/protocol/src/protocol/mod.rs +++ b/protocol/src/protocol/mod.rs @@ -948,19 +948,36 @@ impl fmt::Debug for VarLong { impl Serializable for Position { fn read_from(buf: &mut R) -> Result { let pos = buf.read_u64::()?; - Ok(Position::new( - ((pos as i64) >> 38) as i32, - ((pos as i64) & 0xFFF) as i32, - ((pos as i64) << 26 >> 38) as i32, - )) + let protocol_version = current_protocol_version(); + if protocol_version < 477 { + Ok(Position::new( + ((pos as i64) >> 38) as i32, + (((pos as i64) >> 26) & 0xFFF) as i32, + ((pos as i64) << 38 >> 38) as i32, + )) + } else { + Ok(Position::new( + ((pos as i64) >> 38) as i32, + ((pos as i64) << 52 >> 52) as i32, + ((pos as i64) << 26 >> 38) as i32, + )) + } } fn write_to(&self, buf: &mut W) -> Result<(), Error> { - let pos = (((self.x as u64) & 0x3FFFFFF) << 38) - | ((self.y as u64) & 0xFFF) - | (((self.z as u64) & 0x3FFFFFF) << 12); + let pos; + let protocol_version = current_protocol_version(); + if protocol_version < 477 { + pos = (((self.x as u64) & 0x3FFFFFF) << 38) + | (((self.y as u64) & 0xFFF) << 26) + | ((self.z as u64) & 0x3FFFFFF); + } else { + pos = (((self.x as u64) & 0x3FFFFFF) << 38) + | ((self.y as u64) & 0xFFF) + | (((self.z as u64) & 0x3FFFFFF) << 12); + } buf.write_u64::(pos)?; - Result::Ok(()) + Ok(()) } } diff --git a/src/entity/mod.rs b/src/entity/mod.rs index 5e942b6..36696e6 100644 --- a/src/entity/mod.rs +++ b/src/entity/mod.rs @@ -179,7 +179,6 @@ pub struct DiggingState { pub struct Digging { pub last: Option, pub current: Option, - pub packets: std::collections::VecDeque, } impl Digging { diff --git a/src/entity/systems.rs b/src/entity/systems.rs index 8baf1c2..29a6222 100644 --- a/src/entity/systems.rs +++ b/src/entity/systems.rs @@ -1,4 +1,5 @@ -use std::collections::VecDeque; +use std::sync::Arc; +use std::sync::RwLock; use super::*; use crate::ecs; @@ -7,6 +8,7 @@ use crate::shared::Position as BPos; use crate::world; use cgmath::InnerSpace; use steven_protocol::protocol; +use steven_protocol::protocol::Conn; pub struct ApplyVelocity { filter: ecs::Filter, @@ -293,6 +295,7 @@ pub struct ApplyDigging { filter: ecs::Filter, mouse_buttons: ecs::Key, digging: ecs::Key, + conn: ecs::Key>>>, } impl ApplyDigging { @@ -303,11 +306,12 @@ impl ApplyDigging { filter: ecs::Filter::new().with(mouse_buttons).with(digging), mouse_buttons, digging, + conn: m.get_key(), } } fn send_packet(&self, - packets: &mut VecDeque, + conn: &mut Conn, target: &DiggingState, state: i32 ) { @@ -318,11 +322,28 @@ impl ApplyDigging { n => panic!("Invalid dig state {}", n), } - packets.push_back(packet::play::serverbound::PlayerDigging { - status: protocol::VarInt(state), - location: target.position, - face: target.face.index() as u8, - }); + match conn.protocol_version { + // 1.7.10 + 5 => conn.write_packet(packet::play::serverbound::PlayerDigging_u8_u8y { + status: state as u8, + x: target.position.x, + y: target.position.y as u8, + z: target.position.z, + face: target.face.index() as u8, + }).unwrap(), + // 1.8.9 or v15w39c + 47|74 => conn.write_packet(packet::play::serverbound::PlayerDigging_u8 { + status: state as u8, + location: target.position, + face: target.face.index() as u8, + }).unwrap(), + // 1.9+ + _ => conn.write_packet(packet::play::serverbound::PlayerDigging { + status: protocol::VarInt(state), + location: target.position, + face: target.face.index() as u8, + }).unwrap(), + } } fn next_state(&self, @@ -381,6 +402,15 @@ impl ecs::System for ApplyDigging { use crate::server::target::{trace_ray, test_block}; use cgmath::EuclideanSpace; + let world_entity = m.get_world(); + let mut conn = m.get_component(world_entity, self.conn).unwrap().write().unwrap(); + let conn = match conn.as_mut() { + Some(conn) => conn, + // Don't keep processing digging operations if the connection was + // closed. + None => return, + }; + let target = trace_ray( world, 4.0, @@ -392,7 +422,6 @@ impl ecs::System for ApplyDigging { for e in m.find(&self.filter) { let mouse_buttons = m.get_component(e, self.mouse_buttons).unwrap(); let digging = m.get_component_mut(e, self.digging).unwrap(); - let packets = &mut digging.packets; // Update last and current state std::mem::swap(&mut digging.last, &mut digging.current); @@ -401,21 +430,21 @@ impl ecs::System for ApplyDigging { // Handle digging packets match (&digging.last, &mut digging.current) { // Start the new digging operation. - (None, Some(current)) => self.send_packet(packets, current, 0), + (None, Some(current)) => self.send_packet(conn, current, 0), // Cancel the previous digging operation. - (Some(last), None) if !last.finished => self.send_packet(packets, last, 1), + (Some(last), None) if !last.finished => self.send_packet(conn, last, 1), // Move to digging a new block (Some(last), Some(current)) if last.position != current.position => { // Cancel the previous digging operation. if !current.finished { - self.send_packet(packets, last, 1); + self.send_packet(conn, last, 1); } // Start the new digging operation. - self.send_packet(packets, current, 0); + self.send_packet(conn, current, 0); }, // Finish the new digging operation. (Some(_), Some(current)) if !self.is_finished(current) && !current.finished => { - self.send_packet(packets, current, 2); + self.send_packet(conn, current, 2); current.finished = true; }, _ => {}, diff --git a/src/server/mod.rs b/src/server/mod.rs index 60860a2..e6c375c 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -41,7 +41,7 @@ pub mod target; pub struct Server { uuid: protocol::UUID, - conn: Option, + conn: Arc>>, protocol_version: i32, forge_mods: Vec, read_queue: Option>>, @@ -62,7 +62,6 @@ pub struct Server { game_info: ecs::Key, player_movement: ecs::Key, mouse_buttons: ecs::Key, - digging: ecs::Key, gravity: ecs::Key, position: ecs::Key, target_position: ecs::Key, @@ -170,7 +169,7 @@ impl Server { forge_mods, protocol::UUID::from_str(&val.uuid).unwrap(), resources, - Some(write), + Arc::new(RwLock::new(Some(write))), Some(rx), )); } @@ -187,7 +186,7 @@ impl Server { forge_mods, val.uuid, resources, - Some(write), + Arc::new(RwLock::new(Some(write))), Some(rx), )); } @@ -331,7 +330,7 @@ impl Server { forge_mods, uuid, resources, - Some(write), + Arc::new(RwLock::new(Some(write))), Some(rx), )) } @@ -359,7 +358,7 @@ impl Server { vec![], protocol::UUID::default(), resources, - None, + Arc::new(RwLock::new(None)), None, ); let mut rng = rand::thread_rng(); @@ -447,7 +446,7 @@ impl Server { forge_mods: Vec, uuid: protocol::UUID, resources: Arc>, - conn: Option, + conn: Arc>>, read_queue: Option>>, ) -> Server { let mut entities = ecs::Manager::new(); @@ -456,6 +455,7 @@ impl Server { let world_entity = entities.get_world(); let game_info = entities.get_key(); entities.add_component(world_entity, game_info, entity::GameInfo::new()); + entities.add_component(world_entity, entities.get_key(), conn.clone()); let version = resources.read().unwrap().version(); Server { @@ -480,7 +480,6 @@ impl Server { game_info, player_movement: entities.get_key(), mouse_buttons: entities.get_key(), - digging: entities.get_key(), gravity: entities.get_key(), position: entities.get_key(), target_position: entities.get_key(), @@ -504,7 +503,7 @@ impl Server { } pub fn disconnect(&mut self, reason: Option) { - self.conn = None; + self.conn.write().unwrap().take(); self.disconnect_reason = reason; if let Some(player) = self.player.take() { self.entities.remove_entity(player); @@ -513,7 +512,7 @@ impl Server { } pub fn is_connected(&self) -> bool { - self.conn.is_some() + self.conn.read().unwrap().is_some() } pub fn tick(&mut self, renderer: &mut render::Renderer, delta: f64) { @@ -659,12 +658,12 @@ impl Server { Err(err) => panic!("Err: {:?}", err), } // Disconnected - if self.conn.is_none() { + if self.conn.read().unwrap().is_none() { break; } } - if self.conn.is_some() { + if self.conn.read().unwrap().is_some() { self.read_queue = Some(rx); } } @@ -782,12 +781,6 @@ impl Server { }; self.write_packet(packet); } - - let digging = self.entities.get_component_mut(player, self.digging).unwrap(); - let packets = &mut digging.packets; - while let Some(packet) = packets.pop_front() { - self.write_packet(packet); - } } } @@ -931,8 +924,9 @@ impl Server { } } - pub fn write_packet(&mut self, p: T) { - let _ = self.conn.as_mut().unwrap().write_packet(p); // TODO handle errors + pub fn write_packet(&self, p: T) { + let mut conn = self.conn.write().unwrap(); + let _ = conn.as_mut().unwrap().write_packet(p); // TODO handle errors } fn on_keep_alive_i64( @@ -1079,12 +1073,13 @@ impl Server { // TODO: remove wrappers and directly call on Conn fn write_fmlhs_plugin_message(&mut self, msg: &forge::FmlHs) { - let _ = self.conn.as_mut().unwrap().write_fmlhs_plugin_message(msg); // TODO handle errors + let mut conn = self.conn.write().unwrap(); + let _ = conn.as_mut().unwrap().write_fmlhs_plugin_message(msg); // TODO handle errors } fn write_plugin_message(&mut self, channel: &str, data: &[u8]) { - let _ = self - .conn + let mut conn = self.conn.write().unwrap(); + let _ = conn .as_mut() .unwrap() .write_plugin_message(channel, data); // TODO handle errors