Compare commits

...

2 Commits

Author SHA1 Message Date
a85742e509 hand swing animation + remove unwrap in the context.rs file 2025-05-10 00:32:46 +03:00
f25dc272a0 remove sounds 2025-05-10 00:01:26 +03:00
6 changed files with 93 additions and 65 deletions

View File

@ -38,7 +38,7 @@ impl ServerContext {
self self
.clients .clients
.iter() .iter()
.filter(|o| o.entity_info_opt().is_some()) .filter(|o| o.entity_info().is_some())
.find(|o| { .find(|o| {
let info = o.player_info(); let info = o.player_info();
if let Some(info) = info { if let Some(info) = info {
@ -54,7 +54,7 @@ impl ServerContext {
self self
.clients .clients
.iter() .iter()
.filter(|o| o.entity_info_opt().is_some()) .filter(|o| o.entity_info().is_some())
.find(|o| { .find(|o| {
let info = o.player_info(); let info = o.player_info();
if let Some(info) = info { if let Some(info) = info {
@ -71,7 +71,7 @@ impl ServerContext {
.clients .clients
.iter() .iter()
.filter(|o| o.player_info().is_some()) .filter(|o| o.player_info().is_some())
.filter(|o| o.entity_info_opt().is_some()) .filter(|o| o.entity_info().is_some())
.map(|o| o.clone()) .map(|o| o.clone())
.collect() .collect()
} }

View File

@ -6,6 +6,7 @@ use rust_mc_proto::{DataReader, DataWriter, Packet};
use super::ServerError; use super::ServerError;
pub mod component; pub mod component;
pub mod slot;
// Трейт для чтения NBT-совместимых приколов // Трейт для чтения NBT-совместимых приколов
pub trait ReadWriteNBT<T>: DataReader + DataWriter { pub trait ReadWriteNBT<T>: DataReader + DataWriter {

23
src/data/slot.rs Normal file
View File

@ -0,0 +1,23 @@
use rust_mc_proto::{DataReader, DataWriter};
use crate::ServerError;
pub struct Slot {
// TODO: write fields
}
pub trait ReadWriteSlot: DataReader + DataWriter {
fn read_slot(&mut self) -> Result<Slot, ServerError>;
fn write_slot(&mut self, val: Slot) -> Result<(), ServerError>;
}
pub struct HashedSlot {
// TODO: write fields
}
pub trait ReadWriteHashedSlot: DataReader + DataWriter {
fn read_hashed_slot(&mut self) -> Result<HashedSlot, ServerError>;
fn write_hashed_slot(&mut self, val: HashedSlot) -> Result<(), ServerError>;
}
// TODO: implement traits for packet

View File

@ -53,7 +53,13 @@ pub fn send_entity_animation(
Ok(()) Ok(())
} }
pub fn play_sound(receiver: Arc<ClientContext>, sound: String) -> Result<(), ServerError> { 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 mut packet = Packet::empty(clientbound::play::ENTITY_SOUND_EFFECT);
let timestamp = SystemTime::now() let timestamp = SystemTime::now()
@ -65,10 +71,10 @@ pub fn play_sound(receiver: Arc<ClientContext>, sound: String) -> Result<(), Ser
packet.write_string(&sound)?; packet.write_string(&sound)?;
packet.write_boolean(false)?; // is fixed range packet.write_boolean(false)?; // is fixed range
// packet.write_float(0.0)?; // fixed range // packet.write_float(0.0)?; // fixed range
packet.write_varint(receiver.entity_info().entity_id)?; packet.write_varint(receiver.entity_info().unwrap().entity_id)?;
packet.write_varint(0)?; // sound category (0 - master) packet.write_varint(category)?; // sound category (0 - master)
packet.write_float(1.0)?; // volume packet.write_float(volume)?; // volume
packet.write_float(1.0)?; // pitch packet.write_float(pitch)?; // pitch
packet.write_long(timestamp)?; // seed packet.write_long(timestamp)?; // seed
receiver.write_packet(&packet)?; receiver.write_packet(&packet)?;

View File

@ -3,14 +3,15 @@ use std::{sync::Arc, thread, time::Duration};
use config::handle_configuration_state; use config::handle_configuration_state;
use helper::{ use helper::{
play_sound, send_entity_event, send_game_event, send_keep_alive, send_system_message, send_entity_animation, send_entity_event, send_game_event, send_keep_alive, send_system_message,
set_center_chunk, sync_player_pos, unload_chunk, set_center_chunk, sync_player_pos, unload_chunk,
}; };
use log::debug;
use rust_mc_proto::{DataReader, DataWriter, Packet}; use rust_mc_proto::{DataReader, DataWriter, Packet};
use uuid::Uuid; use uuid::Uuid;
use crate::event::Listener; use crate::event::Listener;
use crate::player::context::EntityInfo; use crate::player::context::PlayerEntityInfo;
use crate::{ use crate::{
ServerError, data::component::TextComponent, event::PacketHandler, player::context::ClientContext, ServerError, data::component::TextComponent, event::PacketHandler, player::context::ClientContext,
}; };
@ -68,7 +69,7 @@ pub fn send_login(client: Arc<ClientContext>) -> Result<(), ServerError> {
// Отправка пакета Login // Отправка пакета Login
let mut packet = Packet::empty(clientbound::play::LOGIN); let mut packet = Packet::empty(clientbound::play::LOGIN);
packet.write_int(client.entity_info().entity_id)?; // Entity ID packet.write_int(client.entity_info().unwrap().entity_id)?; // Entity ID
packet.write_boolean(false)?; // Is hardcore packet.write_boolean(false)?; // Is hardcore
packet.write_varint(4)?; // Dimension Names packet.write_varint(4)?; // Dimension Names
packet.write_string("minecraft:overworld")?; packet.write_string("minecraft:overworld")?;
@ -202,14 +203,14 @@ pub fn remove_player(
let mut packet = Packet::empty(clientbound::play::PLAYER_INFO_REMOVE); let mut packet = Packet::empty(clientbound::play::PLAYER_INFO_REMOVE);
packet.write_varint(1)?; packet.write_varint(1)?;
packet.write_uuid(&player.entity_info().uuid)?; packet.write_uuid(&player.entity_info().unwrap().uuid)?;
receiver.write_packet(&packet)?; receiver.write_packet(&packet)?;
let mut packet = Packet::empty(clientbound::play::REMOVE_ENTITIES); let mut packet = Packet::empty(clientbound::play::REMOVE_ENTITIES);
packet.write_varint(1)?; packet.write_varint(1)?;
packet.write_varint(player.entity_info().entity_id)?; // Entity ID packet.write_varint(player.entity_info().unwrap().entity_id)?; // Entity ID
receiver.write_packet(&packet)?; receiver.write_packet(&packet)?;
@ -224,7 +225,7 @@ pub fn send_player(
packet.write_byte(0x01)?; // only Add Player packet.write_byte(0x01)?; // only Add Player
packet.write_varint(1)?; // players list packet.write_varint(1)?; // players list
packet.write_uuid(&player.entity_info().uuid)?; // player uuid packet.write_uuid(&player.entity_info().unwrap().uuid)?; // player uuid
packet.write_string(&player.player_info().unwrap().name)?; // player name packet.write_string(&player.player_info().unwrap().name)?; // player name
packet.write_varint(0)?; // no properties packet.write_varint(0)?; // no properties
@ -232,12 +233,12 @@ pub fn send_player(
let mut packet = Packet::empty(clientbound::play::SPAWN_ENTITY); let mut packet = Packet::empty(clientbound::play::SPAWN_ENTITY);
let (x, y, z) = player.entity_info().position(); let (x, y, z) = player.entity_info().unwrap().position();
let (yaw, pitch) = player.entity_info().rotation(); let (yaw, pitch) = player.entity_info().unwrap().rotation();
let (vel_x, vel_y, vel_z) = player.entity_info().velocity(); let (vel_x, vel_y, vel_z) = player.entity_info().unwrap().velocity();
packet.write_varint(player.entity_info().entity_id)?; // Entity ID packet.write_varint(player.entity_info().unwrap().entity_id)?; // Entity ID
packet.write_uuid(&player.entity_info().uuid)?; // Entity UUID packet.write_uuid(&player.entity_info().unwrap().uuid)?; // Entity UUID
packet.write_varint(148)?; // Entity type TODO: move to const packet.write_varint(148)?; // Entity type TODO: move to const
packet.write_double(x)?; packet.write_double(x)?;
packet.write_double(y)?; packet.write_double(y)?;
@ -287,9 +288,9 @@ pub fn handle_play_state(
.entity_id_counter .entity_id_counter
.fetch_add(1, Ordering::SeqCst); .fetch_add(1, Ordering::SeqCst);
client.set_entity_info(EntityInfo::new(entity_id, player_uuid)); client.set_entity_info(PlayerEntityInfo::new(entity_id, player_uuid));
client.entity_info().set_position((8.0, 0.0, 8.0)); // set 8 0 8 as position client.entity_info().unwrap().set_position((8.0, 0.0, 8.0)); // set 8 0 8 as position
thread::spawn({ thread::spawn({
let client = client.clone(); let client = client.clone();
@ -335,7 +336,6 @@ pub fn handle_play_state(
send_player(client.clone(), player.clone())?; send_player(client.clone(), player.clone())?;
send_player(player.clone(), client.clone())?; send_player(player.clone(), client.clone())?;
send_rainbow_message(&player, format!("{} joined the game", player_name))?; send_rainbow_message(&player, format!("{} joined the game", player_name))?;
play_sound(player.clone(), format!("minecraft:block.bell.use"))?;
} }
thread::spawn({ thread::spawn({
@ -352,6 +352,7 @@ pub fn handle_play_state(
serverbound::play::CHAT_COMMAND, serverbound::play::CHAT_COMMAND,
serverbound::play::SIGNED_CHAT_COMMAND, serverbound::play::SIGNED_CHAT_COMMAND,
serverbound::play::PLAYER_COMMAND, serverbound::play::PLAYER_COMMAND,
serverbound::play::SWING_ARM,
])?; ])?;
match packet.id() { match packet.id() {
@ -365,6 +366,25 @@ pub fn handle_play_state(
send_rainbow_message(&client, format!("index clicked: {slot}"))?; send_rainbow_message(&client, format!("index clicked: {slot}"))?;
} }
serverbound::play::SWING_ARM => {
let hand = packet.read_varint()?; // hand (0 - main, 1 - off)
send_rainbow_message(&client, format!("hand swinged: {hand}"))?;
let animation = match hand {
0 => 0, // 0 - mainhand swing animatiom
1 => 3, // 3 - offhand swing animatiom
_ => continue,
};
for player in client.server.players() {
if client.addr == player.addr {
continue;
}
send_entity_animation(player, client.entity_info().unwrap().entity_id, animation)?;
}
}
serverbound::play::PLAYER_COMMAND => { serverbound::play::PLAYER_COMMAND => {
let _ = packet.read_varint()?; // entity id let _ = packet.read_varint()?; // entity id
let action = packet.read_varint()?; // action id let action = packet.read_varint()?; // action id
@ -372,9 +392,6 @@ pub fn handle_play_state(
if action == 0 { if action == 0 {
// press sneak key // press sneak key
for player in client.server.players() {
play_sound(player.clone(), format!("minecraft:block.bell.use"))?;
}
} else if action == 1 { } else if action == 1 {
// release sneak key // release sneak key
} }
@ -385,25 +402,12 @@ pub fn handle_play_state(
if command == "gamemode creative" { if command == "gamemode creative" {
send_game_event(client.clone(), 3, 1.0)?; // 3 - Set gamemode send_game_event(client.clone(), 3, 1.0)?; // 3 - Set gamemode
send_rainbow_message(&client, format!("gamemode creative installed"))?; send_rainbow_message(&client, format!("gamemode creative installed"))?;
play_sound(client.clone(), format!("minecraft:block.bell.use"))?;
} else if command == "gamemode survival" { } else if command == "gamemode survival" {
send_game_event(client.clone(), 3, 0.0)?; // 3 - Set gamemode send_game_event(client.clone(), 3, 0.0)?; // 3 - Set gamemode
send_rainbow_message(&client, format!("gamemode survival installed"))?; send_rainbow_message(&client, format!("gamemode survival installed"))?;
play_sound(client.clone(), format!("minecraft:block.bell.use"))?; } else if command == "kill" {
} else if command == "help" {
send_rainbow_message(&client, format!("/gamemode creative"))?;
send_rainbow_message(&client, format!("/gamemode survival"))?;
send_rainbow_message(&client, format!("/help"))?;
send_rainbow_message(&client, format!("/reset"))?;
} else if command == "reset" {
sync_player_pos(client.clone(), 8.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0)?; sync_player_pos(client.clone(), 8.0, 0.0, 8.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0)?;
send_rainbow_message(&client, format!("reseteed"))?; send_rainbow_message(&client, format!("killed"))?;
} else {
send_rainbow_message(&client, format!("use command /help to see my commands bro"))?;
for _ in 0..10 {
play_sound(client.clone(), format!("minecraft:block.bell.use"))?;
thread::sleep(Duration::from_millis(50));
}
} }
} }
serverbound::play::CHAT_MESSAGE => { serverbound::play::CHAT_MESSAGE => {
@ -427,7 +431,6 @@ pub fn handle_play_state(
for player in client.server.players() { for player in client.server.players() {
send_system_message(player.clone(), message.clone(), false)?; send_system_message(player.clone(), message.clone(), false)?;
play_sound(player.clone(), format!("minecraft:block.bell.use"))?;
} }
} }
serverbound::play::SET_PLAYER_POSITION => { serverbound::play::SET_PLAYER_POSITION => {
@ -436,7 +439,7 @@ pub fn handle_play_state(
let z = packet.read_double()?; let z = packet.read_double()?;
let flags = packet.read_byte()?; // flags let flags = packet.read_byte()?; // flags
let prev = client.entity_info().position(); let prev = client.entity_info().unwrap().position();
for player in client.server.players() { for player in client.server.players() {
if client.addr == player.addr { if client.addr == player.addr {
@ -444,7 +447,7 @@ pub fn handle_play_state(
} }
let mut packet = Packet::empty(clientbound::play::UPDATE_ENTITY_POSITION); let mut packet = Packet::empty(clientbound::play::UPDATE_ENTITY_POSITION);
packet.write_varint(client.entity_info().entity_id)?; packet.write_varint(client.entity_info().unwrap().entity_id)?;
packet.write_short((x * 4096.0 - prev.0 * 4096.0) as i16)?; // formula: currentX * 4096 - prevX * 4096 packet.write_short((x * 4096.0 - prev.0 * 4096.0) as i16)?; // formula: currentX * 4096 - prevX * 4096
packet.write_short((y * 4096.0 - prev.1 * 4096.0) as i16)?; packet.write_short((y * 4096.0 - prev.1 * 4096.0) as i16)?;
packet.write_short((z * 4096.0 - prev.2 * 4096.0) as i16)?; packet.write_short((z * 4096.0 - prev.2 * 4096.0) as i16)?;
@ -452,7 +455,7 @@ pub fn handle_play_state(
player.write_packet(&packet)?; player.write_packet(&packet)?;
} }
client.entity_info().set_position((x, y, z)); client.entity_info().unwrap().set_position((x, y, z));
} }
serverbound::play::SET_PLAYER_POSITION_AND_ROTATION => { serverbound::play::SET_PLAYER_POSITION_AND_ROTATION => {
let x = packet.read_double()?; let x = packet.read_double()?;
@ -462,7 +465,7 @@ pub fn handle_play_state(
let pitch = packet.read_float()?; let pitch = packet.read_float()?;
let flags = packet.read_byte()?; // flags let flags = packet.read_byte()?; // flags
let prev = client.entity_info().position(); let prev = client.entity_info().unwrap().position();
for player in client.server.players() { for player in client.server.players() {
if client.addr == player.addr { if client.addr == player.addr {
@ -471,7 +474,7 @@ pub fn handle_play_state(
let mut packet = let mut packet =
Packet::empty(clientbound::play::UPDATE_ENTITY_POSITION_AND_ROTATION); Packet::empty(clientbound::play::UPDATE_ENTITY_POSITION_AND_ROTATION);
packet.write_varint(client.entity_info().entity_id)?; packet.write_varint(client.entity_info().unwrap().entity_id)?;
packet.write_short((x * 4096.0 - prev.0 * 4096.0) as i16)?; // formula: currentX * 4096 - prevX * 4096 packet.write_short((x * 4096.0 - prev.0 * 4096.0) as i16)?; // formula: currentX * 4096 - prevX * 4096
packet.write_short((y * 4096.0 - prev.1 * 4096.0) as i16)?; packet.write_short((y * 4096.0 - prev.1 * 4096.0) as i16)?;
packet.write_short((z * 4096.0 - prev.2 * 4096.0) as i16)?; packet.write_short((z * 4096.0 - prev.2 * 4096.0) as i16)?;
@ -481,13 +484,13 @@ pub fn handle_play_state(
player.write_packet(&packet)?; player.write_packet(&packet)?;
let mut packet = Packet::empty(clientbound::play::SET_HEAD_ROTATION); let mut packet = Packet::empty(clientbound::play::SET_HEAD_ROTATION);
packet.write_varint(client.entity_info().entity_id)?; packet.write_varint(client.entity_info().unwrap().entity_id)?;
packet.write_signed_byte((yaw / 360.0 * 256.0) as i8)?; packet.write_signed_byte((yaw / 360.0 * 256.0) as i8)?;
player.write_packet(&packet)?; player.write_packet(&packet)?;
} }
client.entity_info().set_position((x, y, z)); client.entity_info().unwrap().set_position((x, y, z));
client.entity_info().set_rotation((yaw, pitch)); client.entity_info().unwrap().set_rotation((yaw, pitch));
} }
serverbound::play::SET_PLAYER_ROTATION => { serverbound::play::SET_PLAYER_ROTATION => {
let yaw = packet.read_float()?; let yaw = packet.read_float()?;
@ -500,19 +503,19 @@ pub fn handle_play_state(
} }
let mut packet = Packet::empty(clientbound::play::UPDATE_ENTITY_ROTATION); let mut packet = Packet::empty(clientbound::play::UPDATE_ENTITY_ROTATION);
packet.write_varint(client.entity_info().entity_id)?; packet.write_varint(client.entity_info().unwrap().entity_id)?;
packet.write_signed_byte((yaw / 360.0 * 256.0) as i8)?; packet.write_signed_byte((yaw / 360.0 * 256.0) as i8)?;
packet.write_signed_byte((pitch / 360.0 * 256.0) as i8)?; packet.write_signed_byte((pitch / 360.0 * 256.0) as i8)?;
packet.write_boolean(flags & 0x01 != 0)?; packet.write_boolean(flags & 0x01 != 0)?;
player.write_packet(&packet)?; player.write_packet(&packet)?;
let mut packet = Packet::empty(clientbound::play::SET_HEAD_ROTATION); let mut packet = Packet::empty(clientbound::play::SET_HEAD_ROTATION);
packet.write_varint(client.entity_info().entity_id)?; packet.write_varint(client.entity_info().unwrap().entity_id)?;
packet.write_signed_byte((yaw / 360.0 * 256.0) as i8)?; packet.write_signed_byte((yaw / 360.0 * 256.0) as i8)?;
player.write_packet(&packet)?; player.write_packet(&packet)?;
} }
client.entity_info().set_rotation((yaw, pitch)); client.entity_info().unwrap().set_rotation((yaw, pitch));
} }
_ => {} _ => {}
} }
@ -532,7 +535,7 @@ pub fn handle_play_state(
if ticks_alive % 20 == 0 { if ticks_alive % 20 == 0 {
// 1 sec timer // 1 sec timer
let (x, _, z) = client.entity_info().position(); let (x, _, z) = client.entity_info().unwrap().position();
let (chunk_x, chunk_z) = ((x / 16.0) as i64, (z / 16.0) as i64); let (chunk_x, chunk_z) = ((x / 16.0) as i64, (z / 16.0) as i64);
let (chunk_x, chunk_z) = (chunk_x as i32, chunk_z as i32); let (chunk_x, chunk_z) = (chunk_x as i32, chunk_z as i32);
@ -580,7 +583,6 @@ pub fn handle_disconnect(
&player, &player,
format!("{} left the game", client.player_info().unwrap().name), format!("{} left the game", client.player_info().unwrap().name),
)?; )?;
play_sound(player.clone(), format!("minecraft:block.bell.use"))?;
} }
Ok(()) Ok(())

View File

@ -29,7 +29,7 @@ pub struct ClientContext {
packet_buffer: Mutex<VecDeque<Packet>>, packet_buffer: Mutex<VecDeque<Packet>>,
read_loop: AtomicBool, read_loop: AtomicBool,
is_alive: AtomicBool, is_alive: AtomicBool,
entity_info: RwLock<Option<Arc<EntityInfo>>>, entity_info: RwLock<Option<Arc<PlayerEntityInfo>>>,
} }
// Реализуем сравнение через адрес // Реализуем сравнение через адрес
@ -77,7 +77,7 @@ impl ClientContext {
*self.player_info.write().unwrap() = Some(player_info); *self.player_info.write().unwrap() = Some(player_info);
} }
pub fn set_entity_info(self: &Arc<Self>, entity_info: EntityInfo) { pub fn set_entity_info(self: &Arc<Self>, entity_info: PlayerEntityInfo) {
*self.entity_info.write().unwrap() = Some(Arc::new(entity_info)); *self.entity_info.write().unwrap() = Some(Arc::new(entity_info));
} }
@ -107,14 +107,10 @@ impl ClientContext {
self.player_info.read().unwrap().clone() self.player_info.read().unwrap().clone()
} }
pub fn entity_info_opt(self: &Arc<Self>) -> Option<Arc<EntityInfo>> { pub fn entity_info(self: &Arc<Self>) -> Option<Arc<PlayerEntityInfo>> {
self.entity_info.read().unwrap().clone() self.entity_info.read().unwrap().clone()
} }
pub fn entity_info(self: &Arc<Self>) -> Arc<EntityInfo> {
self.entity_info.read().unwrap().clone().unwrap()
}
pub fn state(self: &Arc<Self>) -> ConnectionState { pub fn state(self: &Arc<Self>) -> ConnectionState {
self.state.read().unwrap().clone() self.state.read().unwrap().clone()
} }
@ -289,7 +285,7 @@ pub struct PlayerInfo {
pub uuid: Uuid, pub uuid: Uuid,
} }
pub struct EntityInfo { pub struct PlayerEntityInfo {
pub entity_id: i32, pub entity_id: i32,
pub uuid: Uuid, pub uuid: Uuid,
position: RwLock<(f64, f64, f64)>, position: RwLock<(f64, f64, f64)>,
@ -297,9 +293,9 @@ pub struct EntityInfo {
rotation: RwLock<(f32, f32)>, rotation: RwLock<(f32, f32)>,
} }
impl EntityInfo { impl PlayerEntityInfo {
pub fn new(entity_id: i32, uuid: Uuid) -> EntityInfo { pub fn new(entity_id: i32, uuid: Uuid) -> PlayerEntityInfo {
EntityInfo { PlayerEntityInfo {
entity_id, entity_id,
uuid, uuid,
position: RwLock::new((0.0, 0.0, 0.0)), position: RwLock::new((0.0, 0.0, 0.0)),