Send correct dig packet for each version

This commit is contained in:
Nathan Ruiz 2022-10-24 16:03:56 +00:00
parent 700a31013f
commit 18b2641d66
4 changed files with 86 additions and 46 deletions

View File

@ -948,19 +948,36 @@ impl fmt::Debug for VarLong {
impl Serializable for Position {
fn read_from<R: io::Read>(buf: &mut R) -> Result<Position, Error> {
let pos = buf.read_u64::<BigEndian>()?;
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<W: io::Write>(&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::<BigEndian>(pos)?;
Result::Ok(())
Ok(())
}
}

View File

@ -179,7 +179,6 @@ pub struct DiggingState {
pub struct Digging {
pub last: Option<DiggingState>,
pub current: Option<DiggingState>,
pub packets: std::collections::VecDeque<packet::play::serverbound::PlayerDigging>,
}
impl Digging {

View File

@ -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<MouseButtons>,
digging: ecs::Key<Digging>,
conn: ecs::Key<Arc<RwLock<Option<Conn>>>>,
}
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<packet::play::serverbound::PlayerDigging>,
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;
},
_ => {},

View File

@ -41,7 +41,7 @@ pub mod target;
pub struct Server {
uuid: protocol::UUID,
conn: Option<protocol::Conn>,
conn: Arc<RwLock<Option<protocol::Conn>>>,
protocol_version: i32,
forge_mods: Vec<forge::ForgeMod>,
read_queue: Option<mpsc::Receiver<Result<packet::Packet, protocol::Error>>>,
@ -62,7 +62,6 @@ pub struct Server {
game_info: ecs::Key<entity::GameInfo>,
player_movement: ecs::Key<entity::player::PlayerMovement>,
mouse_buttons: ecs::Key<entity::MouseButtons>,
digging: ecs::Key<entity::Digging>,
gravity: ecs::Key<entity::Gravity>,
position: ecs::Key<entity::Position>,
target_position: ecs::Key<entity::TargetPosition>,
@ -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<forge::ForgeMod>,
uuid: protocol::UUID,
resources: Arc<RwLock<resources::Manager>>,
conn: Option<protocol::Conn>,
conn: Arc<RwLock<Option<protocol::Conn>>>,
read_queue: Option<mpsc::Receiver<Result<packet::Packet, protocol::Error>>>,
) -> 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<format::Component>) {
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<T: protocol::PacketType>(&mut self, p: T) {
let _ = self.conn.as_mut().unwrap().write_packet(p); // TODO handle errors
pub fn write_packet<T: protocol::PacketType>(&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