mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
add keep alive packets
This commit is contained in:
8
pumpkin-protocol/src/client/play/c_keep_alive.rs
Normal file
8
pumpkin-protocol/src/client/play/c_keep_alive.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use pumpkin_macros::packet;
|
||||
use serde::Serialize;
|
||||
|
||||
#[packet(0x26)]
|
||||
#[derive(Serialize)]
|
||||
pub struct CKeepAlive {
|
||||
pub keep_alive_id: i64,
|
||||
}
|
||||
@@ -14,6 +14,7 @@ mod c_entity_velocity;
|
||||
mod c_game_event;
|
||||
mod c_head_rot;
|
||||
mod c_hurt_animation;
|
||||
mod c_keep_alive;
|
||||
mod c_login;
|
||||
mod c_open_screen;
|
||||
mod c_particle;
|
||||
@@ -57,6 +58,7 @@ pub use c_entity_velocity::*;
|
||||
pub use c_game_event::*;
|
||||
pub use c_head_rot::*;
|
||||
pub use c_hurt_animation::*;
|
||||
pub use c_keep_alive::*;
|
||||
pub use c_login::*;
|
||||
pub use c_open_screen::*;
|
||||
pub use c_particle::*;
|
||||
|
||||
@@ -5,6 +5,7 @@ mod s_client_information;
|
||||
mod s_close_container;
|
||||
mod s_confirm_teleport;
|
||||
mod s_interact;
|
||||
mod s_keep_alive;
|
||||
mod s_ping_request;
|
||||
mod s_player_action;
|
||||
mod s_player_command;
|
||||
@@ -25,6 +26,7 @@ pub use s_client_information::*;
|
||||
pub use s_close_container::*;
|
||||
pub use s_confirm_teleport::*;
|
||||
pub use s_interact::*;
|
||||
pub use s_keep_alive::*;
|
||||
pub use s_ping_request::*;
|
||||
pub use s_player_action::*;
|
||||
pub use s_player_command::*;
|
||||
|
||||
8
pumpkin-protocol/src/server/play/s_keep_alive.rs
Normal file
8
pumpkin-protocol/src/server/play/s_keep_alive.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use pumpkin_macros::packet;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[packet(0x18)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct SKeepAlive {
|
||||
pub keep_alive_id: i64,
|
||||
}
|
||||
@@ -113,10 +113,19 @@ pub struct Client {
|
||||
|
||||
/// Indicates whether the client should be converted into a player.
|
||||
pub make_player: AtomicBool,
|
||||
/// Sends each keep alive packet that the server receives for a player to here, which gets picked up in a tokio task
|
||||
pub keep_alive_sender: Arc<tokio::sync::mpsc::Sender<i64>>,
|
||||
/// Stores the last time it was confirmed that the client is alive
|
||||
pub last_alive_received: AtomicCell<std::time::Instant>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(token: Token, connection: TcpStream, address: SocketAddr) -> Self {
|
||||
pub fn new(
|
||||
token: Token,
|
||||
connection: TcpStream,
|
||||
address: SocketAddr,
|
||||
keep_alive_sender: Arc<tokio::sync::mpsc::Sender<i64>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
protocol_version: AtomicI32::new(0),
|
||||
gameprofile: Mutex::new(None),
|
||||
@@ -132,6 +141,8 @@ impl Client {
|
||||
closed: AtomicBool::new(false),
|
||||
client_packets_queue: Arc::new(Mutex::new(Vec::new())),
|
||||
make_player: AtomicBool::new(false),
|
||||
keep_alive_sender,
|
||||
last_alive_received: AtomicCell::new(std::time::Instant::now()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ use pumpkin_protocol::{
|
||||
ConnectionState, RawPacket, ServerPacket, VarInt,
|
||||
};
|
||||
|
||||
use pumpkin_protocol::server::play::SCloseContainer;
|
||||
use pumpkin_protocol::server::play::{SCloseContainer, SKeepAlive};
|
||||
use pumpkin_world::item::ItemStack;
|
||||
|
||||
use crate::{
|
||||
@@ -50,7 +50,7 @@ pub struct Player {
|
||||
/// The player's game profile information, including their username and UUID.
|
||||
pub gameprofile: GameProfile,
|
||||
/// The client connection associated with the player.
|
||||
pub client: Client,
|
||||
pub client: Arc<Client>,
|
||||
/// The player's configuration settings. Changes when the Player changes their settings.
|
||||
pub config: Mutex<PlayerConfig>,
|
||||
/// The player's current gamemode (e.g., Survival, Creative, Adventure).
|
||||
@@ -90,7 +90,12 @@ pub struct Player {
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(client: Client, world: Arc<World>, entity_id: EntityId, gamemode: GameMode) -> Self {
|
||||
pub fn new(
|
||||
client: Arc<Client>,
|
||||
world: Arc<World>,
|
||||
entity_id: EntityId,
|
||||
gamemode: GameMode,
|
||||
) -> Self {
|
||||
let gameprofile = match client.gameprofile.lock().clone() {
|
||||
Some(profile) => profile,
|
||||
None => {
|
||||
@@ -371,6 +376,14 @@ impl Player {
|
||||
self.handle_close_container(server, SCloseContainer::read(bytebuf)?);
|
||||
Ok(())
|
||||
}
|
||||
SKeepAlive::PACKET_ID => {
|
||||
self.client
|
||||
.keep_alive_sender
|
||||
.send(SKeepAlive::read(bytebuf)?.keep_alive_id)
|
||||
.await
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
log::error!("Failed to handle player packet id {:#04x}", packet.id.0);
|
||||
Ok(())
|
||||
|
||||
@@ -6,11 +6,13 @@ compile_error!("Compiling for WASI targets is not supported!");
|
||||
use mio::net::TcpListener;
|
||||
use mio::{Events, Interest, Poll, Token};
|
||||
|
||||
use client::{interrupted, Client};
|
||||
use pumpkin_protocol::client::play::CKeepAlive;
|
||||
use pumpkin_protocol::ConnectionState;
|
||||
use server::Server;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, Read};
|
||||
|
||||
use client::{interrupted, Client};
|
||||
use server::Server;
|
||||
use std::time::Duration;
|
||||
|
||||
// Setup some tokens to allow us to identify which event is for which socket.
|
||||
|
||||
@@ -78,7 +80,7 @@ fn main() -> io::Result<()> {
|
||||
let use_console = ADVANCED_CONFIG.commands.use_console;
|
||||
let rcon = ADVANCED_CONFIG.rcon.clone();
|
||||
|
||||
let mut clients: HashMap<Token, Client> = HashMap::new();
|
||||
let mut clients: HashMap<Token, Arc<Client>> = HashMap::new();
|
||||
let mut players: HashMap<Token, Arc<Player>> = HashMap::new();
|
||||
|
||||
let server = Arc::new(Server::new());
|
||||
@@ -152,7 +154,41 @@ fn main() -> io::Result<()> {
|
||||
token,
|
||||
Interest::READABLE.add(Interest::WRITABLE),
|
||||
)?;
|
||||
let client = Client::new(token, connection, addr);
|
||||
let keep_alive = tokio::sync::mpsc::channel(1024);
|
||||
let client =
|
||||
Arc::new(Client::new(token, connection, addr, keep_alive.0.into()));
|
||||
|
||||
{
|
||||
let client = client.clone();
|
||||
let mut receiver = keep_alive.1;
|
||||
tokio::spawn(async move {
|
||||
let mut interval = tokio::time::interval(Duration::from_secs(1));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
let now = std::time::Instant::now();
|
||||
if client.connection_state.load() == ConnectionState::Play {
|
||||
if now.duration_since(client.last_alive_received.load())
|
||||
>= Duration::from_secs(15)
|
||||
{
|
||||
dbg!("no keep alive");
|
||||
client.kick("No keep alive received");
|
||||
break;
|
||||
}
|
||||
let random = rand::random::<i64>();
|
||||
client.send_packet(&CKeepAlive {
|
||||
keep_alive_id: random,
|
||||
});
|
||||
if let Some(id) = receiver.recv().await {
|
||||
if id == random {
|
||||
client.last_alive_received.store(now);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client.last_alive_received.store(now);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
clients.insert(token, client);
|
||||
},
|
||||
|
||||
|
||||
@@ -5,10 +5,13 @@ use parking_lot::{Mutex, RwLock};
|
||||
use pumpkin_config::BASIC_CONFIG;
|
||||
use pumpkin_core::GameMode;
|
||||
use pumpkin_entity::EntityId;
|
||||
use pumpkin_inventory::drag_handler::DragHandler;
|
||||
use pumpkin_inventory::{Container, OpenContainer};
|
||||
use pumpkin_plugin::PluginLoader;
|
||||
use pumpkin_protocol::client::login::CEncryptionRequest;
|
||||
use pumpkin_protocol::client::status::CStatusResponse;
|
||||
use pumpkin_protocol::{client::config::CPluginMessage, ClientPacket};
|
||||
use pumpkin_registry::Registry;
|
||||
use pumpkin_world::dimension::Dimension;
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
@@ -19,10 +22,6 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use pumpkin_inventory::drag_handler::DragHandler;
|
||||
use pumpkin_inventory::{Container, OpenContainer};
|
||||
use pumpkin_registry::Registry;
|
||||
|
||||
use crate::client::EncryptionError;
|
||||
use crate::{
|
||||
client::Client,
|
||||
@@ -96,7 +95,7 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn add_player(&self, token: Token, client: Client) -> (Arc<Player>, Arc<World>) {
|
||||
pub async fn add_player(&self, token: Token, client: Arc<Client>) -> (Arc<Player>, Arc<World>) {
|
||||
let entity_id = self.new_entity_id();
|
||||
let gamemode = match BASIC_CONFIG.default_gamemode {
|
||||
GameMode::Undefined => GameMode::Survival,
|
||||
|
||||
@@ -2,6 +2,10 @@ use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
pub mod player_chunker;
|
||||
|
||||
use crate::{
|
||||
client::Client,
|
||||
entity::{player::Player, Entity},
|
||||
};
|
||||
use mio::Token;
|
||||
use num_traits::ToPrimitive;
|
||||
use parking_lot::Mutex;
|
||||
@@ -18,11 +22,6 @@ use pumpkin_protocol::{
|
||||
use pumpkin_world::level::Level;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::{
|
||||
client::Client,
|
||||
entity::{player::Player, Entity},
|
||||
};
|
||||
|
||||
/// Represents a Minecraft world, containing entities, players, and the underlying level data.
|
||||
///
|
||||
/// Each dimension (Overworld, Nether, End) typically has its own `World`.
|
||||
|
||||
Reference in New Issue
Block a user