improve Status Response

This commit is contained in:
Snowiiii
2024-07-29 09:21:12 +02:00
parent 419513d2e7
commit b5541ab5ba
8 changed files with 221 additions and 22 deletions

122
Cargo.lock generated
View File

@@ -2,12 +2,54 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytemuck"
version = "1.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "colored"
version = "2.1.0"
@@ -18,6 +60,15 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.13"
@@ -42,12 +93,43 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "fdeflate"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
dependencies = [
"simd-adler32",
]
[[package]]
name = "flate2"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "image"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10"
dependencies = [
"bytemuck",
"byteorder-lite",
"num-traits",
"png",
]
[[package]]
name = "itoa"
version = "1.0.11"
@@ -72,6 +154,16 @@ version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "miniz_oxide"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
"simd-adler32",
]
[[package]]
name = "mio"
version = "1.0.1"
@@ -91,6 +183,15 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_threads"
version = "0.1.7"
@@ -100,6 +201,19 @@ dependencies = [
"libc",
]
[[package]]
name = "png"
version = "0.17.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
dependencies = [
"bitflags",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
@@ -119,8 +233,10 @@ dependencies = [
name = "pumpkin"
version = "0.1.0"
dependencies = [
"base64",
"byteorder",
"crossbeam-channel",
"image",
"log",
"mio",
"serde",
@@ -175,6 +291,12 @@ dependencies = [
"serde",
]
[[package]]
name = "simd-adler32"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simple_logger"
version = "5.0.0"

View File

@@ -8,6 +8,9 @@ edition = "2021"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
base64 = "0.22.1"
image = { version = "0.25", default-features = false, features = ["png"]}
simple_logger = "5.0.0"
log = "0.4"
byteorder = "1"

BIN
pumpkin/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

View File

@@ -1,10 +1,11 @@
use crate::protocol::{
client::status::{CPingResponse, CStatusResponse},
server::{
handshake::SHandShake,
status::{SPingRequest, SStatusRequest},
},
StatusResponse, Version,
};
use super::Client;
@@ -26,15 +27,9 @@ impl ClientPacketProcessor for Client {
fn handle_status_request(&mut self, _status_request: SStatusRequest) {
dbg!("sending status");
let response = StatusResponse {
version: Version {
version: "1.21".into(),
protocol: 767,
},
description: "Pumpkin Server".into(),
};
self.send_packet(CStatusResponse::new(
serde_json::to_string(&response).unwrap(),
serde_json::to_string(&self.server.status_response).unwrap(),
))
}

View File

@@ -1,14 +1,18 @@
use std::{
collections::VecDeque,
io::{self, Write},
rc::Rc,
};
use crate::protocol::{
server::{
handshake::SHandShake,
status::{SPingRequest, SStatusRequest},
use crate::{
protocol::{
server::{
handshake::SHandShake,
status::{SPingRequest, SStatusRequest},
},
ClientPacket, RawPacket,
},
ClientPacket, RawPacket,
server::Server,
};
use crate::protocol::{bytebuf::buffer::ByteBuffer, ConnectionState};
@@ -21,6 +25,7 @@ pub mod player;
use client_packet::ClientPacketProcessor;
pub struct Client {
pub server: Rc<Server>,
pub connection_state: ConnectionState,
pub closed: bool,
pub connection: TcpStream,
@@ -29,8 +34,9 @@ pub struct Client {
}
impl Client {
pub fn new(connection: TcpStream) -> Self {
pub fn new(server: Rc<Server>, connection: TcpStream) -> Self {
Self {
server,
connection_state: ConnectionState::HandShake,
connection,
closed: false,

View File

@@ -8,10 +8,14 @@ const SERVER: Token = Token(0);
pub mod client;
pub mod protocol;
pub mod server;
#[cfg(not(target_os = "wasi"))]
fn main() -> io::Result<()> {
use std::rc::Rc;
use client::{interrupted, Client};
use server::Server;
simple_logger::SimpleLogger::new().init().unwrap();
@@ -22,11 +26,11 @@ fn main() -> io::Result<()> {
// Setup the TCP server socket.
let addr = "127.0.0.1:25565".parse().unwrap();
let mut server = TcpListener::bind(addr)?;
let mut listener = TcpListener::bind(addr)?;
// Register the server with poll we can receive events for it.
poll.registry()
.register(&mut server, SERVER, Interest::READABLE)?;
.register(&mut listener, SERVER, Interest::READABLE)?;
// Map of `Token` -> `TcpStream`.
let mut connections = HashMap::new();
@@ -35,7 +39,8 @@ fn main() -> io::Result<()> {
log::info!("You can connect to the server using `nc`:");
log::info!(" $ nc 127.0.0.1 9000");
log::info!("You'll see our welcome message and anything you type will be printed here.");
let server = Rc::new(Server::new());
loop {
if let Err(err) = poll.poll(&mut events, None) {
@@ -50,7 +55,7 @@ fn main() -> io::Result<()> {
SERVER => loop {
// Received an event for the TCP server socket, which
// indicates we can accept an connection.
let (mut connection, address) = match server.accept() {
let (mut connection, address) = match listener.accept() {
Ok((connection, address)) => (connection, address),
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
// If we get a `WouldBlock` error we know our
@@ -75,7 +80,7 @@ fn main() -> io::Result<()> {
Interest::READABLE.add(Interest::WRITABLE),
)?;
connections.insert(token, Client::new(connection));
connections.insert(token, Client::new(Rc::clone(&server), connection));
},
token => {
// Maybe received an event for a TCP connection.

View File

@@ -44,11 +44,26 @@ pub trait ClientPacket {
#[derive(Serialize, Deserialize)]
pub struct StatusResponse {
pub version: Version,
pub players: Players,
pub description: String,
// Players, favicon ...
pub favicon: String, // data:image/png;base64,<data>
// Players, favicon ...
}
#[derive(Serialize, Deserialize)]
pub struct Version {
pub version: String,
pub name: String,
pub protocol: u32,
}
#[derive(Serialize, Deserialize)]
pub struct Players {
pub max: u32,
pub online: u32,
pub sample: Sample,
}
#[derive(Serialize, Deserialize)]
pub struct Sample {
pub name: String,
pub id: String, // uuid
}

53
pumpkin/src/server.rs Normal file
View File

@@ -0,0 +1,53 @@
use std::io::Cursor;
use base64::{engine::general_purpose, Engine};
use crate::protocol::{Players, Sample, StatusResponse, Version};
pub struct Server {
pub status_response: StatusResponse,
}
impl Default for Server {
fn default() -> Self {
Self::new()
}
}
impl Server {
pub fn new() -> Self {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/icon.png");
let status_response = StatusResponse {
version: Version {
name: "1.21".into(),
protocol: 767,
},
players: Players {
max: 20,
online: 0,
sample: Sample {
name: "".into(),
id: "".into(),
},
},
description: "Pumpkin Server".into(),
favicon: Self::load_icon(path),
};
Self { status_response }
}
pub fn load_icon(path: &str) -> String {
let mut icon = match image::open(path).map_err(|e| panic!("error loading icon: {}", e)) {
Ok(icon) => icon,
Err(_) => return "".into(),
};
icon = icon.resize_exact(64, 64, image::imageops::FilterType::Triangle);
let mut image = Vec::new();
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
}
}