Made everything thread safe
- Also improved gamemode command - We now can use Server in commands
This commit is contained in:
parent
ddd3f1e781
commit
83aad86005
@ -37,8 +37,8 @@ impl<'a> ClientPacket for CPlayerInfoUpdate<'a> {
|
||||
});
|
||||
}
|
||||
PlayerAction::InitializeChat(_) => todo!(),
|
||||
PlayerAction::UpdateGameMode(_) => todo!(),
|
||||
PlayerAction::UpdateListed { listed } => p.put_bool(*listed),
|
||||
PlayerAction::UpdateGameMode(gamemode) => p.put_var_int(gamemode),
|
||||
PlayerAction::UpdateListed(listed) => p.put_bool(*listed),
|
||||
PlayerAction::UpdateLatency(_) => todo!(),
|
||||
PlayerAction::UpdateDisplayName(_) => todo!(),
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::Property;
|
||||
use crate::{Property, VarInt};
|
||||
|
||||
pub enum PlayerAction {
|
||||
AddPlayer {
|
||||
@ -6,10 +6,10 @@ pub enum PlayerAction {
|
||||
properties: Vec<Property>,
|
||||
},
|
||||
InitializeChat(u8),
|
||||
UpdateGameMode(u8),
|
||||
UpdateListed {
|
||||
listed: bool,
|
||||
},
|
||||
/// Gamemode ?
|
||||
UpdateGameMode(VarInt),
|
||||
/// Listed ?
|
||||
UpdateListed(bool),
|
||||
UpdateLatency(u8),
|
||||
UpdateDisplayName(u8),
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ use std::{
|
||||
io::{self, Write},
|
||||
net::SocketAddr,
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -70,7 +71,7 @@ pub struct Client {
|
||||
pub connection_state: ConnectionState,
|
||||
pub encryption: bool,
|
||||
pub closed: bool,
|
||||
pub token: Rc<Token>,
|
||||
pub token: Arc<Token>,
|
||||
pub connection: TcpStream,
|
||||
pub address: SocketAddr,
|
||||
enc: PacketEncoder,
|
||||
@ -81,7 +82,7 @@ pub struct Client {
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(token: Rc<Token>, connection: TcpStream, address: SocketAddr) -> Self {
|
||||
pub fn new(token: Arc<Token>, connection: TcpStream, address: SocketAddr) -> Self {
|
||||
Self {
|
||||
protocol_version: 0,
|
||||
gameprofile: None,
|
||||
|
||||
@ -174,8 +174,8 @@ impl Player {
|
||||
server.broadcast_packet(self, &CHeadRot::new(entity_id.into(), yaw as u8));
|
||||
}
|
||||
|
||||
pub fn handle_chat_command(&mut self, _server: &mut Server, command: SChatCommand) {
|
||||
handle_command(&mut CommandSender::Player(self), &command.command);
|
||||
pub fn handle_chat_command(&mut self, server: &mut Server, command: SChatCommand) {
|
||||
handle_command(&mut CommandSender::Player(self), server, &command.command);
|
||||
}
|
||||
|
||||
pub fn handle_player_ground(&mut self, _server: &mut Server, ground: SSetPlayerGround) {
|
||||
|
||||
@ -60,12 +60,12 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).with_child(
|
||||
require(&|sender| sender.permission_lvl() >= 2).with_child(
|
||||
argument(ARG_GAMEMODE, consume_arg_gamemode)
|
||||
.with_child(
|
||||
require(&|sender| sender.is_player()).execute(&|sender, args| {
|
||||
.with_child(require(&|sender| sender.is_player()).execute(
|
||||
&|sender, server, args| {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
|
||||
return if let Player(target) = sender {
|
||||
target.set_gamemode(gamemode);
|
||||
target.set_gamemode(server, gamemode);
|
||||
target.send_system_message(TextComponent::text(&format!(
|
||||
"Game mode was set to {:?}",
|
||||
gamemode
|
||||
@ -75,22 +75,22 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
} else {
|
||||
Err(InvalidRequirementError)
|
||||
};
|
||||
}),
|
||||
)
|
||||
.with_child(
|
||||
argument(ARG_TARGET, consume_arg_player).execute(&|sender, args| {
|
||||
},
|
||||
))
|
||||
.with_child(argument(ARG_TARGET, consume_arg_player).execute(
|
||||
&|sender, server, args| {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
let target = parse_arg_player(sender, ARG_TARGET, args)?;
|
||||
|
||||
target.set_gamemode(gamemode);
|
||||
target.set_gamemode(server, gamemode);
|
||||
target.send_system_message(TextComponent::text(&format!(
|
||||
"Set own game mode to {:?}",
|
||||
gamemode
|
||||
)));
|
||||
|
||||
Ok(())
|
||||
}),
|
||||
),
|
||||
},
|
||||
)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ fn parse_arg_command<'a>(
|
||||
pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION)
|
||||
.with_child(
|
||||
argument(ARG_COMMAND, consume_arg_command).execute(&|sender, args| {
|
||||
argument(ARG_COMMAND, consume_arg_command).execute(&|sender, _, args| {
|
||||
let dispatcher = DISPATCHER.get_or_init(dispatcher_init);
|
||||
|
||||
let tree = parse_arg_command(args, dispatcher)?;
|
||||
@ -50,7 +50,7 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
Ok(())
|
||||
}),
|
||||
)
|
||||
.execute(&|sender, _args| {
|
||||
.execute(&|sender, _, _args| {
|
||||
let dispatcher = DISPATCHER.get_or_init(dispatcher_init);
|
||||
|
||||
let mut keys: Vec<&str> = dispatcher.commands.keys().copied().collect();
|
||||
|
||||
@ -9,7 +9,7 @@ const NAMES: [&str; 1] = ["pumpkin"];
|
||||
const DESCRIPTION: &str = "Display information about Pumpkin.";
|
||||
|
||||
pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&|sender, _| {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&|sender, _, _| {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let description = env!("CARGO_PKG_DESCRIPTION");
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ const DESCRIPTION: &str = "Stop the server.";
|
||||
|
||||
pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).with_child(
|
||||
require(&|sender| sender.permission_lvl() >= 4).execute(&|sender, _args| {
|
||||
require(&|sender| sender.permission_lvl() >= 4).execute(&|sender, _, _args| {
|
||||
sender
|
||||
.send_message(TextComponent::text("Stopping Server").color_named(NamedColor::Red));
|
||||
std::process::exit(0)
|
||||
|
||||
@ -3,6 +3,7 @@ use crate::commands::dispatcher::InvalidTreeError::{
|
||||
};
|
||||
use crate::commands::tree::{Command, CommandTree, ConsumedArgs, NodeType, RawArgs};
|
||||
use crate::commands::CommandSender;
|
||||
use crate::server::Server;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -23,7 +24,12 @@ pub(crate) struct CommandDispatcher<'a> {
|
||||
/// Stores registered [CommandTree]s and dispatches commands to them.
|
||||
impl<'a> CommandDispatcher<'a> {
|
||||
/// Execute a command using its corresponding [CommandTree].
|
||||
pub(crate) fn dispatch(&'a self, src: &mut CommandSender, cmd: &str) -> Result<(), String> {
|
||||
pub(crate) fn dispatch(
|
||||
&'a self,
|
||||
src: &mut CommandSender,
|
||||
server: &mut Server,
|
||||
cmd: &str,
|
||||
) -> Result<(), String> {
|
||||
let mut parts = cmd.split_ascii_whitespace();
|
||||
let key = parts.next().ok_or("Empty Command")?;
|
||||
let raw_args: Vec<&str> = parts.rev().collect();
|
||||
@ -32,7 +38,7 @@ impl<'a> CommandDispatcher<'a> {
|
||||
|
||||
// try paths until fitting path is found
|
||||
for path in tree.iter_paths() {
|
||||
match Self::try_is_fitting_path(src, path, tree, raw_args.clone()) {
|
||||
match Self::try_is_fitting_path(src, server, path, tree, raw_args.clone()) {
|
||||
Err(InvalidConsumptionError(s)) => {
|
||||
println!("Error while parsing command \"{cmd}\": {s:?} was consumed, but couldn't be parsed");
|
||||
return Err("Internal Error (See logs for details)".into());
|
||||
@ -69,6 +75,7 @@ impl<'a> CommandDispatcher<'a> {
|
||||
|
||||
fn try_is_fitting_path(
|
||||
src: &mut CommandSender,
|
||||
server: &mut Server,
|
||||
path: Vec<usize>,
|
||||
tree: &CommandTree,
|
||||
mut raw_args: RawArgs,
|
||||
@ -79,7 +86,7 @@ impl<'a> CommandDispatcher<'a> {
|
||||
match node.node_type {
|
||||
NodeType::ExecuteLeaf { run } => {
|
||||
return if raw_args.is_empty() {
|
||||
run(src, &parsed_args)?;
|
||||
run(src, server, &parsed_args)?;
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
|
||||
@ -4,6 +4,7 @@ use std::sync::OnceLock;
|
||||
|
||||
use crate::commands::dispatcher::CommandDispatcher;
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
mod arg_player;
|
||||
mod cmd_gamemode;
|
||||
mod cmd_help;
|
||||
@ -83,10 +84,10 @@ fn dispatcher_init<'a>() -> CommandDispatcher<'a> {
|
||||
dispatcher
|
||||
}
|
||||
|
||||
pub fn handle_command(sender: &mut CommandSender, cmd: &str) {
|
||||
pub fn handle_command(sender: &mut CommandSender, server: &mut Server, cmd: &str) {
|
||||
let dispatcher = DISPATCHER.get_or_init(dispatcher_init);
|
||||
|
||||
if let Err(err) = dispatcher.dispatch(sender, cmd) {
|
||||
if let Err(err) = dispatcher.dispatch(sender, server, cmd) {
|
||||
sender.send_message(
|
||||
TextComponent::text(&err).color_named(pumpkin_core::text::color::NamedColor::Red),
|
||||
)
|
||||
|
||||
@ -2,6 +2,7 @@ use std::collections::{HashMap, VecDeque};
|
||||
|
||||
use crate::commands::dispatcher::InvalidTreeError;
|
||||
use crate::commands::CommandSender;
|
||||
use crate::server::Server;
|
||||
|
||||
/// see [crate::commands::tree_builder::argument]
|
||||
pub(crate) type RawArgs<'a> = Vec<&'a str>;
|
||||
@ -19,7 +20,8 @@ pub(crate) struct Node<'a> {
|
||||
|
||||
pub(crate) enum NodeType<'a> {
|
||||
ExecuteLeaf {
|
||||
run: &'a (dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync),
|
||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
||||
+ Sync),
|
||||
},
|
||||
#[allow(dead_code)] // todo: remove (so far no commands requiring this are implemented)
|
||||
Literal { string: &'a str },
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::commands::dispatcher::InvalidTreeError;
|
||||
use crate::commands::tree::{ArgumentConsumer, CommandTree, ConsumedArgs, Node, NodeType};
|
||||
use crate::commands::CommandSender;
|
||||
use crate::server::Server;
|
||||
|
||||
impl<'a> CommandTree<'a> {
|
||||
/// Add a child [Node] to the root of this [CommandTree].
|
||||
@ -41,7 +42,8 @@ impl<'a> CommandTree<'a> {
|
||||
/// Also see [NonLeafNodeBuilder::execute].
|
||||
pub fn execute(
|
||||
mut self,
|
||||
run: &'a (dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync),
|
||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
||||
+ Sync),
|
||||
) -> Self {
|
||||
let node = Node {
|
||||
node_type: NodeType::ExecuteLeaf { run },
|
||||
@ -117,7 +119,8 @@ impl<'a> NonLeafNodeBuilder<'a> {
|
||||
/// Also see [CommandTree::execute].
|
||||
pub fn execute(
|
||||
mut self,
|
||||
run: &'a (dyn Fn(&mut CommandSender, &ConsumedArgs) -> Result<(), InvalidTreeError> + Sync),
|
||||
run: &'a (dyn Fn(&mut CommandSender, &mut Server, &ConsumedArgs) -> Result<(), InvalidTreeError>
|
||||
+ Sync),
|
||||
) -> Self {
|
||||
self.leaf_nodes.push(LeafNodeBuilder {
|
||||
node_type: NodeType::ExecuteLeaf { run },
|
||||
|
||||
@ -7,7 +7,10 @@ use pumpkin_entity::{entity_type::EntityType, Entity, EntityId};
|
||||
use pumpkin_inventory::player::PlayerInventory;
|
||||
use pumpkin_protocol::{
|
||||
bytebuf::{packet_id::Packet, DeserializerError},
|
||||
client::play::{CGameEvent, CPlayDisconnect, CSyncPlayerPosition, CSystemChatMessage},
|
||||
client::play::{
|
||||
CGameEvent, CPlayDisconnect, CPlayerInfoUpdate, CSyncPlayerPosition, CSystemChatMessage,
|
||||
PlayerAction,
|
||||
},
|
||||
server::play::{
|
||||
SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract,
|
||||
SPlayPingRequest, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation,
|
||||
@ -139,8 +142,18 @@ impl Player {
|
||||
self.food_saturation = food_saturation;
|
||||
}
|
||||
|
||||
pub fn set_gamemode(&mut self, gamemode: GameMode) {
|
||||
pub fn set_gamemode(&mut self, server: &mut Server, gamemode: GameMode) {
|
||||
self.gamemode = gamemode;
|
||||
server.broadcast_packet(
|
||||
self,
|
||||
&CPlayerInfoUpdate::new(
|
||||
0x04,
|
||||
&[pumpkin_protocol::client::play::Player {
|
||||
uuid: self.client.gameprofile.as_ref().unwrap().id,
|
||||
actions: vec![PlayerAction::UpdateGameMode((self.gamemode as i32).into())],
|
||||
}],
|
||||
),
|
||||
);
|
||||
self.client
|
||||
.send_packet(&CGameEvent::new(3, gamemode.to_f32().unwrap()));
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@ static ALLOC: dhat::Alloc = dhat::Alloc;
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
fn main() -> io::Result<()> {
|
||||
use std::{borrow::BorrowMut, sync::{Arc, Mutex}};
|
||||
|
||||
use entity::player::Player;
|
||||
use pumpkin_core::text::{color::NamedColor, TextComponent};
|
||||
|
||||
@ -95,12 +97,16 @@ fn main() -> io::Result<()> {
|
||||
let rcon = advanced_configuration.rcon.clone();
|
||||
|
||||
let mut clients: HashMap<Token, Client> = HashMap::new();
|
||||
let mut players: HashMap<Rc<Token>, Rc<RefCell<Player>>> = HashMap::new();
|
||||
let mut players: HashMap<Arc<Token>, Arc<Mutex<Player>>> = HashMap::new();
|
||||
|
||||
let mut server = Server::new((basic_config, advanced_configuration));
|
||||
let mut server = Arc::new(Mutex::new(Server::new((
|
||||
basic_config,
|
||||
advanced_configuration,
|
||||
))));
|
||||
log::info!("Started Server took {}ms", time.elapsed().as_millis());
|
||||
log::info!("You now can connect to the server, Listening on {}", addr);
|
||||
|
||||
let server1 = server.clone();
|
||||
if use_console {
|
||||
thread::spawn(move || {
|
||||
let stdin = std::io::stdin();
|
||||
@ -111,15 +117,17 @@ fn main() -> io::Result<()> {
|
||||
.expect("Failed to read console line");
|
||||
|
||||
if !out.is_empty() {
|
||||
handle_command(&mut commands::CommandSender::Console, &out);
|
||||
let mut server = server1.lock().unwrap();
|
||||
handle_command(&mut commands::CommandSender::Console, &mut server, &out);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if rcon.enabled {
|
||||
tokio::spawn(async move {
|
||||
RCONServer::new(&rcon).await.unwrap();
|
||||
});
|
||||
let server = server.clone();
|
||||
// tokio::spawn(async move {
|
||||
// RCONServer::new(&rcon, &server).await.unwrap();
|
||||
// });
|
||||
}
|
||||
loop {
|
||||
if let Err(err) = poll.poll(&mut events, None) {
|
||||
@ -161,16 +169,17 @@ fn main() -> io::Result<()> {
|
||||
token,
|
||||
Interest::READABLE.add(Interest::WRITABLE),
|
||||
)?;
|
||||
let rc_token = Rc::new(token);
|
||||
let client = Client::new(Rc::clone(&rc_token), connection, addr);
|
||||
let rc_token = Arc::new(token);
|
||||
let client = Client::new(Arc::clone(&rc_token), connection, addr);
|
||||
clients.insert(token, client);
|
||||
},
|
||||
|
||||
token => {
|
||||
// Poll Players
|
||||
let done = if let Some(player) = players.get_mut(&token) {
|
||||
let mut player = player.borrow_mut();
|
||||
let mut player = player.lock().unwrap();
|
||||
player.client.poll(event).await;
|
||||
let mut server = server.lock().unwrap();
|
||||
player.process_packets(&mut server);
|
||||
player.client.closed
|
||||
} else {
|
||||
@ -179,8 +188,9 @@ fn main() -> io::Result<()> {
|
||||
|
||||
if done {
|
||||
if let Some(player) = players.remove(&token) {
|
||||
let mut server = server.lock().unwrap();
|
||||
server.remove_player(&token);
|
||||
let mut player = player.borrow_mut();
|
||||
let mut player = player.lock().unwrap();
|
||||
poll.registry().deregister(&mut player.client.connection)?;
|
||||
}
|
||||
}
|
||||
@ -189,6 +199,7 @@ fn main() -> io::Result<()> {
|
||||
// Maybe received an event for a TCP connection.
|
||||
let (done, make_player) = if let Some(client) = clients.get_mut(&token) {
|
||||
client.poll(event).await;
|
||||
let mut server = server.lock().unwrap();
|
||||
client.process_packets(&mut server).await;
|
||||
(client.closed, client.make_player)
|
||||
} else {
|
||||
@ -201,9 +212,10 @@ fn main() -> io::Result<()> {
|
||||
poll.registry().deregister(&mut client.connection)?;
|
||||
} else if make_player {
|
||||
let token = client.token.clone();
|
||||
let mut server = server.lock().unwrap();
|
||||
let player = server.add_player(token.clone(), client);
|
||||
players.insert(token, player.clone());
|
||||
let mut player = player.borrow_mut();
|
||||
let mut player = player.lock().unwrap();
|
||||
server.spawn_player(&mut player).await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{self, Read},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use mio::{
|
||||
@ -10,7 +11,7 @@ use mio::{
|
||||
use packet::{Packet, PacketError, PacketType};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{commands::handle_command, config::RCONConfig};
|
||||
use crate::{commands::handle_command, config::RCONConfig, server::Server};
|
||||
|
||||
mod packet;
|
||||
|
||||
@ -29,7 +30,7 @@ const SERVER: Token = Token(0);
|
||||
pub struct RCONServer {}
|
||||
|
||||
impl RCONServer {
|
||||
pub async fn new(config: &RCONConfig) -> Result<Self, io::Error> {
|
||||
pub async fn new(config: &RCONConfig, server: &Arc<Mutex<Server>>) -> Result<Self, io::Error> {
|
||||
assert!(config.enabled, "RCON is not enabled");
|
||||
let addr = format!("{}:{}", config.ip, config.port)
|
||||
.parse()
|
||||
@ -87,7 +88,7 @@ impl RCONServer {
|
||||
|
||||
token => {
|
||||
let done = if let Some(client) = connections.get_mut(&token) {
|
||||
client.handle(&password).await
|
||||
client.handle(&server, &password).await
|
||||
} else {
|
||||
false
|
||||
};
|
||||
@ -126,7 +127,7 @@ impl RCONClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle(&mut self, password: &str) -> bool {
|
||||
pub async fn handle(&mut self, server: &Arc<Mutex<Server>>, password: &str) -> bool {
|
||||
if !self.closed {
|
||||
loop {
|
||||
match self.read_bytes() {
|
||||
@ -141,7 +142,7 @@ impl RCONClient {
|
||||
}
|
||||
}
|
||||
// If we get a close here, we might have a reply, which we still want to write.
|
||||
match self.poll(password).await {
|
||||
match self.poll(server, password).await {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
log::error!("rcon error: {e}");
|
||||
@ -152,7 +153,11 @@ impl RCONClient {
|
||||
self.closed
|
||||
}
|
||||
|
||||
async fn poll(&mut self, password: &str) -> Result<(), PacketError> {
|
||||
async fn poll(
|
||||
&mut self,
|
||||
server: &Arc<Mutex<Server>>,
|
||||
password: &str,
|
||||
) -> Result<(), PacketError> {
|
||||
loop {
|
||||
let packet = match self.receive_packet().await? {
|
||||
Some(p) => p,
|
||||
@ -183,8 +188,10 @@ impl RCONClient {
|
||||
PacketType::ExecCommand => {
|
||||
if self.logged_in {
|
||||
let mut output = Vec::new();
|
||||
let mut server = server.lock().unwrap();
|
||||
handle_command(
|
||||
&mut crate::commands::CommandSender::Rcon(&mut output),
|
||||
&mut server,
|
||||
packet.get_body(),
|
||||
);
|
||||
for line in output {
|
||||
|
||||
@ -6,7 +6,7 @@ use std::{
|
||||
rc::Rc,
|
||||
sync::{
|
||||
atomic::{AtomicI32, Ordering},
|
||||
Arc,
|
||||
Arc, Mutex, MutexGuard,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
@ -33,7 +33,7 @@ use pumpkin_world::{dimension::Dimension, radial_chunk_iterator::RadialIterator,
|
||||
use pumpkin_registry::Registry;
|
||||
use rsa::{traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::sync::{mpsc, Mutex};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::{
|
||||
client::Client,
|
||||
@ -48,7 +48,7 @@ pub struct Server {
|
||||
pub private_key: RsaPrivateKey,
|
||||
pub public_key_der: Box<[u8]>,
|
||||
|
||||
pub world: Arc<Mutex<World>>,
|
||||
pub world: Arc<tokio::sync::Mutex<World>>,
|
||||
pub status_response: StatusResponse,
|
||||
// We cache the json response here so we don't parse it every time someone makes a Status request.
|
||||
// Keep in mind that we must parse this again, when the StatusResponse changes which usally happen when a player joins or leaves
|
||||
@ -60,7 +60,7 @@ pub struct Server {
|
||||
/// Cache the registry so we don't have to parse it every time a player joins
|
||||
pub cached_registry: Vec<Registry>,
|
||||
|
||||
pub current_players: HashMap<Rc<Token>, Rc<RefCell<Player>>>,
|
||||
pub current_players: HashMap<Arc<Token>, Arc<Mutex<Player>>>,
|
||||
|
||||
// TODO: replace with HashMap <World, Player>
|
||||
entity_id: AtomicI32, // TODO: place this into every world
|
||||
@ -108,7 +108,7 @@ impl Server {
|
||||
cached_registry: Registry::get_static(),
|
||||
// 0 is invalid
|
||||
entity_id: 2.into(),
|
||||
world: Arc::new(Mutex::new(world)),
|
||||
world: Arc::new(tokio::sync::Mutex::new(world)),
|
||||
public_key,
|
||||
cached_server_brand,
|
||||
private_key,
|
||||
@ -122,20 +122,20 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_player(&mut self, token: Rc<Token>, client: Client) -> Rc<RefCell<Player>> {
|
||||
pub fn add_player(&mut self, token: Arc<Token>, client: Client) -> Arc<Mutex<Player>> {
|
||||
let entity_id = self.new_entity_id();
|
||||
let gamemode = match self.base_config.default_gamemode {
|
||||
GameMode::Undefined => GameMode::Survival,
|
||||
game_mode => game_mode,
|
||||
};
|
||||
let player = Rc::new(RefCell::new(Player::new(client, entity_id, gamemode)));
|
||||
let player = Arc::new(Mutex::new(Player::new(client, entity_id, gamemode)));
|
||||
self.current_players.insert(token, player.clone());
|
||||
player
|
||||
}
|
||||
|
||||
pub fn remove_player(&mut self, token: &Token) {
|
||||
let player = self.current_players.remove(token).unwrap();
|
||||
let player = player.as_ref().borrow();
|
||||
let player = player.as_ref().lock().unwrap();
|
||||
// despawn the player
|
||||
// todo: put this into the entitiy struct
|
||||
let id = player.entity_id();
|
||||
@ -204,7 +204,7 @@ impl Server {
|
||||
name: gameprofile.name.clone(),
|
||||
properties: gameprofile.properties.clone(),
|
||||
},
|
||||
PlayerAction::UpdateListed { listed: true },
|
||||
PlayerAction::UpdateListed(true),
|
||||
],
|
||||
}],
|
||||
),
|
||||
@ -217,7 +217,7 @@ impl Server {
|
||||
.iter()
|
||||
.filter(|c| c.0 != &player.client.token)
|
||||
{
|
||||
let playerr = playerr.as_ref().borrow();
|
||||
let playerr = playerr.as_ref().lock().unwrap();
|
||||
let gameprofile = &playerr.client.gameprofile.as_ref().unwrap();
|
||||
entries.push(pumpkin_protocol::client::play::Player {
|
||||
uuid: gameprofile.id,
|
||||
@ -226,7 +226,7 @@ impl Server {
|
||||
name: gameprofile.name.clone(),
|
||||
properties: gameprofile.properties.clone(),
|
||||
},
|
||||
PlayerAction::UpdateListed { listed: true },
|
||||
PlayerAction::UpdateListed(true),
|
||||
],
|
||||
})
|
||||
}
|
||||
@ -262,7 +262,7 @@ impl Server {
|
||||
// spawn players for our client
|
||||
let token = player.client.token.clone();
|
||||
for (_, existing_player) in self.current_players.iter().filter(|c| c.0 != &token) {
|
||||
let existing_player = existing_player.as_ref().borrow();
|
||||
let existing_player = existing_player.as_ref().lock().unwrap();
|
||||
let entity = &existing_player.entity;
|
||||
let gameprofile = existing_player.client.gameprofile.as_ref().unwrap();
|
||||
player.client.send_packet(&CSpawnEntity::new(
|
||||
@ -297,13 +297,13 @@ impl Server {
|
||||
}
|
||||
|
||||
/// TODO: This definitly should be in world
|
||||
pub fn get_by_entityid(&self, from: &Player, id: EntityId) -> Option<RefMut<Player>> {
|
||||
pub fn get_by_entityid(&self, from: &Player, id: EntityId) -> Option<MutexGuard<Player>> {
|
||||
for (_, player) in self
|
||||
.current_players
|
||||
.iter()
|
||||
.filter(|c| c.0 != &from.client.token)
|
||||
{
|
||||
let player = player.borrow_mut();
|
||||
let player = player.lock().unwrap();
|
||||
if player.entity_id() == id {
|
||||
return Some(player);
|
||||
}
|
||||
@ -323,7 +323,7 @@ impl Server {
|
||||
.iter()
|
||||
.filter(|c| c.0 != &from.client.token)
|
||||
{
|
||||
let mut player = player.borrow_mut();
|
||||
let mut player = player.lock().unwrap();
|
||||
player.client.send_packet(packet);
|
||||
}
|
||||
}
|
||||
@ -338,7 +338,7 @@ impl Server {
|
||||
.iter()
|
||||
.filter(|c| !from.contains(&c.0.as_ref()))
|
||||
{
|
||||
let mut player = player.borrow_mut();
|
||||
let mut player = player.lock().unwrap();
|
||||
player.client.send_packet(packet);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user