Allow disable encryption
This commit is contained in:
parent
92fef82bda
commit
1ddaca1406
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2031,6 +2031,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"pumpkin-config",
|
||||||
"pumpkin-core",
|
"pumpkin-core",
|
||||||
"pumpkin-macros",
|
"pumpkin-macros",
|
||||||
"pumpkin-world",
|
"pumpkin-world",
|
||||||
|
|||||||
@ -1,24 +1,39 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
// Packet compression
|
/// Packet compression
|
||||||
pub struct CompressionConfig {
|
pub struct CompressionConfig {
|
||||||
/// Is compression enabled ?
|
/// Is compression enabled ?
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub compression_info: CompressionInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
/// We have this in a Seperate struct so we can use it outside of the Config
|
||||||
|
pub struct CompressionInfo {
|
||||||
/// The compression threshold used when compression is enabled
|
/// The compression threshold used when compression is enabled
|
||||||
pub compression_threshold: u32,
|
pub threshold: u32,
|
||||||
/// A value between 0..9
|
/// A value between 0..9
|
||||||
/// 1 = Optimize for the best speed of encoding.
|
/// 1 = Optimize for the best speed of encoding.
|
||||||
/// 9 = Optimize for the size of data being encoded.
|
/// 9 = Optimize for the size of data being encoded.
|
||||||
pub compression_level: u32,
|
pub level: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CompressionInfo {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
threshold: 256,
|
||||||
|
level: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CompressionConfig {
|
impl Default for CompressionConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
compression_threshold: 256,
|
compression_info: Default::default(),
|
||||||
compression_level: 4,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ pub use pvp::PVPConfig;
|
|||||||
pub use rcon::RCONConfig;
|
pub use rcon::RCONConfig;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod compression;
|
pub mod compression;
|
||||||
mod pvp;
|
mod pvp;
|
||||||
mod rcon;
|
mod rcon;
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ version.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
pumpkin-config = { path = "../pumpkin-config" }
|
||||||
pumpkin-macros = { path = "../pumpkin-macros" }
|
pumpkin-macros = { path = "../pumpkin-macros" }
|
||||||
pumpkin-world = { path = "../pumpkin-world" }
|
pumpkin-world = { path = "../pumpkin-world" }
|
||||||
pumpkin-core = { path = "../pumpkin-core" }
|
pumpkin-core = { path = "../pumpkin-core" }
|
||||||
|
|||||||
@ -19,7 +19,7 @@ type Cipher = cfb8::Decryptor<aes::Aes128>;
|
|||||||
pub struct PacketDecoder {
|
pub struct PacketDecoder {
|
||||||
buf: BytesMut,
|
buf: BytesMut,
|
||||||
decompress_buf: BytesMut,
|
decompress_buf: BytesMut,
|
||||||
compression: Option<u32>,
|
compression: bool,
|
||||||
cipher: Option<Cipher>,
|
cipher: Option<Cipher>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ impl PacketDecoder {
|
|||||||
let packet_len_len = VarInt(packet_len).written_size();
|
let packet_len_len = VarInt(packet_len).written_size();
|
||||||
|
|
||||||
let mut data;
|
let mut data;
|
||||||
if self.compression.is_some() {
|
if self.compression {
|
||||||
r = &r[..packet_len as usize];
|
r = &r[..packet_len as usize];
|
||||||
|
|
||||||
let data_len = VarInt::decode(&mut r).map_err(|_| PacketError::TooLong)?.0;
|
let data_len = VarInt::decode(&mut r).map_err(|_| PacketError::TooLong)?.0;
|
||||||
@ -96,19 +96,26 @@ impl PacketDecoder {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_encryption(&mut self, key: &[u8; 16]) {
|
pub fn set_encryption(&mut self, key: Option<&[u8; 16]>) {
|
||||||
|
if let Some(key) = key {
|
||||||
assert!(self.cipher.is_none(), "encryption is already enabled");
|
assert!(self.cipher.is_none(), "encryption is already enabled");
|
||||||
|
|
||||||
let mut cipher = Cipher::new_from_slices(key, key).expect("invalid key");
|
let mut cipher = Cipher::new_from_slices(key, key).expect("invalid key");
|
||||||
|
|
||||||
// Don't forget to decrypt the data we already have.
|
// Don't forget to decrypt the data we already have.
|
||||||
|
|
||||||
Self::decrypt_bytes(&mut cipher, &mut self.buf);
|
Self::decrypt_bytes(&mut cipher, &mut self.buf);
|
||||||
|
|
||||||
self.cipher = Some(cipher);
|
self.cipher = Some(cipher);
|
||||||
|
} else {
|
||||||
|
assert!(self.cipher.is_some(), "encryption is already disabled");
|
||||||
|
|
||||||
|
self.cipher = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables ZLib Deompression
|
/// Sets ZLib Deompression
|
||||||
pub fn set_compression(&mut self, compression: Option<u32>) {
|
pub fn set_compression(&mut self, compression: bool) {
|
||||||
self.compression = compression;
|
self.compression = compression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use std::io::Write;
|
|||||||
|
|
||||||
use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit};
|
use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, KeyIvInit};
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
|
use pumpkin_config::compression::CompressionInfo;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ type Cipher = cfb8::Encryptor<aes::Aes128>;
|
|||||||
pub struct PacketEncoder {
|
pub struct PacketEncoder {
|
||||||
buf: BytesMut,
|
buf: BytesMut,
|
||||||
compress_buf: Vec<u8>,
|
compress_buf: Vec<u8>,
|
||||||
compression: Option<(u32, u32)>,
|
compression: Option<CompressionInfo>,
|
||||||
cipher: Option<Cipher>,
|
cipher: Option<Cipher>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,10 +41,10 @@ impl PacketEncoder {
|
|||||||
|
|
||||||
let data_len = self.buf.len() - start_len;
|
let data_len = self.buf.len() - start_len;
|
||||||
|
|
||||||
if let Some((threshold, compression_level)) = self.compression {
|
if let Some(compression) = &self.compression {
|
||||||
if data_len > threshold as usize {
|
if data_len > compression.threshold as usize {
|
||||||
let mut z =
|
let mut z =
|
||||||
ZlibEncoder::new(&self.buf[start_len..], Compression::new(compression_level));
|
ZlibEncoder::new(&self.buf[start_len..], Compression::new(compression.level));
|
||||||
|
|
||||||
self.compress_buf.clear();
|
self.compress_buf.clear();
|
||||||
|
|
||||||
@ -117,13 +118,20 @@ impl PacketEncoder {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_encryption(&mut self, key: &[u8; 16]) {
|
pub fn set_encryption(&mut self, key: Option<&[u8; 16]>) {
|
||||||
|
if let Some(key) = key {
|
||||||
assert!(self.cipher.is_none(), "encryption is already enabled");
|
assert!(self.cipher.is_none(), "encryption is already enabled");
|
||||||
|
|
||||||
self.cipher = Some(Cipher::new_from_slices(key, key).expect("invalid key"));
|
self.cipher = Some(Cipher::new_from_slices(key, key).expect("invalid key"));
|
||||||
|
} else {
|
||||||
|
assert!(self.cipher.is_some(), "encryption is disabled");
|
||||||
|
|
||||||
|
self.cipher = None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables ZLib Compression
|
/// Enables ZLib Compression
|
||||||
pub fn set_compression(&mut self, compression: Option<(u32, u32)>) {
|
pub fn set_compression(&mut self, compression: Option<CompressionInfo>) {
|
||||||
self.compression = compression;
|
self.compression = compression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,10 +26,9 @@ impl BlockId {
|
|||||||
.iter();
|
.iter();
|
||||||
|
|
||||||
let block_state = match properties {
|
let block_state = match properties {
|
||||||
Some(properties) => match block_states.find(|state| &state.properties == properties) {
|
Some(properties) => block_states
|
||||||
Some(state) => state,
|
.find(|state| &state.properties == properties)
|
||||||
None => return Err(WorldError::BlockStateIdNotFound),
|
.ok_or_else(|| WorldError::BlockStateIdNotFound)?,
|
||||||
},
|
|
||||||
None => block_states
|
None => block_states
|
||||||
.find(|state| state.is_default)
|
.find(|state| state.is_default)
|
||||||
.expect("Every Block should have at least 1 default state"),
|
.expect("Every Block should have at least 1 default state"),
|
||||||
|
|||||||
@ -135,6 +135,8 @@ impl Level {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_block() {}
|
||||||
|
|
||||||
/// Reads/Generates many chunks in a world
|
/// Reads/Generates many chunks in a world
|
||||||
/// MUST be called from a tokio runtime thread
|
/// MUST be called from a tokio runtime thread
|
||||||
///
|
///
|
||||||
@ -147,7 +149,6 @@ impl Level {
|
|||||||
) {
|
) {
|
||||||
chunks.into_par_iter().for_each(|at| {
|
chunks.into_par_iter().for_each(|at| {
|
||||||
if is_alive {
|
if is_alive {
|
||||||
dbg!("a");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut loaded_chunks = self.loaded_chunks.lock();
|
let mut loaded_chunks = self.loaded_chunks.lock();
|
||||||
@ -235,29 +236,21 @@ impl Level {
|
|||||||
|
|
||||||
// Read the file using the offset and size
|
// Read the file using the offset and size
|
||||||
let mut file_buf = {
|
let mut file_buf = {
|
||||||
let seek_result = region_file.seek(std::io::SeekFrom::Start(offset));
|
region_file
|
||||||
if seek_result.is_err() {
|
.seek(std::io::SeekFrom::Start(offset))
|
||||||
return Err(WorldError::RegionIsInvalid);
|
.map_err(|_| WorldError::RegionIsInvalid)?;
|
||||||
}
|
|
||||||
let mut out = vec![0; size];
|
let mut out = vec![0; size];
|
||||||
let read_result = region_file.read_exact(&mut out);
|
region_file
|
||||||
if read_result.is_err() {
|
.read_exact(&mut out)
|
||||||
return Err(WorldError::RegionIsInvalid);
|
.map_err(|_| WorldError::RegionIsInvalid)?;
|
||||||
}
|
|
||||||
out
|
out
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: check checksum to make sure chunk is not corrupted
|
// TODO: check checksum to make sure chunk is not corrupted
|
||||||
let header = file_buf.drain(0..5).collect_vec();
|
let header = file_buf.drain(0..5).collect_vec();
|
||||||
|
|
||||||
let compression = match Compression::from_byte(header[4]) {
|
let compression = Compression::from_byte(header[4])
|
||||||
Some(c) => c,
|
.ok_or_else(|| WorldError::Compression(CompressionError::UnknownCompression))?;
|
||||||
None => {
|
|
||||||
return Err(WorldError::Compression(
|
|
||||||
CompressionError::UnknownCompression,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let size = u32::from_be_bytes(header[..4].try_into().unwrap());
|
let size = u32::from_be_bytes(header[..4].try_into().unwrap());
|
||||||
|
|
||||||
@ -277,23 +270,15 @@ impl Level {
|
|||||||
Compression::Gzip => {
|
Compression::Gzip => {
|
||||||
let mut z = GzDecoder::new(&compressed_data[..]);
|
let mut z = GzDecoder::new(&compressed_data[..]);
|
||||||
let mut chunk_data = Vec::with_capacity(compressed_data.len());
|
let mut chunk_data = Vec::with_capacity(compressed_data.len());
|
||||||
match z.read_to_end(&mut chunk_data) {
|
z.read_to_end(&mut chunk_data)
|
||||||
Ok(_) => {}
|
.map_err(CompressionError::GZipError)?;
|
||||||
Err(e) => {
|
|
||||||
return Err(CompressionError::GZipError(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(chunk_data)
|
Ok(chunk_data)
|
||||||
}
|
}
|
||||||
Compression::Zlib => {
|
Compression::Zlib => {
|
||||||
let mut z = ZlibDecoder::new(&compressed_data[..]);
|
let mut z = ZlibDecoder::new(&compressed_data[..]);
|
||||||
let mut chunk_data = Vec::with_capacity(compressed_data.len());
|
let mut chunk_data = Vec::with_capacity(compressed_data.len());
|
||||||
match z.read_to_end(&mut chunk_data) {
|
z.read_to_end(&mut chunk_data)
|
||||||
Ok(_) => {}
|
.map_err(CompressionError::ZlibError)?;
|
||||||
Err(e) => {
|
|
||||||
return Err(CompressionError::ZlibError(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(chunk_data)
|
Ok(chunk_data)
|
||||||
}
|
}
|
||||||
Compression::None => Ok(compressed_data),
|
Compression::None => Ok(compressed_data),
|
||||||
|
|||||||
@ -107,7 +107,7 @@ impl Client {
|
|||||||
) {
|
) {
|
||||||
let shared_secret = server.decrypt(&encryption_response.shared_secret).unwrap();
|
let shared_secret = server.decrypt(&encryption_response.shared_secret).unwrap();
|
||||||
|
|
||||||
self.enable_encryption(&shared_secret)
|
self.set_encryption(Some(&shared_secret))
|
||||||
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
||||||
|
|
||||||
let mut gameprofile = self.gameprofile.lock();
|
let mut gameprofile = self.gameprofile.lock();
|
||||||
@ -115,6 +115,7 @@ impl Client {
|
|||||||
if BASIC_CONFIG.online_mode {
|
if BASIC_CONFIG.online_mode {
|
||||||
let hash = server.digest_secret(&shared_secret);
|
let hash = server.digest_secret(&shared_secret);
|
||||||
let ip = self.address.lock().ip();
|
let ip = self.address.lock().ip();
|
||||||
|
|
||||||
match authentication::authenticate(
|
match authentication::authenticate(
|
||||||
&gameprofile.as_ref().unwrap().name,
|
&gameprofile.as_ref().unwrap().name,
|
||||||
&hash,
|
&hash,
|
||||||
@ -123,15 +124,15 @@ impl Client {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(p) => {
|
Ok(profile) => {
|
||||||
// Check if player should join
|
// Check if player should join
|
||||||
if let Some(p) = &p.profile_actions {
|
if let Some(actions) = &profile.profile_actions {
|
||||||
if !ADVANCED_CONFIG
|
if !ADVANCED_CONFIG
|
||||||
.authentication
|
.authentication
|
||||||
.player_profile
|
.player_profile
|
||||||
.allow_banned_players
|
.allow_banned_players
|
||||||
{
|
{
|
||||||
if !p.is_empty() {
|
if !actions.is_empty() {
|
||||||
self.kick("Your account can't join");
|
self.kick("Your account can't join");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -140,28 +141,27 @@ impl Client {
|
|||||||
.player_profile
|
.player_profile
|
||||||
.allowed_actions
|
.allowed_actions
|
||||||
{
|
{
|
||||||
if !p.contains(allowed) {
|
if !actions.contains(allowed) {
|
||||||
self.kick("Your account can't join");
|
self.kick("Your account can't join");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*gameprofile = Some(p);
|
*gameprofile = Some(profile);
|
||||||
}
|
}
|
||||||
Err(e) => self.kick(&e.to_string()),
|
Err(e) => self.kick(&e.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for property in &gameprofile.as_ref().unwrap().properties {
|
for property in &gameprofile.as_ref().unwrap().properties {
|
||||||
// TODO: use this (this was the todo here before, ill add it again cuz its prob here for a reason)
|
unpack_textures(property, &ADVANCED_CONFIG.authentication.textures)
|
||||||
let _ = unpack_textures(property, &ADVANCED_CONFIG.authentication.textures);
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable compression
|
// enable compression
|
||||||
if ADVANCED_CONFIG.packet_compression.enabled {
|
if ADVANCED_CONFIG.packet_compression.enabled {
|
||||||
let threshold = ADVANCED_CONFIG.packet_compression.compression_threshold;
|
let compression = ADVANCED_CONFIG.packet_compression.compression_info.clone();
|
||||||
let level = ADVANCED_CONFIG.packet_compression.compression_level;
|
self.send_packet(&CSetCompression::new(compression.threshold.into()));
|
||||||
self.send_packet(&CSetCompression::new(threshold.into()));
|
self.set_compression(Some(compression));
|
||||||
self.set_compression(Some((threshold, level)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(profile) = gameprofile.as_ref() {
|
if let Some(profile) = gameprofile.as_ref() {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ use authentication::GameProfile;
|
|||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use mio::{event::Event, net::TcpStream, Token};
|
use mio::{event::Event, net::TcpStream, Token};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use pumpkin_config::compression::CompressionInfo;
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
bytebuf::{packet_id::Packet, DeserializerError},
|
bytebuf::{packet_id::Packet, DeserializerError},
|
||||||
client::{config::CConfigDisconnect, login::CLoginDisconnect},
|
client::{config::CConfigDisconnect, login::CLoginDisconnect},
|
||||||
@ -151,24 +152,29 @@ impl Client {
|
|||||||
client_packets_queue.push(packet);
|
client_packets_queue.push(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables encryption
|
/// Sets the Packet encryption
|
||||||
pub fn enable_encryption(
|
pub fn set_encryption(
|
||||||
&self,
|
&self,
|
||||||
shared_secret: &[u8], // decrypted
|
shared_secret: Option<&[u8]>, // decrypted
|
||||||
) -> Result<(), EncryptionError> {
|
) -> Result<(), EncryptionError> {
|
||||||
|
if let Some(shared_secret) = shared_secret {
|
||||||
self.encryption
|
self.encryption
|
||||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
let crypt_key: [u8; 16] = shared_secret
|
let crypt_key: [u8; 16] = shared_secret
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| EncryptionError::SharedWrongLength)?;
|
.map_err(|_| EncryptionError::SharedWrongLength)?;
|
||||||
self.dec.lock().enable_encryption(&crypt_key);
|
self.dec.lock().set_encryption(Some(&crypt_key));
|
||||||
self.enc.lock().enable_encryption(&crypt_key);
|
self.enc.lock().set_encryption(Some(&crypt_key));
|
||||||
|
} else {
|
||||||
|
self.dec.lock().set_encryption(None);
|
||||||
|
self.enc.lock().set_encryption(None);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compression threshold, Compression level
|
/// Sets the Packet compression
|
||||||
pub fn set_compression(&self, compression: Option<(u32, u32)>) {
|
pub fn set_compression(&self, compression: Option<CompressionInfo>) {
|
||||||
self.dec.lock().set_compression(compression.map(|v| v.0));
|
self.dec.lock().set_compression(compression.is_some());
|
||||||
self.enc.lock().set_compression(compression);
|
self.enc.lock().set_compression(compression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,14 +206,11 @@ impl Client {
|
|||||||
/// Processes all packets send by the client
|
/// Processes all packets send by the client
|
||||||
pub async fn process_packets(&self, server: &Arc<Server>) {
|
pub async fn process_packets(&self, server: &Arc<Server>) {
|
||||||
while let Some(mut packet) = self.client_packets_queue.lock().pop() {
|
while let Some(mut packet) = self.client_packets_queue.lock().pop() {
|
||||||
match self.handle_packet(server, &mut packet).await {
|
let _ = self.handle_packet(server, &mut packet).await.map_err(|e| {
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
let text = format!("Error while reading incoming packet {}", e);
|
let text = format!("Error while reading incoming packet {}", e);
|
||||||
log::error!("{}", text);
|
log::error!("{}", text);
|
||||||
self.kick(&text)
|
self.kick(&text)
|
||||||
}
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -131,7 +131,7 @@ impl Player {
|
|||||||
self.kick(TextComponent::text("Invalid movement"));
|
self.kick(TextComponent::text("Invalid movement"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !position_rotation.yaw.is_finite() || !position_rotation.pitch.is_finite() {
|
if position_rotation.yaw.is_infinite() || position_rotation.pitch.is_infinite() {
|
||||||
self.kick(TextComponent::text("Invalid rotation"));
|
self.kick(TextComponent::text("Invalid rotation"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,13 +140,10 @@ impl RCONClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we get a close here, we might have a reply, which we still want to write.
|
// If we get a close here, we might have a reply, which we still want to write.
|
||||||
match self.poll(server, password).await {
|
let _ = self.poll(server, password).await.map_err(|e| {
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("rcon error: {e}");
|
log::error!("rcon error: {e}");
|
||||||
self.closed = true;
|
self.closed = true;
|
||||||
}
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.closed
|
self.closed
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ impl CachedStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_response(config: &BasicConfiguration) -> StatusResponse {
|
pub fn build_response(config: &BasicConfiguration) -> StatusResponse {
|
||||||
let icon_path = concat!(env!("CARGO_MANIFEST_DIR"), "/icon.png");
|
let icon_path = "/icon.png";
|
||||||
let icon = if Path::new(icon_path).exists() {
|
let icon = if Path::new(icon_path).exists() {
|
||||||
Some(Self::load_icon(icon_path))
|
Some(Self::load_icon(icon_path))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -103,11 +103,11 @@ impl Server {
|
|||||||
};
|
};
|
||||||
// Basically the default world
|
// Basically the default world
|
||||||
// TODO: select default from config
|
// TODO: select default from config
|
||||||
let world = self.worlds[0].clone();
|
let world = &self.worlds[0];
|
||||||
|
|
||||||
let player = Arc::new(Player::new(client, world.clone(), entity_id, gamemode));
|
let player = Arc::new(Player::new(client, world.clone(), entity_id, gamemode));
|
||||||
world.add_player(token, player.clone());
|
world.add_player(token, player.clone());
|
||||||
(player, world)
|
(player, world.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_get_container(
|
pub fn try_get_container(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user