Cleanup Server struct
This cleanup's goal is to make all `Server` functions only require &self. This means that `Server` can now be a `Arc<Server>` instead of `Arc<Mutex<Server>>`, which solves a lot of deadlock problems.
This commit is contained in:
parent
f23592de8c
commit
fa114e7e23
@ -1,14 +1,14 @@
|
|||||||
use crate::{Container, WindowType};
|
use crate::{Container, WindowType};
|
||||||
use pumpkin_world::item::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use std::sync::Mutex;
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub struct OpenContainer {
|
pub struct OpenContainer {
|
||||||
players: Vec<i32>,
|
players: Vec<i32>,
|
||||||
container: Mutex<Box<dyn Container>>,
|
container: Arc<Mutex<Box<dyn Container>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpenContainer {
|
impl OpenContainer {
|
||||||
pub fn try_open(&self, player_id: i32) -> Option<&Mutex<Box<dyn Container>>> {
|
pub fn try_open(&self, player_id: i32) -> Option<&Arc<Mutex<Box<dyn Container>>>> {
|
||||||
if !self.players.contains(&player_id) {
|
if !self.players.contains(&player_id) {
|
||||||
dbg!("couldn't open container");
|
dbg!("couldn't open container");
|
||||||
return None;
|
return None;
|
||||||
@ -38,7 +38,7 @@ impl OpenContainer {
|
|||||||
pub fn empty(player_id: i32) -> Self {
|
pub fn empty(player_id: i32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
players: vec![player_id],
|
players: vec![player_id],
|
||||||
container: Mutex::new(Box::new(Chest::new())),
|
container: Arc::new(Mutex::new(Box::new(Chest::new()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashMap, net::IpAddr};
|
use std::{collections::HashMap, net::IpAddr, sync::Arc};
|
||||||
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
@ -13,13 +13,13 @@ use uuid::Uuid;
|
|||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
|
|
||||||
#[derive(Deserialize, Clone, Debug)]
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
#[expect(non_snake_case)]
|
|
||||||
#[expect(dead_code)]
|
#[expect(dead_code)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ProfileTextures {
|
pub struct ProfileTextures {
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
profileId: Uuid,
|
profile_id: Uuid,
|
||||||
profileName: String,
|
profile_name: String,
|
||||||
signatureRequired: bool,
|
signature_required: bool,
|
||||||
textures: HashMap<String, Texture>,
|
textures: HashMap<String, Texture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ pub async fn authenticate(
|
|||||||
username: &str,
|
username: &str,
|
||||||
server_hash: &str,
|
server_hash: &str,
|
||||||
ip: &IpAddr,
|
ip: &IpAddr,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
) -> Result<GameProfile, AuthError> {
|
) -> Result<GameProfile, AuthError> {
|
||||||
assert!(ADVANCED_CONFIG.authentication.enabled);
|
assert!(ADVANCED_CONFIG.authentication.enabled);
|
||||||
assert!(server.auth_client.is_some());
|
assert!(server.auth_client.is_some());
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
|
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
|
||||||
use pumpkin_core::text::TextComponent;
|
use pumpkin_core::text::TextComponent;
|
||||||
@ -35,7 +37,7 @@ use super::{
|
|||||||
/// NEVER TRUST THE CLIENT. HANDLE EVERY ERROR, UNWRAP/EXPECT
|
/// NEVER TRUST THE CLIENT. HANDLE EVERY ERROR, UNWRAP/EXPECT
|
||||||
/// TODO: REMOVE ALL UNWRAPS
|
/// TODO: REMOVE ALL UNWRAPS
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn handle_handshake(&mut self, _server: &mut Server, handshake: SHandShake) {
|
pub fn handle_handshake(&mut self, _server: &Arc<Server>, handshake: SHandShake) {
|
||||||
dbg!("handshake");
|
dbg!("handshake");
|
||||||
self.protocol_version = handshake.protocol_version.0;
|
self.protocol_version = handshake.protocol_version.0;
|
||||||
self.connection_state = handshake.next_state;
|
self.connection_state = handshake.next_state;
|
||||||
@ -53,24 +55,21 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_status_request(&mut self, server: &mut Server, _status_request: SStatusRequest) {
|
pub fn handle_status_request(&mut self, server: &Arc<Server>, _status_request: SStatusRequest) {
|
||||||
self.send_packet(&CStatusResponse::new(&server.status_response_json));
|
self.send_packet(&CStatusResponse::new(&server.status_response_json));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_ping_request(&mut self, _server: &mut Server, ping_request: SStatusPingRequest) {
|
pub fn handle_ping_request(&mut self, _server: &Arc<Server>, ping_request: SStatusPingRequest) {
|
||||||
dbg!("ping");
|
dbg!("ping");
|
||||||
self.send_packet(&CPingResponse::new(ping_request.payload));
|
self.send_packet(&CPingResponse::new(ping_request.payload));
|
||||||
self.close();
|
self.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_player_name(name: &str) -> bool {
|
fn is_valid_player_name(name: &str) -> bool {
|
||||||
name.len() <= 16
|
name.len() <= 16 && name.chars().all(|c| c > 32 as char && c < 127 as char)
|
||||||
&& name
|
|
||||||
.chars()
|
|
||||||
.all(|c| c > 32 as u8 as char && c < 127 as u8 as char)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart) {
|
pub fn handle_login_start(&mut self, server: &Arc<Server>, login_start: SLoginStart) {
|
||||||
log::debug!("login start, State {:?}", self.connection_state);
|
log::debug!("login start, State {:?}", self.connection_state);
|
||||||
|
|
||||||
if !Self::is_valid_player_name(&login_start.name) {
|
if !Self::is_valid_player_name(&login_start.name) {
|
||||||
@ -107,7 +106,7 @@ impl Client {
|
|||||||
|
|
||||||
pub async fn handle_encryption_response(
|
pub async fn handle_encryption_response(
|
||||||
&mut self,
|
&mut self,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
encryption_response: SEncryptionResponse,
|
encryption_response: SEncryptionResponse,
|
||||||
) {
|
) {
|
||||||
let shared_secret = server
|
let shared_secret = server
|
||||||
@ -185,14 +184,14 @@ impl Client {
|
|||||||
|
|
||||||
pub fn handle_plugin_response(
|
pub fn handle_plugin_response(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
_plugin_response: SLoginPluginResponse,
|
_plugin_response: SLoginPluginResponse,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_login_acknowledged(
|
pub fn handle_login_acknowledged(
|
||||||
&mut self,
|
&mut self,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
_login_acknowledged: SLoginAcknowledged,
|
_login_acknowledged: SLoginAcknowledged,
|
||||||
) {
|
) {
|
||||||
self.connection_state = ConnectionState::Config;
|
self.connection_state = ConnectionState::Config;
|
||||||
@ -227,7 +226,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
pub fn handle_client_information_config(
|
pub fn handle_client_information_config(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
client_information: SClientInformationConfig,
|
client_information: SClientInformationConfig,
|
||||||
) {
|
) {
|
||||||
dbg!("got client settings");
|
dbg!("got client settings");
|
||||||
@ -243,7 +242,7 @@ impl Client {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_plugin_message(&mut self, _server: &mut Server, plugin_message: SPluginMessage) {
|
pub fn handle_plugin_message(&mut self, _server: &Arc<Server>, plugin_message: SPluginMessage) {
|
||||||
if plugin_message.channel.starts_with("minecraft:brand")
|
if plugin_message.channel.starts_with("minecraft:brand")
|
||||||
|| plugin_message.channel.starts_with("MC|Brand")
|
|| plugin_message.channel.starts_with("MC|Brand")
|
||||||
{
|
{
|
||||||
@ -255,7 +254,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_known_packs(&mut self, server: &mut Server, _config_acknowledged: SKnownPacks) {
|
pub fn handle_known_packs(&mut self, server: &Arc<Server>, _config_acknowledged: SKnownPacks) {
|
||||||
for registry in &server.cached_registry {
|
for registry in &server.cached_registry {
|
||||||
self.send_packet(&CRegistryData::new(
|
self.send_packet(&CRegistryData::new(
|
||||||
®istry.registry_id,
|
®istry.registry_id,
|
||||||
@ -270,7 +269,7 @@ impl Client {
|
|||||||
|
|
||||||
pub async fn handle_config_acknowledged(
|
pub async fn handle_config_acknowledged(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
_config_acknowledged: SAcknowledgeFinishConfig,
|
_config_acknowledged: SAcknowledgeFinishConfig,
|
||||||
) {
|
) {
|
||||||
dbg!("config acknowledged");
|
dbg!("config acknowledged");
|
||||||
|
|||||||
@ -19,11 +19,12 @@ use pumpkin_world::item::ItemStack;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub fn open_container(&mut self, server: &mut Server, minecraft_menu_id: &str) {
|
pub fn open_container(&mut self, server: &Arc<Server>, minecraft_menu_id: &str) {
|
||||||
self.inventory.state_id = 0;
|
self.inventory.state_id = 0;
|
||||||
let total_opened_containers = self.inventory.total_opened_containers;
|
let total_opened_containers = self.inventory.total_opened_containers;
|
||||||
let mut container = self
|
let container = self.get_open_container(server);
|
||||||
.get_open_container(server)
|
let mut container = container
|
||||||
|
.as_ref()
|
||||||
.map(|container| container.lock().unwrap());
|
.map(|container| container.lock().unwrap());
|
||||||
let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY
|
let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY
|
||||||
.get("minecraft:menu")
|
.get("minecraft:menu")
|
||||||
@ -97,11 +98,12 @@ impl Player {
|
|||||||
|
|
||||||
pub async fn handle_click_container(
|
pub async fn handle_click_container(
|
||||||
&mut self,
|
&mut self,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
packet: SClickContainer,
|
packet: SClickContainer,
|
||||||
) -> Result<(), InventoryError> {
|
) -> Result<(), InventoryError> {
|
||||||
let mut opened_container = self
|
let opened_container = self.get_open_container(server);
|
||||||
.get_open_container(server)
|
let mut opened_container = opened_container
|
||||||
|
.as_ref()
|
||||||
.map(|container| container.lock().unwrap());
|
.map(|container| container.lock().unwrap());
|
||||||
let drag_handler = &server.drag_handler;
|
let drag_handler = &server.drag_handler;
|
||||||
|
|
||||||
@ -165,7 +167,10 @@ impl Player {
|
|||||||
}
|
}
|
||||||
self.mouse_drag(drag_handler, opened_container.as_deref_mut(), drag_state)
|
self.mouse_drag(drag_handler, opened_container.as_deref_mut(), drag_state)
|
||||||
}
|
}
|
||||||
ClickType::DropType(_drop_type) => {dbg!("todo"); Ok(())},
|
ClickType::DropType(_drop_type) => {
|
||||||
|
dbg!("todo");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}?;
|
}?;
|
||||||
if let Some(mut opened_container) = opened_container {
|
if let Some(mut opened_container) = opened_container {
|
||||||
if update_whole_container {
|
if update_whole_container {
|
||||||
@ -355,14 +360,19 @@ impl Player {
|
|||||||
&mut self,
|
&mut self,
|
||||||
server: &Server,
|
server: &Server,
|
||||||
) -> Vec<Arc<Mutex<Player>>> {
|
) -> Vec<Arc<Mutex<Player>>> {
|
||||||
let player_ids = server
|
let player_ids = {
|
||||||
|
let open_containers = server
|
||||||
.open_containers
|
.open_containers
|
||||||
|
.read()
|
||||||
|
.expect("open_containers is poisoned");
|
||||||
|
open_containers
|
||||||
.get(&self.open_container.unwrap())
|
.get(&self.open_container.unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.all_player_ids()
|
.all_player_ids()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|player_id| *player_id != self.entity_id())
|
.filter(|player_id| *player_id != self.entity_id())
|
||||||
.collect_vec();
|
.collect_vec()
|
||||||
|
};
|
||||||
let player_token = self.client.token;
|
let player_token = self.client.token;
|
||||||
|
|
||||||
// TODO: Figure out better way to get only the players from player_ids
|
// TODO: Figure out better way to get only the players from player_ids
|
||||||
@ -415,19 +425,14 @@ impl Player {
|
|||||||
|
|
||||||
for player in players {
|
for player in players {
|
||||||
let mut player = player.lock().unwrap();
|
let mut player = player.lock().unwrap();
|
||||||
let mut container = player
|
let container = player.get_open_container(server);
|
||||||
.get_open_container(server)
|
let mut container = container.as_ref().map(|v| v.lock().unwrap());
|
||||||
.map(|container| container.lock().unwrap());
|
|
||||||
player.set_container_content(container.as_deref_mut());
|
player.set_container_content(container.as_deref_mut());
|
||||||
drop(container)
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_open_container<'a>(
|
pub fn get_open_container(&self, server: &Server) -> Option<Arc<Mutex<Box<dyn Container>>>> {
|
||||||
&self,
|
|
||||||
server: &'a Server,
|
|
||||||
) -> Option<&'a Mutex<Box<dyn Container>>> {
|
|
||||||
if let Some(id) = self.open_container {
|
if let Some(id) = self.open_container {
|
||||||
server.try_get_container(self.entity_id(), id)
|
server.try_get_container(self.entity_id(), id)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -148,7 +149,7 @@ impl Client {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn process_packets(&mut self, server: &mut Server) {
|
pub async fn process_packets(&mut self, server: &Arc<Server>) {
|
||||||
while let Some(mut packet) = self.client_packets_queue.pop() {
|
while let Some(mut packet) = self.client_packets_queue.pop() {
|
||||||
match self.handle_packet(server, &mut packet).await {
|
match self.handle_packet(server, &mut packet).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -164,7 +165,7 @@ impl Client {
|
|||||||
/// Handles an incoming decoded not Play state Packet
|
/// Handles an incoming decoded not Play state Packet
|
||||||
pub async fn handle_packet(
|
pub async fn handle_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
packet: &mut RawPacket,
|
packet: &mut RawPacket,
|
||||||
) -> Result<(), DeserializerError> {
|
) -> Result<(), DeserializerError> {
|
||||||
// TODO: handle each packet's Error instead of calling .unwrap()
|
// TODO: handle each packet's Error instead of calling .unwrap()
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::f32::consts::PI;
|
use std::{f32::consts::PI, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
commands::CommandSender,
|
commands::CommandSender,
|
||||||
@ -43,7 +43,7 @@ fn modulus(a: f32, b: f32) -> f32 {
|
|||||||
impl Player {
|
impl Player {
|
||||||
pub fn handle_confirm_teleport(
|
pub fn handle_confirm_teleport(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
confirm_teleport: SConfirmTeleport,
|
confirm_teleport: SConfirmTeleport,
|
||||||
) {
|
) {
|
||||||
if let Some((id, position)) = self.awaiting_teleport.as_ref() {
|
if let Some((id, position)) = self.awaiting_teleport.as_ref() {
|
||||||
@ -70,7 +70,7 @@ impl Player {
|
|||||||
pos.clamp(-2.0E7, 2.0E7)
|
pos.clamp(-2.0E7, 2.0E7)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_position(&mut self, _server: &mut Server, position: SPlayerPosition) {
|
pub async fn handle_position(&mut self, _server: &Arc<Server>, position: SPlayerPosition) {
|
||||||
if position.x.is_nan() || position.feet_y.is_nan() || position.z.is_nan() {
|
if position.x.is_nan() || position.feet_y.is_nan() || position.z.is_nan() {
|
||||||
self.kick(TextComponent::text("Invalid movement"));
|
self.kick(TextComponent::text("Invalid movement"));
|
||||||
return;
|
return;
|
||||||
@ -118,7 +118,7 @@ impl Player {
|
|||||||
|
|
||||||
pub async fn handle_position_rotation(
|
pub async fn handle_position_rotation(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
position_rotation: SPlayerPositionRotation,
|
position_rotation: SPlayerPositionRotation,
|
||||||
) {
|
) {
|
||||||
if position_rotation.x.is_nan()
|
if position_rotation.x.is_nan()
|
||||||
@ -188,7 +188,7 @@ impl Player {
|
|||||||
player_chunker::update_position(&world, self).await;
|
player_chunker::update_position(&world, self).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_rotation(&mut self, _server: &mut Server, rotation: SPlayerRotation) {
|
pub async fn handle_rotation(&mut self, _server: &Arc<Server>, rotation: SPlayerRotation) {
|
||||||
if !rotation.yaw.is_finite() || !rotation.pitch.is_finite() {
|
if !rotation.yaw.is_finite() || !rotation.pitch.is_finite() {
|
||||||
self.kick(TextComponent::text("Invalid rotation"));
|
self.kick(TextComponent::text("Invalid rotation"));
|
||||||
return;
|
return;
|
||||||
@ -213,16 +213,16 @@ impl Player {
|
|||||||
world.broadcast_packet(&[self.client.token], &packet);
|
world.broadcast_packet(&[self.client.token], &packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_chat_command(&mut self, server: &mut Server, command: SChatCommand) {
|
pub fn handle_chat_command(&mut self, server: &Arc<Server>, command: SChatCommand) {
|
||||||
let dispatcher = server.command_dispatcher.clone();
|
let dispatcher = server.command_dispatcher.clone();
|
||||||
dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command);
|
dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_player_ground(&mut self, _server: &mut Server, ground: SSetPlayerGround) {
|
pub fn handle_player_ground(&mut self, _server: &Arc<Server>, ground: SSetPlayerGround) {
|
||||||
self.entity.on_ground = ground.on_ground;
|
self.entity.on_ground = ground.on_ground;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_player_command(&mut self, _server: &mut Server, command: SPlayerCommand) {
|
pub async fn handle_player_command(&mut self, _server: &Arc<Server>, command: SPlayerCommand) {
|
||||||
if command.entity_id != self.entity.entity_id.into() {
|
if command.entity_id != self.entity.entity_id.into() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_swing_arm(&mut self, _server: &mut Server, swing_arm: SSwingArm) {
|
pub async fn handle_swing_arm(&mut self, _server: &Arc<Server>, swing_arm: SSwingArm) {
|
||||||
match Hand::from_i32(swing_arm.hand.0) {
|
match Hand::from_i32(swing_arm.hand.0) {
|
||||||
Some(hand) => {
|
Some(hand) => {
|
||||||
let animation = match hand {
|
let animation = match hand {
|
||||||
@ -287,7 +287,7 @@ impl Player {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_chat_message(&mut self, _server: &mut Server, chat_message: SChatMessage) {
|
pub async fn handle_chat_message(&mut self, _server: &Arc<Server>, chat_message: SChatMessage) {
|
||||||
dbg!("got message");
|
dbg!("got message");
|
||||||
|
|
||||||
let message = chat_message.message;
|
let message = chat_message.message;
|
||||||
@ -331,7 +331,7 @@ impl Player {
|
|||||||
|
|
||||||
pub fn handle_client_information_play(
|
pub fn handle_client_information_play(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
client_information: SClientInformationPlay,
|
client_information: SClientInformationPlay,
|
||||||
) {
|
) {
|
||||||
if let (Some(main_hand), Some(chat_mode)) = (
|
if let (Some(main_hand), Some(chat_mode)) = (
|
||||||
@ -353,7 +353,7 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_interact(&mut self, _: &mut Server, interact: SInteract) {
|
pub async fn handle_interact(&mut self, _: &Arc<Server>, interact: SInteract) {
|
||||||
let sneaking = interact.sneaking;
|
let sneaking = interact.sneaking;
|
||||||
if self.entity.sneaking != sneaking {
|
if self.entity.sneaking != sneaking {
|
||||||
self.entity.set_sneaking(&mut self.client, sneaking).await;
|
self.entity.set_sneaking(&mut self.client, sneaking).await;
|
||||||
@ -422,7 +422,7 @@ impl Player {
|
|||||||
}
|
}
|
||||||
pub async fn handle_player_action(
|
pub async fn handle_player_action(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
player_action: SPlayerAction,
|
player_action: SPlayerAction,
|
||||||
) {
|
) {
|
||||||
match Status::from_i32(player_action.status.0) {
|
match Status::from_i32(player_action.status.0) {
|
||||||
@ -497,12 +497,12 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_play_ping_request(&mut self, _server: &mut Server, request: SPlayPingRequest) {
|
pub fn handle_play_ping_request(&mut self, _server: &Arc<Server>, request: SPlayPingRequest) {
|
||||||
self.client
|
self.client
|
||||||
.send_packet(&CPingResponse::new(request.payload));
|
.send_packet(&CPingResponse::new(request.payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_use_item_on(&mut self, _server: &mut Server, use_item_on: SUseItemOn) {
|
pub async fn handle_use_item_on(&mut self, _server: &Arc<Server>, use_item_on: SUseItemOn) {
|
||||||
let location = use_item_on.location;
|
let location = use_item_on.location;
|
||||||
|
|
||||||
if !self.can_interact_with_block_at(&location, 1.0) {
|
if !self.can_interact_with_block_at(&location, 1.0) {
|
||||||
@ -539,12 +539,12 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_use_item(&mut self, _server: &mut Server, _use_item: SUseItem) {
|
pub fn handle_use_item(&mut self, _server: &Arc<Server>, _use_item: SUseItem) {
|
||||||
// TODO: handle packet correctly
|
// TODO: handle packet correctly
|
||||||
log::error!("An item was used(SUseItem), but the packet is not implemented yet");
|
log::error!("An item was used(SUseItem), but the packet is not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_set_held_item(&mut self, _server: &mut Server, held: SSetHeldItem) {
|
pub fn handle_set_held_item(&mut self, _server: &Arc<Server>, held: SSetHeldItem) {
|
||||||
let slot = held.slot;
|
let slot = held.slot;
|
||||||
if !(0..=8).contains(&slot) {
|
if !(0..=8).contains(&slot) {
|
||||||
self.kick(TextComponent::text("Invalid held slot"))
|
self.kick(TextComponent::text("Invalid held slot"))
|
||||||
@ -554,7 +554,7 @@ impl Player {
|
|||||||
|
|
||||||
pub fn handle_set_creative_slot(
|
pub fn handle_set_creative_slot(
|
||||||
&mut self,
|
&mut self,
|
||||||
_server: &mut Server,
|
_server: &Arc<Server>,
|
||||||
packet: SSetCreativeSlot,
|
packet: SSetCreativeSlot,
|
||||||
) -> Result<(), InventoryError> {
|
) -> Result<(), InventoryError> {
|
||||||
if self.gamemode != GameMode::Creative {
|
if self.gamemode != GameMode::Creative {
|
||||||
@ -567,11 +567,15 @@ impl Player {
|
|||||||
// TODO:
|
// TODO:
|
||||||
// This function will in the future be used to keep track of if the client is in a valid state.
|
// This function will in the future be used to keep track of if the client is in a valid state.
|
||||||
// But this is not possible yet
|
// But this is not possible yet
|
||||||
pub fn handle_close_container(&mut self, server: &mut Server, packet: SCloseContainer) {
|
pub fn handle_close_container(&mut self, server: &Arc<Server>, packet: SCloseContainer) {
|
||||||
// window_id 0 represents both 9x1 Generic AND inventory here
|
// window_id 0 represents both 9x1 Generic AND inventory here
|
||||||
self.inventory.state_id = 0;
|
self.inventory.state_id = 0;
|
||||||
if let Some(id) = self.open_container {
|
if let Some(id) = self.open_container {
|
||||||
if let Some(container) = server.open_containers.get_mut(&id) {
|
let mut open_containers = server
|
||||||
|
.open_containers
|
||||||
|
.write()
|
||||||
|
.expect("open_containers got poisoned");
|
||||||
|
if let Some(container) = open_containers.get_mut(&id) {
|
||||||
container.remove_player(self.entity_id())
|
container.remove_player(self.entity_id())
|
||||||
}
|
}
|
||||||
self.open_container = None;
|
self.open_container = None;
|
||||||
|
|||||||
@ -12,13 +12,19 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
|||||||
if let Some(player) = sender.as_mut_player() {
|
if let Some(player) = sender.as_mut_player() {
|
||||||
let entity_id = player.entity_id();
|
let entity_id = player.entity_id();
|
||||||
player.open_container = Some(0);
|
player.open_container = Some(0);
|
||||||
match server.open_containers.get_mut(&0) {
|
{
|
||||||
|
let mut open_containers = server
|
||||||
|
.open_containers
|
||||||
|
.write()
|
||||||
|
.expect("open_containers got poisoned");
|
||||||
|
match open_containers.get_mut(&0) {
|
||||||
Some(ender_chest) => {
|
Some(ender_chest) => {
|
||||||
ender_chest.add_player(entity_id);
|
ender_chest.add_player(entity_id);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let open_container = OpenContainer::empty(entity_id);
|
let open_container = OpenContainer::empty(entity_id);
|
||||||
server.open_containers.insert(0, open_container);
|
open_containers.insert(0, open_container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
player.open_container(server, "minecraft:generic_9x3");
|
player.open_container(server, "minecraft:generic_9x3");
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use crate::commands::tree::{Command, CommandTree, ConsumedArgs, NodeType, RawArg
|
|||||||
use crate::commands::CommandSender;
|
use crate::commands::CommandSender;
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum InvalidTreeError {
|
pub(crate) enum InvalidTreeError {
|
||||||
@ -26,7 +27,7 @@ pub struct CommandDispatcher<'a> {
|
|||||||
|
|
||||||
/// Stores registered [CommandTree]s and dispatches commands to them.
|
/// Stores registered [CommandTree]s and dispatches commands to them.
|
||||||
impl<'a> CommandDispatcher<'a> {
|
impl<'a> CommandDispatcher<'a> {
|
||||||
pub fn handle_command(&self, sender: &mut CommandSender, server: &mut Server, cmd: &str) {
|
pub fn handle_command(&self, sender: &mut CommandSender, server: &Arc<Server>, cmd: &str) {
|
||||||
if let Err(err) = self.dispatch(sender, server, cmd) {
|
if let Err(err) = self.dispatch(sender, server, cmd) {
|
||||||
sender.send_message(
|
sender.send_message(
|
||||||
TextComponent::text(&err).color_named(pumpkin_core::text::color::NamedColor::Red),
|
TextComponent::text(&err).color_named(pumpkin_core::text::color::NamedColor::Red),
|
||||||
@ -38,7 +39,7 @@ impl<'a> CommandDispatcher<'a> {
|
|||||||
pub(crate) fn dispatch(
|
pub(crate) fn dispatch(
|
||||||
&'a self,
|
&'a self,
|
||||||
src: &mut CommandSender,
|
src: &mut CommandSender,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
cmd: &str,
|
cmd: &str,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut parts = cmd.split_ascii_whitespace();
|
let mut parts = cmd.split_ascii_whitespace();
|
||||||
@ -86,7 +87,7 @@ impl<'a> CommandDispatcher<'a> {
|
|||||||
|
|
||||||
fn try_is_fitting_path(
|
fn try_is_fitting_path(
|
||||||
src: &mut CommandSender,
|
src: &mut CommandSender,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
path: Vec<usize>,
|
path: Vec<usize>,
|
||||||
tree: &CommandTree,
|
tree: &CommandTree,
|
||||||
mut raw_args: RawArgs,
|
mut raw_args: RawArgs,
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dispatcher::InvalidTreeError;
|
||||||
use pumpkin_core::text::TextComponent;
|
use pumpkin_core::text::TextComponent;
|
||||||
|
use tree::ConsumedArgs;
|
||||||
|
|
||||||
use crate::commands::dispatcher::CommandDispatcher;
|
use crate::commands::dispatcher::CommandDispatcher;
|
||||||
use crate::entity::player::Player;
|
use crate::entity::player::Player;
|
||||||
|
use crate::server::Server;
|
||||||
mod arg_player;
|
mod arg_player;
|
||||||
mod cmd_echest;
|
mod cmd_echest;
|
||||||
mod cmd_gamemode;
|
mod cmd_gamemode;
|
||||||
@ -73,3 +78,6 @@ pub fn default_dispatcher<'a>() -> CommandDispatcher<'a> {
|
|||||||
|
|
||||||
dispatcher
|
dispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RunFunctionType = (dyn Fn(&mut CommandSender, &Arc<Server>, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
||||||
|
+ Sync);
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
use std::collections::{HashMap, VecDeque};
|
use super::RunFunctionType;
|
||||||
|
|
||||||
use crate::commands::dispatcher::InvalidTreeError;
|
|
||||||
use crate::commands::CommandSender;
|
use crate::commands::CommandSender;
|
||||||
use crate::server::Server;
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
/// see [crate::commands::tree_builder::argument]
|
/// see [crate::commands::tree_builder::argument]
|
||||||
pub(crate) type RawArgs<'a> = Vec<&'a str>;
|
pub(crate) type RawArgs<'a> = Vec<&'a str>;
|
||||||
@ -20,8 +18,7 @@ pub(crate) struct Node<'a> {
|
|||||||
|
|
||||||
pub(crate) enum NodeType<'a> {
|
pub(crate) enum NodeType<'a> {
|
||||||
ExecuteLeaf {
|
ExecuteLeaf {
|
||||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
run: &'a RunFunctionType,
|
||||||
+ Sync),
|
|
||||||
},
|
},
|
||||||
Literal {
|
Literal {
|
||||||
string: &'a str,
|
string: &'a str,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::commands::dispatcher::InvalidTreeError;
|
use crate::commands::tree::{ArgumentConsumer, CommandTree, Node, NodeType};
|
||||||
use crate::commands::tree::{ArgumentConsumer, CommandTree, ConsumedArgs, Node, NodeType};
|
|
||||||
use crate::commands::CommandSender;
|
use crate::commands::CommandSender;
|
||||||
use crate::server::Server;
|
|
||||||
|
use super::RunFunctionType;
|
||||||
|
|
||||||
impl<'a> CommandTree<'a> {
|
impl<'a> CommandTree<'a> {
|
||||||
/// Add a child [Node] to the root of this [CommandTree].
|
/// Add a child [Node] to the root of this [CommandTree].
|
||||||
@ -40,11 +40,7 @@ impl<'a> CommandTree<'a> {
|
|||||||
/// desired type.
|
/// desired type.
|
||||||
///
|
///
|
||||||
/// Also see [NonLeafNodeBuilder::execute].
|
/// Also see [NonLeafNodeBuilder::execute].
|
||||||
pub fn execute(
|
pub fn execute(mut self, run: &'a RunFunctionType) -> Self {
|
||||||
mut self,
|
|
||||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
|
||||||
+ Sync),
|
|
||||||
) -> Self {
|
|
||||||
let node = Node {
|
let node = Node {
|
||||||
node_type: NodeType::ExecuteLeaf { run },
|
node_type: NodeType::ExecuteLeaf { run },
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
@ -117,11 +113,7 @@ impl<'a> NonLeafNodeBuilder<'a> {
|
|||||||
/// desired type.
|
/// desired type.
|
||||||
///
|
///
|
||||||
/// Also see [CommandTree::execute].
|
/// Also see [CommandTree::execute].
|
||||||
pub fn execute(
|
pub fn execute(mut self, run: &'a RunFunctionType) -> Self {
|
||||||
mut self,
|
|
||||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
|
||||||
+ Sync),
|
|
||||||
) -> Self {
|
|
||||||
self.leaf_nodes.push(LeafNodeBuilder {
|
self.leaf_nodes.push(LeafNodeBuilder {
|
||||||
node_type: NodeType::ExecuteLeaf { run },
|
node_type: NodeType::ExecuteLeaf { run },
|
||||||
});
|
});
|
||||||
|
|||||||
@ -263,7 +263,7 @@ impl Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub async fn process_packets(&mut self, server: &mut Server) {
|
pub async fn process_packets(&mut self, server: &Arc<Server>) {
|
||||||
while let Some(mut packet) = self.client.client_packets_queue.pop() {
|
while let Some(mut packet) = self.client.client_packets_queue.pop() {
|
||||||
match self.handle_play_packet(server, &mut packet).await {
|
match self.handle_play_packet(server, &mut packet).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -278,7 +278,7 @@ impl Player {
|
|||||||
|
|
||||||
pub async fn handle_play_packet(
|
pub async fn handle_play_packet(
|
||||||
&mut self,
|
&mut self,
|
||||||
server: &mut Server,
|
server: &Arc<Server>,
|
||||||
packet: &mut RawPacket,
|
packet: &mut RawPacket,
|
||||||
) -> Result<(), DeserializerError> {
|
) -> Result<(), DeserializerError> {
|
||||||
let bytebuf = &mut packet.bytebuf;
|
let bytebuf = &mut packet.bytebuf;
|
||||||
|
|||||||
@ -81,12 +81,12 @@ fn main() -> io::Result<()> {
|
|||||||
let mut clients: HashMap<Token, Client> = HashMap::new();
|
let mut clients: HashMap<Token, Client> = HashMap::new();
|
||||||
let mut players: HashMap<Token, Arc<Mutex<Player>>> = HashMap::new();
|
let mut players: HashMap<Token, Arc<Mutex<Player>>> = HashMap::new();
|
||||||
|
|
||||||
let server = Arc::new(tokio::sync::Mutex::new(Server::new()));
|
let server = Arc::new(Server::new());
|
||||||
log::info!("Started Server took {}ms", time.elapsed().as_millis());
|
log::info!("Started Server took {}ms", time.elapsed().as_millis());
|
||||||
log::info!("You now can connect to the server, Listening on {}", addr);
|
log::info!("You now can connect to the server, Listening on {}", addr);
|
||||||
|
|
||||||
let server1 = server.clone();
|
|
||||||
if use_console {
|
if use_console {
|
||||||
|
let server = server.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
loop {
|
loop {
|
||||||
@ -96,11 +96,10 @@ fn main() -> io::Result<()> {
|
|||||||
.expect("Failed to read console line");
|
.expect("Failed to read console line");
|
||||||
|
|
||||||
if !out.is_empty() {
|
if !out.is_empty() {
|
||||||
let mut server = server1.lock().await;
|
|
||||||
let dispatcher = server.command_dispatcher.clone();
|
let dispatcher = server.command_dispatcher.clone();
|
||||||
dispatcher.handle_command(
|
dispatcher.handle_command(
|
||||||
&mut commands::CommandSender::Console,
|
&mut commands::CommandSender::Console,
|
||||||
&mut server,
|
&server,
|
||||||
&out,
|
&out,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -163,8 +162,7 @@ fn main() -> io::Result<()> {
|
|||||||
let mut player = player.lock().unwrap();
|
let mut player = player.lock().unwrap();
|
||||||
player.client.poll(event).await;
|
player.client.poll(event).await;
|
||||||
if !player.client.closed {
|
if !player.client.closed {
|
||||||
let mut server = server.lock().await;
|
player.process_packets(&server).await;
|
||||||
player.process_packets(&mut server).await;
|
|
||||||
}
|
}
|
||||||
if player.client.closed {
|
if player.client.closed {
|
||||||
drop(player);
|
drop(player);
|
||||||
@ -181,8 +179,7 @@ fn main() -> io::Result<()> {
|
|||||||
let (done, make_player) = if let Some(client) = clients.get_mut(&token) {
|
let (done, make_player) = if let Some(client) = clients.get_mut(&token) {
|
||||||
client.poll(event).await;
|
client.poll(event).await;
|
||||||
if !client.closed {
|
if !client.closed {
|
||||||
let mut server = server.lock().await;
|
client.process_packets(&server).await;
|
||||||
client.process_packets(&mut server).await;
|
|
||||||
}
|
}
|
||||||
(client.closed, client.make_player)
|
(client.closed, client.make_player)
|
||||||
} else {
|
} else {
|
||||||
@ -195,7 +192,6 @@ fn main() -> io::Result<()> {
|
|||||||
poll.registry().deregister(&mut client.connection)?;
|
poll.registry().deregister(&mut client.connection)?;
|
||||||
} else if make_player {
|
} else if make_player {
|
||||||
let token = client.token;
|
let token = client.token;
|
||||||
let mut server = server.lock().await;
|
|
||||||
let (player, world) = server.add_player(token, client).await;
|
let (player, world) = server.add_player(token, client).await;
|
||||||
players.insert(token, player.clone());
|
players.insert(token, player.clone());
|
||||||
let mut world = world.lock().await;
|
let mut world = world.lock().await;
|
||||||
|
|||||||
@ -31,10 +31,7 @@ const SERVER: Token = Token(0);
|
|||||||
pub struct RCONServer {}
|
pub struct RCONServer {}
|
||||||
|
|
||||||
impl RCONServer {
|
impl RCONServer {
|
||||||
pub async fn new(
|
pub async fn new(config: &RCONConfig, server: Arc<Server>) -> Result<Self, io::Error> {
|
||||||
config: &RCONConfig,
|
|
||||||
server: Arc<tokio::sync::Mutex<Server>>,
|
|
||||||
) -> Result<Self, io::Error> {
|
|
||||||
assert!(config.enabled, "RCON is not enabled");
|
assert!(config.enabled, "RCON is not enabled");
|
||||||
let mut poll = Poll::new().unwrap();
|
let mut poll = Poll::new().unwrap();
|
||||||
let mut listener = TcpListener::bind(config.address).unwrap();
|
let mut listener = TcpListener::bind(config.address).unwrap();
|
||||||
@ -128,11 +125,7 @@ impl RCONClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle(
|
pub async fn handle(&mut self, server: &Arc<Server>, password: &str) -> bool {
|
||||||
&mut self,
|
|
||||||
server: &Arc<tokio::sync::Mutex<Server>>,
|
|
||||||
password: &str,
|
|
||||||
) -> bool {
|
|
||||||
if !self.closed {
|
if !self.closed {
|
||||||
loop {
|
loop {
|
||||||
match self.read_bytes() {
|
match self.read_bytes() {
|
||||||
@ -158,11 +151,7 @@ impl RCONClient {
|
|||||||
self.closed
|
self.closed
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn poll(
|
async fn poll(&mut self, server: &Arc<Server>, password: &str) -> Result<(), PacketError> {
|
||||||
&mut self,
|
|
||||||
server: &Arc<tokio::sync::Mutex<Server>>,
|
|
||||||
password: &str,
|
|
||||||
) -> Result<(), PacketError> {
|
|
||||||
loop {
|
loop {
|
||||||
let packet = match self.receive_packet().await? {
|
let packet = match self.receive_packet().await? {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
@ -193,11 +182,10 @@ impl RCONClient {
|
|||||||
PacketType::ExecCommand => {
|
PacketType::ExecCommand => {
|
||||||
if self.logged_in {
|
if self.logged_in {
|
||||||
let mut output = Vec::new();
|
let mut output = Vec::new();
|
||||||
let mut server = server.lock().await;
|
|
||||||
let dispatcher = server.command_dispatcher.clone();
|
let dispatcher = server.command_dispatcher.clone();
|
||||||
dispatcher.handle_command(
|
dispatcher.handle_command(
|
||||||
&mut crate::commands::CommandSender::Rcon(&mut output),
|
&mut crate::commands::CommandSender::Rcon(&mut output),
|
||||||
&mut server,
|
server,
|
||||||
packet.get_body(),
|
packet.get_body(),
|
||||||
);
|
);
|
||||||
for line in output {
|
for line in output {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ use pumpkin_protocol::{
|
|||||||
};
|
};
|
||||||
use pumpkin_world::dimension::Dimension;
|
use pumpkin_world::dimension::Dimension;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::RwLock;
|
||||||
use std::{
|
use std::{
|
||||||
io::Cursor,
|
io::Cursor,
|
||||||
path::Path,
|
path::Path,
|
||||||
@ -56,7 +57,7 @@ pub struct Server {
|
|||||||
/// Cache the registry so we don't have to parse it every time a player joins
|
/// Cache the registry so we don't have to parse it every time a player joins
|
||||||
pub cached_registry: Vec<Registry>,
|
pub cached_registry: Vec<Registry>,
|
||||||
|
|
||||||
pub open_containers: HashMap<u64, OpenContainer>,
|
pub open_containers: RwLock<HashMap<u64, OpenContainer>>,
|
||||||
pub drag_handler: DragHandler,
|
pub drag_handler: DragHandler,
|
||||||
entity_id: AtomicI32,
|
entity_id: AtomicI32,
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ impl Server {
|
|||||||
Self {
|
Self {
|
||||||
plugin_loader,
|
plugin_loader,
|
||||||
cached_registry: Registry::get_static(),
|
cached_registry: Registry::get_static(),
|
||||||
open_containers: HashMap::new(),
|
open_containers: RwLock::new(HashMap::new()),
|
||||||
drag_handler: DragHandler::new(),
|
drag_handler: DragHandler::new(),
|
||||||
// 0 is invalid
|
// 0 is invalid
|
||||||
entity_id: 2.into(),
|
entity_id: 2.into(),
|
||||||
@ -121,7 +122,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_player(
|
pub async fn add_player(
|
||||||
&mut self,
|
&self,
|
||||||
token: Token,
|
token: Token,
|
||||||
client: Client,
|
client: Client,
|
||||||
) -> (Arc<Mutex<Player>>, Arc<tokio::sync::Mutex<World>>) {
|
) -> (Arc<Mutex<Player>>, Arc<tokio::sync::Mutex<World>>) {
|
||||||
@ -148,8 +149,15 @@ impl Server {
|
|||||||
&self,
|
&self,
|
||||||
player_id: EntityId,
|
player_id: EntityId,
|
||||||
container_id: u64,
|
container_id: u64,
|
||||||
) -> Option<&Mutex<Box<dyn Container>>> {
|
) -> Option<Arc<Mutex<Box<dyn Container>>>> {
|
||||||
self.open_containers.get(&container_id)?.try_open(player_id)
|
let open_containers = self
|
||||||
|
.open_containers
|
||||||
|
.read()
|
||||||
|
.expect("open_containers is poisoned");
|
||||||
|
open_containers
|
||||||
|
.get(&container_id)?
|
||||||
|
.try_open(player_id)
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a Packet to all Players in all worlds
|
/// Sends a Packet to all Players in all worlds
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user