mirror of
https://github.com/GIKExe/rust_mc_serv.git
synced 2025-06-25 10:52:58 +03:00
Compare commits
No commits in common. "a1b0da37d96bbae4a573891e81f118a0dc29f85f" and "a746a0d9b443191c14475852ade59425130dbc1a" have entirely different histories.
a1b0da37d9
...
a746a0d9b4
@ -1,3 +1,5 @@
|
|||||||
|
cargo-features = ["edition2024"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "rust_mc_serv"
|
name = "rust_mc_serv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -46,9 +46,7 @@ rust_mc_serv = { git = "https://github.com/GIKExe/rust_mc_serv.git" }
|
|||||||
let config = Arc::new(Config::default());
|
let config = Arc::new(Config::default());
|
||||||
let mut server = ServerContext::new(config);
|
let mut server = ServerContext::new(config);
|
||||||
|
|
||||||
// Добавляем дефолтную обработку режима Play
|
server.add_packet_handler(Box::new(PlayHandler)); // Добавляем дефолтную обработку режима Play
|
||||||
server.add_packet_handler(Box::new(PlayHandler));
|
|
||||||
server.add_listener(Box::new(PlayListener));
|
|
||||||
|
|
||||||
server.add_listener(Box::new(ExampleListener)); // Добавляем пример листенера
|
server.add_listener(Box::new(ExampleListener)); // Добавляем пример листенера
|
||||||
server.add_packet_handler(Box::new(ExamplePacketHandler)); // Добавляем пример пакет хандлера
|
server.add_packet_handler(Box::new(ExamplePacketHandler)); // Добавляем пример пакет хандлера
|
||||||
|
@ -38,7 +38,6 @@ impl ServerContext {
|
|||||||
self
|
self
|
||||||
.clients
|
.clients
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|o| o.entity_info_opt().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 +53,6 @@ impl ServerContext {
|
|||||||
self
|
self
|
||||||
.clients
|
.clients
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|o| o.entity_info_opt().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 +69,6 @@ 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())
|
|
||||||
.map(|o| o.clone())
|
.map(|o| o.clone())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use rust_mc_proto::{DataReader, DataWriter, Packet};
|
|||||||
|
|
||||||
use super::ServerError;
|
use super::ServerError;
|
||||||
|
|
||||||
pub mod component;
|
pub mod text_component;
|
||||||
|
|
||||||
// Трейт для чтения NBT-совместимых приколов
|
// Трейт для чтения NBT-совместимых приколов
|
||||||
pub trait ReadWriteNBT<T>: DataReader + DataWriter {
|
pub trait ReadWriteNBT<T>: DataReader + DataWriter {
|
||||||
|
@ -37,35 +37,6 @@ impl TextComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rainbow_offset(text: String, offset: i64) -> TextComponent {
|
|
||||||
if text.is_empty() {
|
|
||||||
return TextComponent::new(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
let children = text
|
|
||||||
.char_indices()
|
|
||||||
.map(|(i, c)| {
|
|
||||||
let hue = (((i as i64 + offset) % text.chars().count() as i64) as f32)
|
|
||||||
/ (text.chars().count() as f32)
|
|
||||||
* 360.0;
|
|
||||||
let hsl = Hsl::new(hue, 1.0, 0.5);
|
|
||||||
let rgb: Srgb = hsl.into_color();
|
|
||||||
let r = (rgb.red * 255.0).round() as u8;
|
|
||||||
let g = (rgb.green * 255.0).round() as u8;
|
|
||||||
let b = (rgb.blue * 255.0).round() as u8;
|
|
||||||
let mut component = TextComponent::new(c.to_string());
|
|
||||||
component.color = Some(format!("#{:02X}{:02X}{:02X}", r, g, b));
|
|
||||||
component
|
|
||||||
})
|
|
||||||
.collect::<Vec<TextComponent>>();
|
|
||||||
|
|
||||||
let mut parent = children[0].clone();
|
|
||||||
if children.len() > 1 {
|
|
||||||
parent.extra = Some(children[1..].to_vec());
|
|
||||||
}
|
|
||||||
parent
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rainbow(text: String) -> TextComponent {
|
pub fn rainbow(text: String) -> TextComponent {
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
return TextComponent::new(text);
|
return TextComponent::new(text);
|
@ -37,27 +37,9 @@ macro_rules! trigger_event {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Игнорирует результат листенеров
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! trigger_event_ignore {
|
|
||||||
($client:ident, $event:ident $(, $arg_ty:expr)* $(,)?) => {{
|
|
||||||
paste::paste! {
|
|
||||||
for handler in $client.server.listeners(
|
|
||||||
|o| o.[<on_ $event _priority>]()
|
|
||||||
).iter() {
|
|
||||||
let _ = handler.[<on_ $event>](
|
|
||||||
$client.clone()
|
|
||||||
$(, $arg_ty)*
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Listener: Sync + Send {
|
pub trait Listener: Sync + Send {
|
||||||
generate_handlers!(status, &mut String);
|
generate_handlers!(status, &mut String);
|
||||||
generate_handlers!(plugin_message, &str, &[u8]);
|
generate_handlers!(plugin_message, &str, &[u8]);
|
||||||
generate_handlers!(disconnect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PacketHandler: Sync + Send {
|
pub trait PacketHandler: Sync + Send {
|
||||||
|
@ -98,8 +98,6 @@ pub fn start_server(server: Arc<ServerContext>) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
trigger_event_ignore!(client, disconnect);
|
|
||||||
|
|
||||||
// Удаляем клиента из списка клиентов
|
// Удаляем клиента из списка клиентов
|
||||||
server.clients.remove(&client.addr);
|
server.clients.remove(&client.addr);
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ use rust_mc_serv::{
|
|||||||
ServerError,
|
ServerError,
|
||||||
config::Config,
|
config::Config,
|
||||||
context::ServerContext,
|
context::ServerContext,
|
||||||
data::component::TextComponent,
|
data::text_component::TextComponent,
|
||||||
event::{Listener, PacketHandler},
|
event::{Listener, PacketHandler},
|
||||||
play::{PlayHandler, PlayListener},
|
play::PlayHandler,
|
||||||
player::context::ClientContext,
|
player::context::ClientContext,
|
||||||
protocol::ConnectionState,
|
protocol::ConnectionState,
|
||||||
start_server,
|
start_server,
|
||||||
@ -154,9 +154,7 @@ fn main() {
|
|||||||
// Передается во все подключения
|
// Передается во все подключения
|
||||||
let mut server = ServerContext::new(config);
|
let mut server = ServerContext::new(config);
|
||||||
|
|
||||||
// Добавляем дефолтную обработку режима Play
|
server.add_packet_handler(Box::new(PlayHandler)); // Добавляем дефолтную обработку режима Play
|
||||||
server.add_packet_handler(Box::new(PlayHandler));
|
|
||||||
server.add_listener(Box::new(PlayListener));
|
|
||||||
|
|
||||||
server.add_listener(Box::new(ExampleListener)); // Добавляем пример листенера
|
server.add_listener(Box::new(ExampleListener)); // Добавляем пример листенера
|
||||||
server.add_packet_handler(Box::new(ExamplePacketHandler)); // Добавляем пример пакет хандлера
|
server.add_packet_handler(Box::new(ExamplePacketHandler)); // Добавляем пример пакет хандлера
|
||||||
|
@ -7,7 +7,7 @@ use rust_mc_proto::{DataReader, DataWriter, Packet};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerError,
|
ServerError,
|
||||||
data::{ReadWriteNBT, component::TextComponent},
|
data::{ReadWriteNBT, text_component::TextComponent},
|
||||||
player::context::ClientContext,
|
player::context::ClientContext,
|
||||||
protocol::packet_id::{clientbound, serverbound},
|
protocol::packet_id::{clientbound, serverbound},
|
||||||
};
|
};
|
||||||
@ -25,19 +25,6 @@ pub fn send_game_event(
|
|||||||
client.write_packet(&packet)
|
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 sync_player_pos(
|
pub fn sync_player_pos(
|
||||||
client: Arc<ClientContext>,
|
client: Arc<ClientContext>,
|
||||||
x: f64,
|
x: f64,
|
||||||
|
175
src/play/mod.rs
175
src/play/mod.rs
@ -3,16 +3,16 @@ use std::{sync::Arc, thread, time::Duration};
|
|||||||
|
|
||||||
use config::handle_configuration_state;
|
use config::handle_configuration_state;
|
||||||
use helper::{
|
use helper::{
|
||||||
send_entity_event, send_game_event, send_keep_alive, send_system_message, set_center_chunk,
|
send_game_event, send_keep_alive, send_system_message, set_center_chunk, sync_player_pos,
|
||||||
sync_player_pos, unload_chunk,
|
unload_chunk,
|
||||||
};
|
};
|
||||||
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::player::context::EntityInfo;
|
use crate::player::context::EntityInfo;
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerError, data::component::TextComponent, event::PacketHandler, player::context::ClientContext,
|
ServerError, data::text_component::TextComponent, event::PacketHandler,
|
||||||
|
player::context::ClientContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::protocol::{ConnectionState, packet_id::*};
|
use crate::protocol::{ConnectionState, packet_id::*};
|
||||||
@ -56,14 +56,6 @@ impl PacketHandler for PlayHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PlayListener;
|
|
||||||
|
|
||||||
impl Listener for PlayListener {
|
|
||||||
fn on_disconnect(&self, client: Arc<ClientContext>) -> Result<(), ServerError> {
|
|
||||||
handle_disconnect(client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_login(client: Arc<ClientContext>) -> Result<(), ServerError> {
|
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);
|
||||||
@ -127,7 +119,7 @@ pub fn send_example_chunk(client: Arc<ClientContext>, x: i32, z: i32) -> Result<
|
|||||||
|
|
||||||
// blocks paletted container
|
// blocks paletted container
|
||||||
chunk_data.write_byte(0)?; // Bits Per Entry, use Single valued palette format
|
chunk_data.write_byte(0)?; // Bits Per Entry, use Single valued palette format
|
||||||
chunk_data.write_varint(1)?; // block state id in the registry
|
chunk_data.write_varint(10)?; // block state id in the registry (1 for stone, 10 for dirt)
|
||||||
|
|
||||||
// biomes palleted container
|
// biomes palleted container
|
||||||
chunk_data.write_byte(0)?; // Bits Per Entry, use Single valued palette format
|
chunk_data.write_byte(0)?; // Bits Per Entry, use Single valued palette format
|
||||||
@ -195,27 +187,6 @@ pub fn send_example_chunks_in_distance(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_player(
|
|
||||||
receiver: Arc<ClientContext>,
|
|
||||||
player: Arc<ClientContext>,
|
|
||||||
) -> Result<(), ServerError> {
|
|
||||||
let mut packet = Packet::empty(clientbound::play::PLAYER_INFO_REMOVE);
|
|
||||||
|
|
||||||
packet.write_varint(1)?;
|
|
||||||
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().entity_id)?; // Entity ID
|
|
||||||
|
|
||||||
receiver.write_packet(&packet)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_player(
|
pub fn send_player(
|
||||||
receiver: Arc<ClientContext>,
|
receiver: Arc<ClientContext>,
|
||||||
player: Arc<ClientContext>,
|
player: Arc<ClientContext>,
|
||||||
@ -268,26 +239,18 @@ pub fn get_offline_uuid(name: &str) -> Uuid {
|
|||||||
Uuid::new_v3(&namespace, (&name[2..]).as_bytes())
|
Uuid::new_v3(&namespace, (&name[2..]).as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_rainbow_message(
|
|
||||||
client: &Arc<ClientContext>,
|
|
||||||
message: String,
|
|
||||||
) -> Result<(), ServerError> {
|
|
||||||
send_system_message(client.clone(), TextComponent::rainbow(message), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Отдельная функция для работы с самой игрой
|
// Отдельная функция для работы с самой игрой
|
||||||
pub fn handle_play_state(
|
pub fn handle_play_state(
|
||||||
client: Arc<ClientContext>, // Контекст клиента
|
client: Arc<ClientContext>, // Контекст клиента
|
||||||
) -> Result<(), ServerError> {
|
) -> Result<(), ServerError> {
|
||||||
let player_name = client.player_info().unwrap().name;
|
client.set_entity_info(EntityInfo::new(
|
||||||
let player_uuid = get_offline_uuid(&client.player_info().unwrap().name); // TODO: authenticated uuid
|
client
|
||||||
let entity_id = client
|
|
||||||
.server
|
.server
|
||||||
.world
|
.world
|
||||||
.entity_id_counter
|
.entity_id_counter
|
||||||
.fetch_add(1, Ordering::SeqCst);
|
.fetch_add(1, Ordering::SeqCst),
|
||||||
|
get_offline_uuid(&client.player_info().unwrap().name), // TODO: authenticated uuid
|
||||||
client.set_entity_info(EntityInfo::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().set_position((8.0, 0.0, 8.0)); // set 8 0 8 as position
|
||||||
|
|
||||||
@ -303,8 +266,6 @@ pub fn handle_play_state(
|
|||||||
send_login(client.clone())?;
|
send_login(client.clone())?;
|
||||||
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_game_event(client.clone(), 13, 0.0)?; // 13 - Start waiting for level chunks
|
send_game_event(client.clone(), 13, 0.0)?; // 13 - Start waiting for level chunks
|
||||||
// send_game_event(client.clone(), 3, 1.0)?; // 3 - Set gamemode, 1.0 - creative
|
|
||||||
send_entity_event(client.clone(), entity_id, 28)?; // 28 - give op level 4
|
|
||||||
set_center_chunk(client.clone(), 0, 0)?;
|
set_center_chunk(client.clone(), 0, 0)?;
|
||||||
|
|
||||||
let mut chunks = Vec::new();
|
let mut chunks = Vec::new();
|
||||||
@ -315,18 +276,24 @@ pub fn handle_play_state(
|
|||||||
|
|
||||||
// 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!("Your IP: {}", client.addr))?;
|
send_system_message(
|
||||||
// send_rainbow_message(
|
client.clone(),
|
||||||
// &client,
|
TextComponent::rainbow(format!("Your Name: {}", client.player_info().unwrap().name)),
|
||||||
// format!("Your brand: {}", client.client_info().unwrap().brand),
|
false,
|
||||||
// )?;
|
)?;
|
||||||
// send_rainbow_message(
|
send_system_message(
|
||||||
// &client,
|
client.clone(),
|
||||||
// format!("Your locale: {}", client.client_info().unwrap().locale),
|
TextComponent::rainbow(format!(
|
||||||
// )?;
|
"Your Entity ID: {}",
|
||||||
// send_rainbow_message(&client, format!("Your UUID: {}", client.entity_info().uuid))?;
|
client.entity_info().entity_id
|
||||||
// send_rainbow_message(&client, format!("Your Name: {}", &player_name))?;
|
)),
|
||||||
// send_rainbow_message(&client, format!("Your Entity ID: {}", entity_id))?;
|
false,
|
||||||
|
)?;
|
||||||
|
send_system_message(
|
||||||
|
client.clone(),
|
||||||
|
TextComponent::rainbow(format!("Your UUID: {}", client.entity_info().uuid)),
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
|
||||||
for player in client.server.players() {
|
for player in client.server.players() {
|
||||||
if client.addr == player.addr {
|
if client.addr == player.addr {
|
||||||
@ -334,7 +301,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))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::spawn({
|
thread::spawn({
|
||||||
@ -346,57 +312,9 @@ pub fn handle_play_state(
|
|||||||
serverbound::play::SET_PLAYER_POSITION,
|
serverbound::play::SET_PLAYER_POSITION,
|
||||||
serverbound::play::SET_PLAYER_POSITION_AND_ROTATION,
|
serverbound::play::SET_PLAYER_POSITION_AND_ROTATION,
|
||||||
serverbound::play::SET_PLAYER_ROTATION,
|
serverbound::play::SET_PLAYER_ROTATION,
|
||||||
serverbound::play::CHAT_MESSAGE,
|
|
||||||
serverbound::play::CLICK_CONTAINER,
|
|
||||||
serverbound::play::CHAT_COMMAND,
|
|
||||||
serverbound::play::SIGNED_CHAT_COMMAND,
|
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
match packet.id() {
|
match packet.id() {
|
||||||
serverbound::play::CLICK_CONTAINER => {
|
|
||||||
let _ = packet.read_varint()?; // window id
|
|
||||||
let _ = packet.read_varint()?; // state id
|
|
||||||
let slot = packet.read_short()?; // slot
|
|
||||||
let _ = packet.read_byte()?; // button
|
|
||||||
let _ = packet.read_varint()?; // mode
|
|
||||||
// i cannot read item slots now
|
|
||||||
|
|
||||||
send_rainbow_message(&client, format!("index clicked: {slot}"))?;
|
|
||||||
}
|
|
||||||
serverbound::play::CHAT_COMMAND | serverbound::play::SIGNED_CHAT_COMMAND => {
|
|
||||||
let command = packet.read_string()?;
|
|
||||||
|
|
||||||
if command == "gamemode creative" {
|
|
||||||
send_game_event(client.clone(), 3, 1.0)?; // 3 - Set gamemode
|
|
||||||
send_rainbow_message(&client, format!("gamemode creative installed"))?;
|
|
||||||
} else if command == "gamemode survival" {
|
|
||||||
send_game_event(client.clone(), 3, 0.0)?; // 3 - Set gamemode
|
|
||||||
send_rainbow_message(&client, format!("gamemode survival installed"))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serverbound::play::CHAT_MESSAGE => {
|
|
||||||
let message_text = packet.read_string()?;
|
|
||||||
// skip remaining data coz they suck
|
|
||||||
|
|
||||||
let mut message =
|
|
||||||
TextComponent::rainbow(format!("{} said: ", client.player_info().unwrap().name));
|
|
||||||
|
|
||||||
message.italic = Some(true);
|
|
||||||
|
|
||||||
let text_message = TextComponent::builder()
|
|
||||||
.color("white")
|
|
||||||
.text(&message_text)
|
|
||||||
.italic(false)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
if let Some(extra) = &mut message.extra {
|
|
||||||
extra.push(text_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
for player in client.server.players() {
|
|
||||||
send_system_message(player, message.clone(), false)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
serverbound::play::SET_PLAYER_POSITION => {
|
serverbound::play::SET_PLAYER_POSITION => {
|
||||||
let x = packet.read_double()?;
|
let x = packet.read_double()?;
|
||||||
let y = packet.read_double()?;
|
let y = packet.read_double()?;
|
||||||
@ -515,22 +433,15 @@ pub fn handle_play_state(
|
|||||||
|
|
||||||
// text animation
|
// text animation
|
||||||
{
|
{
|
||||||
if ticks_alive > 40 {
|
let animation_text = format!("Ticks alive: {} жёпа", ticks_alive);
|
||||||
let animation_text = format!(
|
let animation_index = ((ticks_alive + 40) % 300) as usize;
|
||||||
"жёпа .-.-.-.-.-.- Ticks passed during the aliveness of the connection: {} ticks (1/20 of second) -.-.-.-.-.-. жёпа",
|
let animation_end = animation_text.len() + 20;
|
||||||
ticks_alive
|
|
||||||
);
|
|
||||||
|
|
||||||
let now_length = ((ticks_alive - 40 + 1) as usize).min(animation_text.chars().count());
|
if animation_index < animation_end {
|
||||||
|
let now_length = (animation_index + 1).min(animation_text.chars().count());
|
||||||
let now_text = animation_text.chars().take(now_length).collect();
|
let now_text = animation_text.chars().take(now_length).collect();
|
||||||
|
|
||||||
let mut text = TextComponent::rainbow_offset(now_text, -(ticks_alive as i64));
|
send_system_message(client.clone(), TextComponent::rainbow(now_text), true)?;
|
||||||
|
|
||||||
text.bold = Some(true);
|
|
||||||
text.italic = Some(true);
|
|
||||||
text.underlined = Some(true);
|
|
||||||
|
|
||||||
send_system_message(client.clone(), text, true)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,21 +451,3 @@ pub fn handle_play_state(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_disconnect(
|
|
||||||
client: Arc<ClientContext>, // Контекст клиента
|
|
||||||
) -> Result<(), ServerError> {
|
|
||||||
for player in client.server.players() {
|
|
||||||
if client.addr == player.addr {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_player(player.clone(), client.clone())?;
|
|
||||||
send_rainbow_message(
|
|
||||||
&player,
|
|
||||||
format!("{} left the game", client.player_info().unwrap().name),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
@ -107,10 +107,6 @@ 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>> {
|
|
||||||
self.entity_info.read().unwrap().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn entity_info(self: &Arc<Self>) -> Arc<EntityInfo> {
|
pub fn entity_info(self: &Arc<Self>) -> Arc<EntityInfo> {
|
||||||
self.entity_info.read().unwrap().clone().unwrap()
|
self.entity_info.read().unwrap().clone().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use rust_mc_proto::{DataReader, DataWriter, Packet};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerError,
|
ServerError,
|
||||||
data::{ReadWriteNBT, component::TextComponent},
|
data::{ReadWriteNBT, text_component::TextComponent},
|
||||||
protocol::{
|
protocol::{
|
||||||
packet_id::{clientbound, serverbound},
|
packet_id::{clientbound, serverbound},
|
||||||
*,
|
*,
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
use std::{
|
use std::{io::Read, sync::Arc};
|
||||||
io::{Cursor, Read},
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ServerError,
|
ServerError,
|
||||||
@ -132,7 +129,7 @@ pub fn handle_connection(
|
|||||||
packet.get_mut().read_to_end(&mut data).unwrap();
|
packet.get_mut().read_to_end(&mut data).unwrap();
|
||||||
|
|
||||||
if identifier == "minecraft:brand" {
|
if identifier == "minecraft:brand" {
|
||||||
break Cursor::new(data).read_string()?;
|
break String::from_utf8_lossy(&data).to_string();
|
||||||
} else {
|
} else {
|
||||||
trigger_event!(client, plugin_message, &identifier, &data);
|
trigger_event!(client, plugin_message, &identifier, &data);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user