fix crash on join
This commit is contained in:
parent
090599b412
commit
37cac21899
14
configuration.toml
Normal file
14
configuration.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
server_address = "127.0.0.1"
|
||||||
|
server_port = 25565
|
||||||
|
seed = ""
|
||||||
|
max_plyers = -1
|
||||||
|
view_distances = 10
|
||||||
|
simulation_distance = 10
|
||||||
|
resource_pack = ""
|
||||||
|
resource_pack_sha1 = ""
|
||||||
|
default_difficulty = "Normal"
|
||||||
|
allow_nether = true
|
||||||
|
hardcore = false
|
||||||
|
online_mode = true
|
||||||
|
spawn_protection = 16
|
||||||
|
motd = "A Blazing fast Pumpkin Server!"
|
||||||
2
features.toml
Normal file
2
features.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
liquid_physics = true
|
||||||
|
encryption = true
|
||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::protocol::{
|
use crate::{
|
||||||
|
protocol::{
|
||||||
client::{
|
client::{
|
||||||
config::CFinishConfig,
|
config::CFinishConfig,
|
||||||
login::{CEncryptionRequest, CLoginSuccess},
|
login::{CEncryptionRequest, CLoginSuccess},
|
||||||
@ -11,69 +12,79 @@ use crate::protocol::{
|
|||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
},
|
},
|
||||||
ConnectionState,
|
ConnectionState,
|
||||||
|
},
|
||||||
|
server::Server,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Client, PlayerConfig};
|
use super::{Client, PlayerConfig};
|
||||||
|
|
||||||
pub trait ClientPacketProcessor {
|
pub trait ClientPacketProcessor {
|
||||||
// Handshake
|
// Handshake
|
||||||
fn handle_handshake(&mut self, handshake: SHandShake);
|
fn handle_handshake(&mut self, server: &mut Server, handshake: SHandShake);
|
||||||
// Status
|
// Status
|
||||||
fn handle_status_request(&mut self, status_request: SStatusRequest);
|
fn handle_status_request(&mut self, server: &mut Server, status_request: SStatusRequest);
|
||||||
fn handle_ping_request(&mut self, ping_request: SPingRequest);
|
fn handle_ping_request(&mut self, server: &mut Server, ping_request: SPingRequest);
|
||||||
// Login
|
// Login
|
||||||
fn handle_login_start(&mut self, login_start: SLoginStart);
|
fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart);
|
||||||
fn handle_encryption_response(&mut self, encryption_response: SEncryptionResponse);
|
fn handle_encryption_response(
|
||||||
fn handle_plugin_response(&mut self, plugin_response: SLoginPluginResponse);
|
&mut self,
|
||||||
fn handle_login_acknowledged(&mut self, login_acknowledged: SLoginAcknowledged);
|
server: &mut Server,
|
||||||
|
encryption_response: SEncryptionResponse,
|
||||||
|
);
|
||||||
|
fn handle_plugin_response(
|
||||||
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
plugin_response: SLoginPluginResponse,
|
||||||
|
);
|
||||||
|
fn handle_login_acknowledged(
|
||||||
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
login_acknowledged: SLoginAcknowledged,
|
||||||
|
);
|
||||||
// Config
|
// Config
|
||||||
fn handle_client_information(&mut self, client_information: SClientInformation);
|
fn handle_client_information(
|
||||||
fn handle_config_acknowledged(&mut self, config_acknowledged: SAcknowledgeFinishConfig);
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
client_information: SClientInformation,
|
||||||
|
);
|
||||||
|
fn handle_config_acknowledged(
|
||||||
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
config_acknowledged: SAcknowledgeFinishConfig,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientPacketProcessor for Client {
|
impl ClientPacketProcessor for Client {
|
||||||
fn handle_handshake(&mut self, handshake: SHandShake) {
|
fn handle_handshake(&mut self, _server: &mut Server, handshake: SHandShake) {
|
||||||
// TODO set protocol version and check protocol version
|
// TODO set protocol version and check protocol version
|
||||||
self.connection_state = handshake.next_state;
|
self.connection_state = handshake.next_state;
|
||||||
dbg!("handshake");
|
dbg!("handshake");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_status_request(&mut self, _status_request: SStatusRequest) {
|
fn handle_status_request(&mut self, server: &mut Server, _status_request: SStatusRequest) {
|
||||||
dbg!("sending status");
|
dbg!("sending status");
|
||||||
|
|
||||||
dbg!("test first");
|
let response = serde_json::to_string(&server.status_response).unwrap();
|
||||||
|
|
||||||
let guard = self.server.try_lock().unwrap();
|
|
||||||
dbg!("test");
|
|
||||||
|
|
||||||
let response = serde_json::to_string(&guard.status_response).unwrap();
|
|
||||||
drop(guard);
|
|
||||||
|
|
||||||
self.send_packet(CStatusResponse::new(response));
|
self.send_packet(CStatusResponse::new(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_ping_request(&mut self, ping_request: SPingRequest) {
|
fn handle_ping_request(&mut self, _server: &mut Server, ping_request: SPingRequest) {
|
||||||
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 handle_login_start(&mut self, login_start: SLoginStart) {
|
fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart) {
|
||||||
dbg!("login start");
|
dbg!("login start");
|
||||||
self.name = Some(login_start.name);
|
self.name = Some(login_start.name);
|
||||||
self.uuid = Some(login_start.uuid);
|
self.uuid = Some(login_start.uuid);
|
||||||
let verify_token: [u8; 4] = rand::random();
|
let verify_token: [u8; 4] = rand::random();
|
||||||
let public_key_der = self
|
let public_key_der = &server.public_key_der;
|
||||||
.server
|
|
||||||
.to_owned()
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.public_key_der
|
|
||||||
.clone(); // todo do not clone
|
|
||||||
let packet = CEncryptionRequest::new(
|
let packet = CEncryptionRequest::new(
|
||||||
"".into(),
|
"".into(),
|
||||||
public_key_der.len() as i32,
|
public_key_der.len() as i32,
|
||||||
&public_key_der,
|
public_key_der,
|
||||||
verify_token.len() as i32,
|
verify_token.len() as i32,
|
||||||
&verify_token,
|
&verify_token,
|
||||||
false, // TODO
|
false, // TODO
|
||||||
@ -81,27 +92,45 @@ impl ClientPacketProcessor for Client {
|
|||||||
self.send_packet(packet);
|
self.send_packet(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_encryption_response(&mut self, encryption_response: SEncryptionResponse) {
|
fn handle_encryption_response(
|
||||||
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
encryption_response: SEncryptionResponse,
|
||||||
|
) {
|
||||||
dbg!("encryption response");
|
dbg!("encryption response");
|
||||||
// should be impossible
|
// should be impossible
|
||||||
if self.uuid.is_none() || self.name.is_none() {
|
if self.uuid.is_none() || self.name.is_none() {
|
||||||
self.kick("UUID or Name is none".into());
|
self.kick("UUID or Name is none".into());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.enable_encryption(encryption_response.shared_secret)
|
self.enable_encryption(server, encryption_response.shared_secret)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let packet = CLoginSuccess::new(self.uuid.unwrap(), self.name.clone().unwrap(), 0, false);
|
let packet = CLoginSuccess::new(self.uuid.unwrap(), self.name.clone().unwrap(), 0, false);
|
||||||
self.send_packet(packet);
|
self.send_packet(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_plugin_response(&mut self, plugin_response: SLoginPluginResponse) {}
|
fn handle_plugin_response(
|
||||||
|
&mut self,
|
||||||
|
_server: &mut Server,
|
||||||
|
_plugin_response: SLoginPluginResponse,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_login_acknowledged(&mut self, login_acknowledged: SLoginAcknowledged) {
|
fn handle_login_acknowledged(
|
||||||
|
&mut self,
|
||||||
|
_server: &mut Server,
|
||||||
|
login_acknowledged: SLoginAcknowledged,
|
||||||
|
) {
|
||||||
|
let _ = login_acknowledged;
|
||||||
self.connection_state = ConnectionState::Config;
|
self.connection_state = ConnectionState::Config;
|
||||||
dbg!("login achnowlaged");
|
dbg!("login achnowlaged");
|
||||||
}
|
}
|
||||||
fn handle_client_information(&mut self, client_information: SClientInformation) {
|
fn handle_client_information(
|
||||||
|
&mut self,
|
||||||
|
_server: &mut Server,
|
||||||
|
client_information: SClientInformation,
|
||||||
|
) {
|
||||||
self.config = Some(PlayerConfig {
|
self.config = Some(PlayerConfig {
|
||||||
locale: client_information.locale,
|
locale: client_information.locale,
|
||||||
view_distance: client_information.view_distance,
|
view_distance: client_information.view_distance,
|
||||||
@ -116,10 +145,14 @@ impl ClientPacketProcessor for Client {
|
|||||||
self.send_packet(CFinishConfig::new());
|
self.send_packet(CFinishConfig::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_config_acknowledged(&mut self, config_acknowledged: SAcknowledgeFinishConfig) {
|
fn handle_config_acknowledged(
|
||||||
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
config_acknowledged: SAcknowledgeFinishConfig,
|
||||||
|
) {
|
||||||
dbg!("config acknowledged");
|
dbg!("config acknowledged");
|
||||||
self.connection_state = ConnectionState::Play;
|
self.connection_state = ConnectionState::Play;
|
||||||
// generate a player
|
// generate a player
|
||||||
self.server.lock().unwrap().spawn_player(&self.token);
|
server.spawn_player(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,10 @@ use std::{
|
|||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::player::{ChatMode, Hand},
|
entity::player::{ChatMode, Hand, Player},
|
||||||
protocol::{
|
protocol::{
|
||||||
client::{config::CConfigDisconnect, login::CLoginDisconnect},
|
client::{config::CConfigDisconnect, login::CLoginDisconnect},
|
||||||
server::{
|
server::{
|
||||||
@ -49,11 +48,12 @@ pub struct PlayerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
|
pub player: Option<Player>,
|
||||||
|
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub uuid: Option<uuid::Uuid>,
|
pub uuid: Option<uuid::Uuid>,
|
||||||
pub config: Option<PlayerConfig>,
|
pub config: Option<PlayerConfig>,
|
||||||
|
|
||||||
pub server: Arc<Mutex<Server>>,
|
|
||||||
pub connection_state: ConnectionState,
|
pub connection_state: ConnectionState,
|
||||||
pub encrytion: bool,
|
pub encrytion: bool,
|
||||||
pub closed: bool,
|
pub closed: bool,
|
||||||
@ -65,13 +65,13 @@ pub struct Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(server: Arc<Mutex<Server>>, token: Rc<Token>, connection: TcpStream) -> Self {
|
pub fn new(token: Rc<Token>, connection: TcpStream) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: None,
|
name: None,
|
||||||
uuid: None,
|
uuid: None,
|
||||||
config: None,
|
config: None,
|
||||||
server,
|
|
||||||
token,
|
token,
|
||||||
|
player: None,
|
||||||
connection_state: ConnectionState::HandShake,
|
connection_state: ConnectionState::HandShake,
|
||||||
connection,
|
connection,
|
||||||
enc: PacketEncoder::default(),
|
enc: PacketEncoder::default(),
|
||||||
@ -86,12 +86,13 @@ impl Client {
|
|||||||
self.client_packets_queue.push_back(packet);
|
self.client_packets_queue.push_back(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_encryption(&mut self, shared_secret: Vec<u8>) -> anyhow::Result<()> {
|
pub fn enable_encryption(
|
||||||
|
&mut self,
|
||||||
|
server: &mut Server,
|
||||||
|
shared_secret: Vec<u8>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
self.encrytion = true;
|
self.encrytion = true;
|
||||||
let shared_secret = self
|
let shared_secret = server
|
||||||
.server
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.private_key
|
.private_key
|
||||||
.decrypt(Pkcs1v15Encrypt, &shared_secret)
|
.decrypt(Pkcs1v15Encrypt, &shared_secret)
|
||||||
.context("failed to decrypt shared secret")?;
|
.context("failed to decrypt shared secret")?;
|
||||||
@ -110,21 +111,21 @@ impl Client {
|
|||||||
self.connection.write_all(&self.enc.take()).unwrap();
|
self.connection.write_all(&self.enc.take()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn procress_packets(&mut self) {
|
pub fn process_packets(&mut self, server: &mut Server) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < self.client_packets_queue.len() {
|
while i < self.client_packets_queue.len() {
|
||||||
let mut packet = self.client_packets_queue.remove(i).unwrap();
|
let mut packet = self.client_packets_queue.remove(i).unwrap();
|
||||||
self.handle_packet(&mut packet);
|
self.handle_packet(server, &mut packet);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_packet(&mut self, packet: &mut RawPacket) {
|
pub fn handle_packet(&mut self, server: &mut Server, packet: &mut RawPacket) {
|
||||||
dbg!("Handling packet");
|
dbg!("Handling packet");
|
||||||
let bytebuf = &mut packet.bytebuf;
|
let bytebuf = &mut packet.bytebuf;
|
||||||
match self.connection_state {
|
match self.connection_state {
|
||||||
crate::protocol::ConnectionState::HandShake => match packet.id {
|
crate::protocol::ConnectionState::HandShake => match packet.id {
|
||||||
SHandShake::PACKET_ID => self.handle_handshake(SHandShake::read(bytebuf)),
|
SHandShake::PACKET_ID => self.handle_handshake(server, SHandShake::read(bytebuf)),
|
||||||
_ => log::error!(
|
_ => log::error!(
|
||||||
"Failed to handle packet id {} while in Handshake state",
|
"Failed to handle packet id {} while in Handshake state",
|
||||||
packet.id
|
packet.id
|
||||||
@ -132,24 +133,28 @@ impl Client {
|
|||||||
},
|
},
|
||||||
crate::protocol::ConnectionState::Status => match packet.id {
|
crate::protocol::ConnectionState::Status => match packet.id {
|
||||||
SStatusRequest::PACKET_ID => {
|
SStatusRequest::PACKET_ID => {
|
||||||
self.handle_status_request(SStatusRequest::read(bytebuf))
|
self.handle_status_request(server, SStatusRequest::read(bytebuf))
|
||||||
|
}
|
||||||
|
SPingRequest::PACKET_ID => {
|
||||||
|
self.handle_ping_request(server, SPingRequest::read(bytebuf))
|
||||||
}
|
}
|
||||||
SPingRequest::PACKET_ID => self.handle_ping_request(SPingRequest::read(bytebuf)),
|
|
||||||
_ => log::error!(
|
_ => log::error!(
|
||||||
"Failed to handle packet id {} while in Status state",
|
"Failed to handle packet id {} while in Status state",
|
||||||
packet.id
|
packet.id
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
crate::protocol::ConnectionState::Login => match packet.id {
|
crate::protocol::ConnectionState::Login => match packet.id {
|
||||||
SLoginStart::PACKET_ID => self.handle_login_start(SLoginStart::read(bytebuf)),
|
SLoginStart::PACKET_ID => {
|
||||||
|
self.handle_login_start(server, SLoginStart::read(bytebuf))
|
||||||
|
}
|
||||||
SEncryptionResponse::PACKET_ID => {
|
SEncryptionResponse::PACKET_ID => {
|
||||||
self.handle_encryption_response(SEncryptionResponse::read(bytebuf))
|
self.handle_encryption_response(server, SEncryptionResponse::read(bytebuf))
|
||||||
}
|
}
|
||||||
SLoginPluginResponse::PACKET_ID => {
|
SLoginPluginResponse::PACKET_ID => {
|
||||||
self.handle_plugin_response(SLoginPluginResponse::read(bytebuf))
|
self.handle_plugin_response(server, SLoginPluginResponse::read(bytebuf))
|
||||||
}
|
}
|
||||||
SLoginAcknowledged::PACKET_ID => {
|
SLoginAcknowledged::PACKET_ID => {
|
||||||
self.handle_login_acknowledged(SLoginAcknowledged::read(bytebuf))
|
self.handle_login_acknowledged(server, SLoginAcknowledged::read(bytebuf))
|
||||||
}
|
}
|
||||||
_ => log::error!(
|
_ => log::error!(
|
||||||
"Failed to handle packet id {} while in Login state",
|
"Failed to handle packet id {} while in Login state",
|
||||||
@ -158,10 +163,10 @@ impl Client {
|
|||||||
},
|
},
|
||||||
crate::protocol::ConnectionState::Config => match packet.id {
|
crate::protocol::ConnectionState::Config => match packet.id {
|
||||||
SClientInformation::PACKET_ID => {
|
SClientInformation::PACKET_ID => {
|
||||||
self.handle_client_information(SClientInformation::read(bytebuf))
|
self.handle_client_information(server, SClientInformation::read(bytebuf))
|
||||||
}
|
}
|
||||||
SAcknowledgeFinishConfig::PACKET_ID => {
|
SAcknowledgeFinishConfig::PACKET_ID => {
|
||||||
self.handle_config_acknowledged(SAcknowledgeFinishConfig::read(bytebuf))
|
self.handle_config_acknowledged(server, SAcknowledgeFinishConfig::read(bytebuf))
|
||||||
}
|
}
|
||||||
_ => log::error!(
|
_ => log::error!(
|
||||||
"Failed to handle packet id {} while in Config state",
|
"Failed to handle packet id {} while in Config state",
|
||||||
@ -173,7 +178,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the connection is done.
|
/// Returns `true` if the connection is done.
|
||||||
pub fn poll(&mut self, _registry: &Registry, event: &Event) -> anyhow::Result<()> {
|
pub fn poll(&mut self, server: &mut Server, event: &Event) -> anyhow::Result<bool> {
|
||||||
if event.is_readable() {
|
if event.is_readable() {
|
||||||
let mut received_data = vec![0; 4096];
|
let mut received_data = vec![0; 4096];
|
||||||
let mut bytes_read = 0;
|
let mut bytes_read = 0;
|
||||||
@ -206,12 +211,12 @@ impl Client {
|
|||||||
self.dec.queue_slice(&received_data[..bytes_read]);
|
self.dec.queue_slice(&received_data[..bytes_read]);
|
||||||
if let Some(packet) = self.dec.decode()? {
|
if let Some(packet) = self.dec.decode()? {
|
||||||
self.add_packet(packet);
|
self.add_packet(packet);
|
||||||
self.procress_packets();
|
self.process_packets(server);
|
||||||
}
|
}
|
||||||
self.dec.clear();
|
self.dec.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(self.closed)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kick(&mut self, reason: String) {
|
pub fn kick(&mut self, reason: String) {
|
||||||
|
|||||||
@ -3,7 +3,6 @@ use std::io::Write;
|
|||||||
use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit};
|
use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit};
|
||||||
use anyhow::{ensure, Context};
|
use anyhow::{ensure, Context};
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use rsa::pkcs8::der::Encode;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::MAX_PACKET_SIZE,
|
client::MAX_PACKET_SIZE,
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::Client,
|
client::Client,
|
||||||
protocol::{ClientPacket, RawPacket, VarInt},
|
protocol::{ClientPacket, RawPacket, VarInt},
|
||||||
@ -7,24 +9,16 @@ use super::{Entity, EntityId};
|
|||||||
|
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
// All networking stuff
|
|
||||||
pub client: Client,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub fn new(entity: Entity, client: Client) -> Self {
|
pub fn new(entity: Entity) -> Self {
|
||||||
Self { entity, client }
|
Self { entity }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entity_id(&self) -> EntityId {
|
pub fn entity_id(&self) -> EntityId {
|
||||||
self.entity.entity_id
|
self.entity.entity_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_packet(&mut self, _packet: &mut RawPacket) {}
|
|
||||||
|
|
||||||
pub fn send_packet<P: ClientPacket>(&mut self, packet: P) {
|
|
||||||
self.client.send_packet(packet);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Hand {
|
pub enum Hand {
|
||||||
|
|||||||
@ -17,9 +17,13 @@ pub mod entity;
|
|||||||
pub mod protocol;
|
pub mod protocol;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
pub mod world;
|
||||||
|
|
||||||
#[cfg(not(target_os = "wasi"))]
|
#[cfg(not(target_os = "wasi"))]
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
|
use client::Client;
|
||||||
use configuration::AdvancedConfiguration;
|
use configuration::AdvancedConfiguration;
|
||||||
|
|
||||||
let basic_config = BasicConfiguration::load("configuration.toml");
|
let basic_config = BasicConfiguration::load("configuration.toml");
|
||||||
@ -44,9 +48,11 @@ fn main() -> io::Result<()> {
|
|||||||
// Unique token for each incoming connection.
|
// Unique token for each incoming connection.
|
||||||
let mut unique_token = Token(SERVER.0 + 1);
|
let mut unique_token = Token(SERVER.0 + 1);
|
||||||
|
|
||||||
|
let mut connections: HashMap<Token, Client> = HashMap::new();
|
||||||
|
|
||||||
log::info!("You now can connect to the server");
|
log::info!("You now can connect to the server");
|
||||||
|
|
||||||
let server = Arc::new(Mutex::new(Server::new()));
|
let mut server = Server::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Err(err) = poll.poll(&mut events, None) {
|
if let Err(err) = poll.poll(&mut events, None) {
|
||||||
@ -86,26 +92,20 @@ fn main() -> io::Result<()> {
|
|||||||
Interest::READABLE.add(Interest::WRITABLE),
|
Interest::READABLE.add(Interest::WRITABLE),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let rc_server = Arc::clone(&server);
|
connections.insert(token, Client::new(Rc::new(token), connection));
|
||||||
let mut guard = server.try_lock().unwrap();
|
|
||||||
guard.new_client(rc_server, connection, token);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
token => {
|
token => {
|
||||||
// Maybe received an event for a TCP connection.
|
// Maybe received an event for a TCP connection.
|
||||||
let done = if let Some(client) =
|
let done = if let Some(client) = connections.get_mut(&token) {
|
||||||
server.try_lock().unwrap().connections.get_mut(&token)
|
client.poll(&mut server, event).unwrap();
|
||||||
{
|
|
||||||
client.poll(poll.registry(), event).unwrap();
|
|
||||||
client.closed
|
client.closed
|
||||||
} else {
|
} else {
|
||||||
// Sporadic events happen, we can safely ignore them.
|
// Sporadic events happen, we can safely ignore them.
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
if done {
|
if done {
|
||||||
if let Some(mut client) =
|
if let Some(mut client) = connections.remove(&token) {
|
||||||
server.try_lock().unwrap().connections.remove(&token)
|
|
||||||
{
|
|
||||||
poll.registry().deregister(&mut client.connection)?;
|
poll.registry().deregister(&mut client.connection)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::protocol::{VarInt, VarLong};
|
use crate::protocol::{nbt::NBT, VarInt, VarLong};
|
||||||
|
|
||||||
use super::{Endian, CONTINUE_BIT, SEGMENT_BITS};
|
use super::{Endian, CONTINUE_BIT, SEGMENT_BITS};
|
||||||
use byteorder::{BigEndian, ByteOrder, LittleEndian};
|
use byteorder::{BigEndian, ByteOrder, LittleEndian};
|
||||||
@ -618,6 +618,15 @@ impl ByteBuffer {
|
|||||||
read_number!(self, read_f64, 8)
|
read_number!(self, read_f64, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_nbt(&mut self) -> Result<NBT> {
|
||||||
|
match NBT::deserialize_buf(self) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(err) => {
|
||||||
|
return Err(Error::new(ErrorKind::InvalidData, "Failed read nbt"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Read a string.
|
/// Read a string.
|
||||||
///
|
///
|
||||||
/// _Note_: First it reads a 32 bits value representing the size, then 'size' raw bytes
|
/// _Note_: First it reads a 32 bits value representing the size, then 'size' raw bytes
|
||||||
|
|||||||
@ -1,4 +1,26 @@
|
|||||||
use crate::protocol::ClientPacket;
|
use crate::protocol::{nbt::NBT, ClientPacket, VarInt};
|
||||||
|
|
||||||
|
pub struct CRegistryData {
|
||||||
|
registry_id: String,
|
||||||
|
entry_count: VarInt,
|
||||||
|
entries: NBT,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Entry {
|
||||||
|
entry_id: String,
|
||||||
|
has_data: bool,
|
||||||
|
data: NBT,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClientPacket for CRegistryData {
|
||||||
|
const PACKET_ID: VarInt = 0x07;
|
||||||
|
|
||||||
|
fn write(&self, bytebuf: &mut crate::protocol::bytebuf::buffer::ByteBuffer) {
|
||||||
|
bytebuf.write_string(&self.registry_id);
|
||||||
|
bytebuf.write_var_int(self.entry_count);
|
||||||
|
// bytebuf.write_array(self.entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CCookieRequest {
|
pub struct CCookieRequest {
|
||||||
// TODO
|
// TODO
|
||||||
@ -30,6 +52,12 @@ impl ClientPacket for CConfigDisconnect {
|
|||||||
|
|
||||||
pub struct CFinishConfig {}
|
pub struct CFinishConfig {}
|
||||||
|
|
||||||
|
impl Default for CFinishConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CFinishConfig {
|
impl CFinishConfig {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {}
|
Self {}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ pub struct CLogin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CLogin {
|
impl CLogin {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
entity_id: i32,
|
entity_id: i32,
|
||||||
is_hardcore: bool,
|
is_hardcore: bool,
|
||||||
|
|||||||
@ -6,6 +6,8 @@ use byteorder::ReadBytesExt;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod bytebuf;
|
pub mod bytebuf;
|
||||||
|
pub mod nbt;
|
||||||
|
mod registry;
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|||||||
105
pumpkin/src/protocol/nbt/deserialize.rs
Normal file
105
pumpkin/src/protocol/nbt/deserialize.rs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
use std::{collections::HashMap, error::Error, fmt, string::FromUtf8Error};
|
||||||
|
|
||||||
|
use crate::protocol::bytebuf::buffer::ByteBuffer;
|
||||||
|
|
||||||
|
use super::{Tag, NBT};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ParseError {
|
||||||
|
InvalidType(u8),
|
||||||
|
InvalidString(FromUtf8Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ParseError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::InvalidType(ty) => write!(f, "invalid tag type: {}", ty),
|
||||||
|
Self::InvalidString(e) => write!(f, "invalid string: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ParseError {}
|
||||||
|
|
||||||
|
impl NBT {
|
||||||
|
/// Deserializes the given byte array as nbt data.
|
||||||
|
pub fn deserialize(buf: Vec<u8>) -> Result<Self, ParseError> {
|
||||||
|
Self::deserialize_buf(&mut ByteBuffer::from_vec(buf))
|
||||||
|
}
|
||||||
|
/// Deserializes the given buffer as nbt data. This will continue reading
|
||||||
|
/// where this buffer is currently placed, and will advance the reader to be
|
||||||
|
/// right after the nbt data. If this function returns an error, then the
|
||||||
|
/// buffer will be in an undefined state (it will still be safe, but there are
|
||||||
|
/// no guarantees as too how far ahead the buffer will have been advanced).
|
||||||
|
pub fn deserialize_buf(buf: &mut ByteBuffer) -> Result<Self, ParseError> {
|
||||||
|
let ty = buf.read_u8().unwrap();
|
||||||
|
let len = buf.read_u16().unwrap();
|
||||||
|
let name = String::from_utf8(buf.read_bytes(len as usize).unwrap()).unwrap();
|
||||||
|
Ok(NBT::new(&name, Tag::deserialize(ty, buf)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tag {
|
||||||
|
fn deserialize(ty: u8, buf: &mut ByteBuffer) -> Result<Self, ParseError> {
|
||||||
|
match ty {
|
||||||
|
0 => Ok(Self::End),
|
||||||
|
1 => Ok(Self::Byte(buf.read_i8().unwrap())),
|
||||||
|
2 => Ok(Self::Short(buf.read_i16().unwrap())),
|
||||||
|
3 => Ok(Self::Int(buf.read_i32().unwrap())),
|
||||||
|
4 => Ok(Self::Long(buf.read_i64().unwrap())),
|
||||||
|
5 => Ok(Self::Float(buf.read_f32().unwrap())),
|
||||||
|
6 => Ok(Self::Double(buf.read_f64().unwrap())),
|
||||||
|
7 => {
|
||||||
|
let len = buf.read_i32().unwrap();
|
||||||
|
Ok(Self::ByteArr(buf.read_bytes(len as usize).unwrap()))
|
||||||
|
}
|
||||||
|
8 => {
|
||||||
|
let len = buf.read_u16().unwrap();
|
||||||
|
match String::from_utf8(buf.read_bytes(len as usize).unwrap()) {
|
||||||
|
Ok(v) => Ok(Self::String(v)),
|
||||||
|
Err(e) => Err(ParseError::InvalidString(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
9 => {
|
||||||
|
let inner_ty = buf.read_u8().unwrap();
|
||||||
|
let len = buf.read_i32().unwrap();
|
||||||
|
let mut inner = Vec::with_capacity(len as usize);
|
||||||
|
for _ in 0..len {
|
||||||
|
inner.push(Tag::deserialize(inner_ty, buf)?);
|
||||||
|
}
|
||||||
|
Ok(Self::List(inner))
|
||||||
|
}
|
||||||
|
10 => {
|
||||||
|
let mut inner = HashMap::new();
|
||||||
|
loop {
|
||||||
|
let ty = buf.read_u8().unwrap();
|
||||||
|
if ty == Self::End.ty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let len = buf.read_u16().unwrap();
|
||||||
|
let name = String::from_utf8(buf.read_bytes(len as usize).unwrap()).unwrap();
|
||||||
|
let tag = Tag::deserialize(ty, buf)?;
|
||||||
|
inner.insert(name, tag);
|
||||||
|
}
|
||||||
|
Ok(Self::Compound(inner))
|
||||||
|
}
|
||||||
|
11 => {
|
||||||
|
let len = buf.read_i32().unwrap();
|
||||||
|
let mut inner = Vec::with_capacity(len as usize);
|
||||||
|
for _ in 0..len {
|
||||||
|
inner.push(buf.read_i32().unwrap());
|
||||||
|
}
|
||||||
|
Ok(Self::IntArray(inner))
|
||||||
|
}
|
||||||
|
12 => {
|
||||||
|
let len = buf.read_i32().unwrap();
|
||||||
|
let mut inner = Vec::with_capacity(len as usize);
|
||||||
|
for _ in 0..len {
|
||||||
|
inner.push(buf.read_i64().unwrap());
|
||||||
|
}
|
||||||
|
Ok(Self::LongArray(inner))
|
||||||
|
}
|
||||||
|
_ => Err(ParseError::InvalidType(ty)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
115
pumpkin/src/protocol/nbt/mod.rs
Normal file
115
pumpkin/src/protocol/nbt/mod.rs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
mod deserialize;
|
||||||
|
mod serialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct NBT {
|
||||||
|
tag: Tag,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is a single tag. It does not contain a name, but has the actual data
|
||||||
|
/// for any of the nbt tags.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Tag {
|
||||||
|
End,
|
||||||
|
Byte(i8),
|
||||||
|
Short(i16),
|
||||||
|
Int(i32),
|
||||||
|
Long(i64),
|
||||||
|
Float(f32),
|
||||||
|
Double(f64),
|
||||||
|
ByteArr(Vec<u8>),
|
||||||
|
String(String),
|
||||||
|
List(Vec<Tag>), // All elements must be the same type, and un-named.
|
||||||
|
Compound(HashMap<String, Tag>), // Types can be any kind, and are named. Order is not defined.
|
||||||
|
IntArray(Vec<i32>),
|
||||||
|
LongArray(Vec<i64>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NBT {
|
||||||
|
/// Creates a new nbt tag. The tag value can be anything.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// This will panic if the tag is a list, and the values within that list
|
||||||
|
/// contain multiple types. This is a limitation with the nbt data format:
|
||||||
|
/// lists can only contain one type of data.
|
||||||
|
pub fn new(name: &str, tag: Tag) -> Self {
|
||||||
|
if let Tag::List(inner) = &tag {
|
||||||
|
if let Some(v) = inner.get(0) {
|
||||||
|
let ty = v.ty();
|
||||||
|
for v in inner {
|
||||||
|
if v.ty() != ty {
|
||||||
|
panic!("the given list contains multiple types: {:?}", inner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NBT {
|
||||||
|
tag,
|
||||||
|
name: name.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an empty nbt tag.
|
||||||
|
pub fn empty(name: &str) -> Self {
|
||||||
|
NBT {
|
||||||
|
tag: Tag::End,
|
||||||
|
name: name.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends the given element to the list. This will panic if self is not a
|
||||||
|
/// list, or if tag does not match the type of the existing elements.
|
||||||
|
pub fn list_add(&mut self, tag: Tag) {
|
||||||
|
if let Tag::List(inner) = &mut self.tag {
|
||||||
|
if let Some(v) = inner.get(0) {
|
||||||
|
if tag.ty() != v.ty() {
|
||||||
|
panic!(
|
||||||
|
"cannot add different types to list. current: {:?}, new: {:?}",
|
||||||
|
inner, tag
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
inner.push(tag);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No elements yet, so we add this no matter what type it is.
|
||||||
|
inner.push(tag);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("called list_add on non-list type: {:?}", self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends the given element to the compound. This will panic if self is not
|
||||||
|
/// a compound tag.
|
||||||
|
pub fn compound_add(&mut self, name: String, value: Tag) {
|
||||||
|
if let Tag::Compound(inner) = &mut self.tag {
|
||||||
|
inner.insert(name, value);
|
||||||
|
} else {
|
||||||
|
panic!("called compound_add on non-compound type: {:?}", self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If this is a compound tag, this returns the inner data of the tag.
|
||||||
|
/// Otherwise, this panics.
|
||||||
|
pub fn compound(&self) -> &HashMap<String, Tag> {
|
||||||
|
if let Tag::Compound(inner) = &self.tag {
|
||||||
|
&inner
|
||||||
|
} else {
|
||||||
|
panic!("called compound on non-compound type: {:?}", self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tag {
|
||||||
|
/// A simpler way to construct compound tags inline.
|
||||||
|
pub fn compound(value: &[(&str, Tag)]) -> Self {
|
||||||
|
let mut inner = HashMap::new();
|
||||||
|
for (name, tag) in value {
|
||||||
|
inner.insert(name.to_string(), tag.clone());
|
||||||
|
}
|
||||||
|
Self::Compound(inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
91
pumpkin/src/protocol/nbt/serialize.rs
Normal file
91
pumpkin/src/protocol/nbt/serialize.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use crate::protocol::bytebuf::buffer::ByteBuffer;
|
||||||
|
|
||||||
|
use super::{Tag, NBT};
|
||||||
|
|
||||||
|
impl NBT {
|
||||||
|
pub fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut out = ByteBuffer::new();
|
||||||
|
out.write_u8(self.tag.ty());
|
||||||
|
out.write_u16(self.name.len() as u16);
|
||||||
|
out.write_bytes(self.name.as_bytes());
|
||||||
|
out.write_bytes(&self.tag.serialize());
|
||||||
|
out.into_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tag {
|
||||||
|
/// Returns the type of the tag.
|
||||||
|
pub fn ty(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Self::End => 0,
|
||||||
|
Self::Byte(_) => 1,
|
||||||
|
Self::Short(_) => 2,
|
||||||
|
Self::Int(_) => 3,
|
||||||
|
Self::Long(_) => 4,
|
||||||
|
Self::Float(_) => 5,
|
||||||
|
Self::Double(_) => 6,
|
||||||
|
Self::ByteArr(_) => 7,
|
||||||
|
Self::String(_) => 8,
|
||||||
|
Self::List(_) => 9,
|
||||||
|
Self::Compound(_) => 10,
|
||||||
|
Self::IntArray(_) => 11,
|
||||||
|
Self::LongArray(_) => 12,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self) -> Vec<u8> {
|
||||||
|
let mut out = ByteBuffer::new();
|
||||||
|
match self {
|
||||||
|
Self::End => (),
|
||||||
|
Self::Byte(v) => out.write_i8(*v),
|
||||||
|
Self::Short(v) => out.write_i16(*v),
|
||||||
|
Self::Int(v) => out.write_i32(*v),
|
||||||
|
Self::Long(v) => out.write_i64(*v),
|
||||||
|
Self::Float(v) => out.write_f32(*v),
|
||||||
|
Self::Double(v) => out.write_f64(*v),
|
||||||
|
Self::ByteArr(v) => {
|
||||||
|
out.write_i32(v.len() as i32);
|
||||||
|
out.write_bytes(v);
|
||||||
|
}
|
||||||
|
Self::String(v) => {
|
||||||
|
out.write_u16(v.len() as u16);
|
||||||
|
out.write_bytes(v.as_bytes());
|
||||||
|
}
|
||||||
|
Self::List(v) => {
|
||||||
|
out.write_u8(v.get(0).unwrap_or(&Self::End).ty());
|
||||||
|
out.write_i32(v.len() as i32);
|
||||||
|
for tag in v {
|
||||||
|
out.write_bytes(&tag.serialize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::Compound(v) => {
|
||||||
|
for (name, tag) in v {
|
||||||
|
// Each element in the HashMap is essentially a NBT, but we store it in a
|
||||||
|
// separated form, so we have a manual implementation of serialize() here.
|
||||||
|
out.write_u8(tag.ty());
|
||||||
|
if tag.ty() == Self::End.ty() {
|
||||||
|
// End tags don't have a name, so we stop early.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.write_u16(name.len() as u16);
|
||||||
|
out.write_bytes(name.as_bytes());
|
||||||
|
out.write_bytes(&tag.serialize());
|
||||||
|
}
|
||||||
|
out.write_u8(Self::End.ty());
|
||||||
|
}
|
||||||
|
Self::IntArray(v) => {
|
||||||
|
out.write_i32(v.len() as i32);
|
||||||
|
for elem in v {
|
||||||
|
out.write_i32(*elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::LongArray(v) => {
|
||||||
|
out.write_i32(v.len() as i32);
|
||||||
|
for elem in v {
|
||||||
|
out.write_i64(*elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.into_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
0
pumpkin/src/protocol/registry/mod.rs
Normal file
0
pumpkin/src/protocol/registry/mod.rs
Normal file
@ -1,15 +1,13 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
borrow::BorrowMut,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::Cursor,
|
io::Cursor,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{
|
sync::atomic::{AtomicI32, Ordering},
|
||||||
atomic::{AtomicI32, Ordering},
|
|
||||||
Arc, Mutex,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
use mio::{net::TcpStream, Token};
|
use mio::{event::Event, net::TcpStream, Poll, Token};
|
||||||
use rsa::{rand_core::OsRng, traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey};
|
use rsa::{rand_core::OsRng, traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -20,6 +18,7 @@ use crate::{
|
|||||||
Entity, EntityId,
|
Entity, EntityId,
|
||||||
},
|
},
|
||||||
protocol::{client::play::CLogin, Players, Sample, StatusResponse, VarInt, Version},
|
protocol::{client::play::CLogin, Players, Sample, StatusResponse, VarInt, Version},
|
||||||
|
world::World,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
@ -33,12 +32,12 @@ pub struct Server {
|
|||||||
|
|
||||||
pub max_players: u32,
|
pub max_players: u32,
|
||||||
|
|
||||||
|
pub world: World,
|
||||||
|
|
||||||
pub status_response: StatusResponse,
|
pub status_response: StatusResponse,
|
||||||
pub connections: HashMap<Token, Client>,
|
|
||||||
|
|
||||||
// todo replace with HashMap <World, Player>
|
// todo replace with HashMap <World, Player>
|
||||||
entity_id: AtomicI32, // todo: place this into every world
|
entity_id: AtomicI32, // todo: place this into every world
|
||||||
pub players: Vec<Player>,
|
|
||||||
pub difficulty: Difficulty,
|
pub difficulty: Difficulty,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +64,7 @@ impl Server {
|
|||||||
Self {
|
Self {
|
||||||
// 0 is invalid
|
// 0 is invalid
|
||||||
entity_id: 2.into(),
|
entity_id: 2.into(),
|
||||||
|
world: World::new(),
|
||||||
online_mode: true,
|
online_mode: true,
|
||||||
encryption: true,
|
encryption: true,
|
||||||
compression_threshold: None, // 256
|
compression_threshold: None, // 256
|
||||||
@ -73,23 +73,29 @@ impl Server {
|
|||||||
max_players,
|
max_players,
|
||||||
status_response,
|
status_response,
|
||||||
public_key_der,
|
public_key_der,
|
||||||
connections: HashMap::new(),
|
|
||||||
players: Vec::new(),
|
|
||||||
difficulty: Difficulty::Normal,
|
difficulty: Difficulty::Normal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_client(&mut self, rc: Arc<Mutex<Server>>, connection: TcpStream, token: Token) {
|
// Returns Tokens to remove
|
||||||
self.connections
|
pub fn poll(
|
||||||
.insert(token, Client::new(rc, Rc::new(token), connection));
|
&mut self,
|
||||||
|
client: &mut Client,
|
||||||
|
poll: &Poll,
|
||||||
|
event: &Event,
|
||||||
|
) -> anyhow::Result<bool> {
|
||||||
|
// todo, Poll players in every world
|
||||||
|
client.poll(self, event)
|
||||||
}
|
}
|
||||||
|
//CLIENT KOMMT in den Player
|
||||||
pub fn spawn_player(&mut self, token: &Token) {
|
pub fn spawn_player(&mut self, client: &mut Client) {
|
||||||
let mut player = Player {
|
let player = Player {
|
||||||
entity: Entity::new(self.new_entity_id()),
|
entity: Entity {
|
||||||
client: self.connections.remove(token).unwrap(),
|
entity_id: self.new_entity_id(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
player.send_packet(CLogin::new(
|
|
||||||
|
client.send_packet(CLogin::new(
|
||||||
player.entity_id(),
|
player.entity_id(),
|
||||||
self.difficulty == Difficulty::Hard,
|
self.difficulty == Difficulty::Hard,
|
||||||
1,
|
1,
|
||||||
@ -114,7 +120,7 @@ impl Server {
|
|||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.players.push(player);
|
client.player = Some(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
// move to world
|
// move to world
|
||||||
|
|||||||
22
pumpkin/src/world.rs
Normal file
22
pumpkin/src/world.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use mio::Token;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
entity::{
|
||||||
|
player::{GameMode, Player},
|
||||||
|
Entity,
|
||||||
|
},
|
||||||
|
protocol::{client::play::CLogin, VarInt},
|
||||||
|
server::Difficulty,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct World {
|
||||||
|
pub players: Vec<Player>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl World {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
players: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user