-
-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #89 from StripedMonkey/connection_refactor
Networking Refactor Pt. 2
- Loading branch information
Showing
13 changed files
with
260 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,32 @@ | ||
use pumpkin_macros::packet; | ||
use serde::Serialize; | ||
use serde::{ser::SerializeSeq, Serialize}; | ||
|
||
use crate::{uuid::UUID, VarInt}; | ||
use crate::VarInt; | ||
|
||
#[derive(Serialize)] | ||
#[packet(0x3D)] | ||
pub struct CRemovePlayerInfo<'a> { | ||
players_count: VarInt, | ||
players: &'a [UUID], | ||
#[serde(serialize_with = "serialize_slice_uuids")] | ||
players: &'a [uuid::Uuid], | ||
} | ||
|
||
impl<'a> CRemovePlayerInfo<'a> { | ||
pub fn new(players_count: VarInt, players: &'a [UUID]) -> Self { | ||
pub fn new(players_count: VarInt, players: &'a [uuid::Uuid]) -> Self { | ||
Self { | ||
players_count, | ||
players, | ||
} | ||
} | ||
} | ||
|
||
fn serialize_slice_uuids<S: serde::Serializer>( | ||
uuids: &[uuid::Uuid], | ||
serializer: S, | ||
) -> Result<S::Ok, S::Error> { | ||
let mut seq = serializer.serialize_seq(Some(uuids.len()))?; | ||
for uuid in uuids { | ||
seq.serialize_element(uuid.as_bytes())?; | ||
} | ||
seq.end() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
use std::{io::Cursor, path::Path}; | ||
|
||
use base64::{engine::general_purpose, Engine as _}; | ||
use image::GenericImageView as _; | ||
use pumpkin_config::{BasicConfiguration, BASIC_CONFIG}; | ||
use pumpkin_protocol::{ | ||
client::{config::CPluginMessage, status::CStatusResponse}, | ||
Players, Sample, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, | ||
}; | ||
|
||
use super::CURRENT_MC_VERSION; | ||
|
||
pub struct CachedStatus { | ||
_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 usually happen when a player joins or leaves | ||
status_response_json: String, | ||
} | ||
|
||
pub struct CachedBranding { | ||
/// Cached Server brand buffer so we don't have to rebuild them every time a player joins | ||
cached_server_brand: Vec<u8>, | ||
} | ||
|
||
impl CachedBranding { | ||
pub fn new() -> CachedBranding { | ||
let cached_server_brand = Self::build_brand(); | ||
CachedBranding { | ||
cached_server_brand, | ||
} | ||
} | ||
pub fn get_branding(&self) -> CPluginMessage { | ||
CPluginMessage::new("minecraft:brand", &self.cached_server_brand) | ||
} | ||
fn build_brand() -> Vec<u8> { | ||
let brand = "Pumpkin"; | ||
let mut buf = vec![]; | ||
let _ = VarInt(brand.len() as i32).encode(&mut buf); | ||
buf.extend_from_slice(brand.as_bytes()); | ||
buf | ||
} | ||
} | ||
|
||
impl CachedStatus { | ||
pub fn new() -> Self { | ||
let status_response = Self::build_response(&BASIC_CONFIG); | ||
let status_response_json = serde_json::to_string(&status_response) | ||
.expect("Failed to parse Status response into JSON"); | ||
|
||
CachedStatus { | ||
_status_response: status_response, | ||
status_response_json, | ||
} | ||
} | ||
|
||
pub fn get_status(&self) -> CStatusResponse<'_> { | ||
CStatusResponse::new(&self.status_response_json) | ||
} | ||
|
||
pub fn build_response(config: &BasicConfiguration) -> StatusResponse { | ||
let icon_path = concat!(env!("CARGO_MANIFEST_DIR"), "/icon.png"); | ||
let icon = if Path::new(icon_path).exists() { | ||
Some(Self::load_icon(icon_path)) | ||
} else { | ||
None | ||
}; | ||
|
||
StatusResponse { | ||
version: Some(Version { | ||
name: CURRENT_MC_VERSION.into(), | ||
protocol: CURRENT_MC_PROTOCOL, | ||
}), | ||
players: Some(Players { | ||
max: config.max_players, | ||
online: 0, | ||
sample: vec![Sample { | ||
name: "".into(), | ||
id: "".into(), | ||
}], | ||
}), | ||
description: config.motd.clone(), | ||
favicon: icon, | ||
enforece_secure_chat: false, | ||
} | ||
} | ||
|
||
fn load_icon(path: &str) -> String { | ||
let icon = match image::open(path).map_err(|e| panic!("error loading icon: {}", e)) { | ||
Ok(icon) => icon, | ||
Err(_) => return "".into(), | ||
}; | ||
let dimension = icon.dimensions(); | ||
assert!(dimension.0 == 64, "Icon width must be 64"); | ||
assert!(dimension.1 == 64, "Icon height must be 64"); | ||
let mut image = Vec::with_capacity(64 * 64 * 4); | ||
icon.write_to(&mut Cursor::new(&mut image), image::ImageFormat::Png) | ||
.unwrap(); | ||
let mut result = "data:image/png;base64,".to_owned(); | ||
general_purpose::STANDARD.encode_string(image, &mut result); | ||
result | ||
} | ||
} |
Oops, something went wrong.