improve Status Response
This commit is contained in:
parent
419513d2e7
commit
b5541ab5ba
122
Cargo.lock
generated
122
Cargo.lock
generated
@ -2,12 +2,54 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
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]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
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]]
|
[[package]]
|
||||||
name = "colored"
|
name = "colored"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@ -18,6 +60,15 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"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]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.13"
|
version = "0.5.13"
|
||||||
@ -42,12 +93,43 @@ dependencies = [
|
|||||||
"powerfmt",
|
"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]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
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]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
@ -72,6 +154,16 @@ version = "0.4.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
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]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -91,6 +183,15 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
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]]
|
[[package]]
|
||||||
name = "num_threads"
|
name = "num_threads"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@ -100,6 +201,19 @@ dependencies = [
|
|||||||
"libc",
|
"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]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -119,8 +233,10 @@ dependencies = [
|
|||||||
name = "pumpkin"
|
name = "pumpkin"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
"image",
|
||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
"serde",
|
"serde",
|
||||||
@ -175,6 +291,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simple_logger"
|
name = "simple_logger"
|
||||||
version = "5.0.0"
|
version = "5.0.0"
|
||||||
|
|||||||
@ -8,6 +8,9 @@ edition = "2021"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
|
base64 = "0.22.1"
|
||||||
|
image = { version = "0.25", default-features = false, features = ["png"]}
|
||||||
|
|
||||||
simple_logger = "5.0.0"
|
simple_logger = "5.0.0"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
|||||||
BIN
pumpkin/icon.png
Normal file
BIN
pumpkin/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 277 B |
@ -1,10 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
use crate::protocol::{
|
use crate::protocol::{
|
||||||
client::status::{CPingResponse, CStatusResponse},
|
client::status::{CPingResponse, CStatusResponse},
|
||||||
server::{
|
server::{
|
||||||
handshake::SHandShake,
|
handshake::SHandShake,
|
||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
},
|
},
|
||||||
StatusResponse, Version,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Client;
|
use super::Client;
|
||||||
@ -26,15 +27,9 @@ impl ClientPacketProcessor for Client {
|
|||||||
|
|
||||||
fn handle_status_request(&mut self, _status_request: SStatusRequest) {
|
fn handle_status_request(&mut self, _status_request: SStatusRequest) {
|
||||||
dbg!("sending status");
|
dbg!("sending status");
|
||||||
let response = StatusResponse {
|
|
||||||
version: Version {
|
|
||||||
version: "1.21".into(),
|
|
||||||
protocol: 767,
|
|
||||||
},
|
|
||||||
description: "Pumpkin Server".into(),
|
|
||||||
};
|
|
||||||
self.send_packet(CStatusResponse::new(
|
self.send_packet(CStatusResponse::new(
|
||||||
serde_json::to_string(&response).unwrap(),
|
serde_json::to_string(&self.server.status_response).unwrap(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::protocol::{
|
use crate::{
|
||||||
server::{
|
protocol::{
|
||||||
handshake::SHandShake,
|
server::{
|
||||||
status::{SPingRequest, SStatusRequest},
|
handshake::SHandShake,
|
||||||
|
status::{SPingRequest, SStatusRequest},
|
||||||
|
},
|
||||||
|
ClientPacket, RawPacket,
|
||||||
},
|
},
|
||||||
ClientPacket, RawPacket,
|
server::Server,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::protocol::{bytebuf::buffer::ByteBuffer, ConnectionState};
|
use crate::protocol::{bytebuf::buffer::ByteBuffer, ConnectionState};
|
||||||
@ -21,6 +25,7 @@ pub mod player;
|
|||||||
use client_packet::ClientPacketProcessor;
|
use client_packet::ClientPacketProcessor;
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
|
pub server: Rc<Server>,
|
||||||
pub connection_state: ConnectionState,
|
pub connection_state: ConnectionState,
|
||||||
pub closed: bool,
|
pub closed: bool,
|
||||||
pub connection: TcpStream,
|
pub connection: TcpStream,
|
||||||
@ -29,8 +34,9 @@ pub struct Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(connection: TcpStream) -> Self {
|
pub fn new(server: Rc<Server>, connection: TcpStream) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
server,
|
||||||
connection_state: ConnectionState::HandShake,
|
connection_state: ConnectionState::HandShake,
|
||||||
connection,
|
connection,
|
||||||
closed: false,
|
closed: false,
|
||||||
|
|||||||
@ -8,10 +8,14 @@ const SERVER: Token = Token(0);
|
|||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod protocol;
|
pub mod protocol;
|
||||||
|
pub mod server;
|
||||||
|
|
||||||
#[cfg(not(target_os = "wasi"))]
|
#[cfg(not(target_os = "wasi"))]
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use client::{interrupted, Client};
|
use client::{interrupted, Client};
|
||||||
|
use server::Server;
|
||||||
|
|
||||||
simple_logger::SimpleLogger::new().init().unwrap();
|
simple_logger::SimpleLogger::new().init().unwrap();
|
||||||
|
|
||||||
@ -22,11 +26,11 @@ fn main() -> io::Result<()> {
|
|||||||
|
|
||||||
// Setup the TCP server socket.
|
// Setup the TCP server socket.
|
||||||
let addr = "127.0.0.1:25565".parse().unwrap();
|
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.
|
// Register the server with poll we can receive events for it.
|
||||||
poll.registry()
|
poll.registry()
|
||||||
.register(&mut server, SERVER, Interest::READABLE)?;
|
.register(&mut listener, SERVER, Interest::READABLE)?;
|
||||||
|
|
||||||
// Map of `Token` -> `TcpStream`.
|
// Map of `Token` -> `TcpStream`.
|
||||||
let mut connections = HashMap::new();
|
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!("You can connect to the server using `nc`:");
|
||||||
log::info!(" $ nc 127.0.0.1 9000");
|
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 {
|
loop {
|
||||||
if let Err(err) = poll.poll(&mut events, None) {
|
if let Err(err) = poll.poll(&mut events, None) {
|
||||||
@ -50,7 +55,7 @@ fn main() -> io::Result<()> {
|
|||||||
SERVER => loop {
|
SERVER => loop {
|
||||||
// Received an event for the TCP server socket, which
|
// Received an event for the TCP server socket, which
|
||||||
// indicates we can accept an connection.
|
// 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),
|
Ok((connection, address)) => (connection, address),
|
||||||
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||||
// If we get a `WouldBlock` error we know our
|
// If we get a `WouldBlock` error we know our
|
||||||
@ -75,7 +80,7 @@ fn main() -> io::Result<()> {
|
|||||||
Interest::READABLE.add(Interest::WRITABLE),
|
Interest::READABLE.add(Interest::WRITABLE),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
connections.insert(token, Client::new(connection));
|
connections.insert(token, Client::new(Rc::clone(&server), connection));
|
||||||
},
|
},
|
||||||
token => {
|
token => {
|
||||||
// Maybe received an event for a TCP connection.
|
// Maybe received an event for a TCP connection.
|
||||||
|
|||||||
@ -44,11 +44,26 @@ pub trait ClientPacket {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct StatusResponse {
|
pub struct StatusResponse {
|
||||||
pub version: Version,
|
pub version: Version,
|
||||||
|
pub players: Players,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
// Players, favicon ...
|
pub favicon: String, // data:image/png;base64,<data>
|
||||||
|
// Players, favicon ...
|
||||||
}
|
}
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Version {
|
pub struct Version {
|
||||||
pub version: String,
|
pub name: String,
|
||||||
pub protocol: u32,
|
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
53
pumpkin/src/server.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user