Compare commits

..

No commits in common. "a85742e5096dcf0cebe167c2b14b129521beba38" and "cfbb4f197c5fca5d17e02d49326b1e19a1ae5cb2" have entirely different histories.

6 changed files with 65 additions and 93 deletions

View File

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

View File

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

View File

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

View File

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

View File

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