167 lines
3.9 KiB
Rust
167 lines
3.9 KiB
Rust
use std::{
|
|
sync::Arc,
|
|
time::{SystemTime, UNIX_EPOCH},
|
|
};
|
|
|
|
use rust_mc_proto::{DataReader, DataWriter, Packet};
|
|
|
|
use crate::{
|
|
ServerError,
|
|
data::{ReadWriteNBT, component::TextComponent},
|
|
player::context::ClientContext,
|
|
protocol::packet_id::{clientbound, serverbound},
|
|
};
|
|
|
|
pub fn send_game_event(
|
|
client: Arc<ClientContext>,
|
|
event: u8,
|
|
value: f32,
|
|
) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::GAME_EVENT);
|
|
|
|
packet.write_byte(event)?;
|
|
packet.write_float(value)?;
|
|
|
|
client.write_packet(&packet)
|
|
}
|
|
|
|
pub fn send_entity_event(
|
|
client: Arc<ClientContext>,
|
|
entity_id: i32,
|
|
status: u8,
|
|
) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::ENTITY_EVENT);
|
|
|
|
packet.write_int(entity_id)?;
|
|
packet.write_byte(status)?;
|
|
|
|
client.write_packet(&packet)
|
|
}
|
|
|
|
pub fn send_entity_animation(
|
|
receiver: Arc<ClientContext>,
|
|
entity_id: i32,
|
|
animation: u8,
|
|
) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::ENTITY_ANIMATION);
|
|
|
|
packet.write_varint(entity_id)?;
|
|
packet.write_byte(animation)?;
|
|
|
|
receiver.write_packet(&packet)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn play_global_sound(
|
|
receiver: Arc<ClientContext>,
|
|
sound: String,
|
|
volume: f32,
|
|
pitch: f32,
|
|
category: i32,
|
|
) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::ENTITY_SOUND_EFFECT);
|
|
|
|
let timestamp = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_micros() as i64;
|
|
|
|
packet.write_varint(0)?;
|
|
packet.write_string(&sound)?;
|
|
packet.write_boolean(false)?; // is fixed range
|
|
// packet.write_float(0.0)?; // fixed range
|
|
packet.write_varint(receiver.entity_info().unwrap().entity_id)?;
|
|
packet.write_varint(category)?; // sound category (0 - master)
|
|
packet.write_float(volume)?; // volume
|
|
packet.write_float(pitch)?; // pitch
|
|
packet.write_long(timestamp)?; // seed
|
|
|
|
receiver.write_packet(&packet)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn sync_player_pos(
|
|
client: Arc<ClientContext>,
|
|
x: f64,
|
|
y: f64,
|
|
z: f64,
|
|
vel_x: f64,
|
|
vel_y: f64,
|
|
vel_z: f64,
|
|
yaw: f32,
|
|
pitch: f32,
|
|
flags: i32,
|
|
) -> Result<(), ServerError> {
|
|
let timestamp = (SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_millis()
|
|
& 0xFFFFFFFF) as i32;
|
|
|
|
let mut packet = Packet::empty(clientbound::play::SYNCHRONIZE_PLAYER_POSITION);
|
|
|
|
packet.write_varint(timestamp)?;
|
|
packet.write_double(x)?;
|
|
packet.write_double(y)?;
|
|
packet.write_double(z)?;
|
|
packet.write_double(vel_x)?;
|
|
packet.write_double(vel_y)?;
|
|
packet.write_double(vel_z)?;
|
|
packet.write_float(yaw)?;
|
|
packet.write_float(pitch)?;
|
|
packet.write_int(flags)?;
|
|
|
|
client.write_packet(&packet)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn set_center_chunk(client: Arc<ClientContext>, x: i32, z: i32) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::SET_CENTER_CHUNK);
|
|
|
|
packet.write_varint(x)?;
|
|
packet.write_varint(z)?;
|
|
|
|
client.write_packet(&packet)
|
|
}
|
|
|
|
pub fn send_keep_alive(client: Arc<ClientContext>) -> Result<(), ServerError> {
|
|
let timestamp = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_secs() as i64;
|
|
|
|
let mut packet = Packet::empty(clientbound::play::KEEP_ALIVE);
|
|
packet.write_long(timestamp)?;
|
|
client.write_packet(&packet)?;
|
|
|
|
let mut packet = client.read_packet(&[serverbound::play::KEEP_ALIVE])?;
|
|
let timestamp2 = packet.read_long()?;
|
|
if timestamp2 != timestamp {
|
|
// Послать клиента нахуй
|
|
Err(ServerError::WrongPacket)
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub fn send_system_message(
|
|
client: Arc<ClientContext>,
|
|
message: TextComponent,
|
|
is_action_bar: bool,
|
|
) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::SYSTEM_CHAT_MESSAGE);
|
|
packet.write_nbt(&message)?;
|
|
packet.write_boolean(is_action_bar)?;
|
|
client.write_packet(&packet)
|
|
}
|
|
|
|
pub fn unload_chunk(client: Arc<ClientContext>, x: i32, z: i32) -> Result<(), ServerError> {
|
|
let mut packet = Packet::empty(clientbound::play::UNLOAD_CHUNK);
|
|
packet.write_int(z)?;
|
|
packet.write_int(x)?;
|
|
client.write_packet(&packet)
|
|
}
|