mirror of
https://github.com/zyllian/classics.git
synced 2025-01-18 03:32:41 -08:00
add basic server configuration + password protection
This commit is contained in:
parent
ca94ec10f2
commit
c78303cf44
7 changed files with 146 additions and 17 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
server-config.json
|
||||||
|
|
45
Cargo.lock
generated
45
Cargo.lock
generated
|
@ -70,6 +70,8 @@ dependencies = [
|
||||||
"half",
|
"half",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rand",
|
"rand",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -131,6 +133,12 @@ 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 = "itoa"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.153"
|
version = "0.2.153"
|
||||||
|
@ -290,12 +298,49 @@ version = "0.1.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.198"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.198"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.116"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
|
|
@ -8,4 +8,6 @@ flate2 = "1"
|
||||||
half = "2"
|
half = "2"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
tokio = {version = "1", features = ["full"]}
|
tokio = {version = "1", features = ["full"]}
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,13 +1,32 @@
|
||||||
use server::Server;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use server::{config::ServerConfig, Server};
|
||||||
|
|
||||||
mod level;
|
mod level;
|
||||||
mod packet;
|
mod packet;
|
||||||
mod player;
|
mod player;
|
||||||
mod server;
|
mod server;
|
||||||
|
|
||||||
|
const CONFIG_FILE: &str = "./server-config.json";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
let mut server = Server::new().await?;
|
let config_path = PathBuf::from(CONFIG_FILE);
|
||||||
|
let config = if config_path.exists() {
|
||||||
|
serde_json::from_str(&std::fs::read_to_string(config_path)?)
|
||||||
|
.expect("failed to deserialize config")
|
||||||
|
} else {
|
||||||
|
let config = ServerConfig::default();
|
||||||
|
std::fs::write(
|
||||||
|
config_path,
|
||||||
|
serde_json::to_string_pretty(&config).expect("failed to serialize default config"),
|
||||||
|
)?;
|
||||||
|
config
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("starting server with config: {config:#?}");
|
||||||
|
|
||||||
|
let mut server = Server::new(config).await?;
|
||||||
|
|
||||||
server.run().await?;
|
server.run().await?;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod config;
|
||||||
mod network;
|
mod network;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -8,6 +9,8 @@ use tokio::{net::TcpListener, sync::RwLock};
|
||||||
|
|
||||||
use crate::{level::Level, player::Player};
|
use crate::{level::Level, player::Player};
|
||||||
|
|
||||||
|
use self::config::ServerConfig;
|
||||||
|
|
||||||
const DEFAULT_SERVER_SIZE: usize = 128;
|
const DEFAULT_SERVER_SIZE: usize = 128;
|
||||||
|
|
||||||
/// the server
|
/// the server
|
||||||
|
@ -28,18 +31,25 @@ pub struct ServerData {
|
||||||
pub players: Vec<Player>,
|
pub players: Vec<Player>,
|
||||||
/// list of player ids which have been freed up
|
/// list of player ids which have been freed up
|
||||||
pub free_player_ids: Vec<i8>,
|
pub free_player_ids: Vec<i8>,
|
||||||
|
/// the server's config
|
||||||
|
pub config: ServerConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
/// creates a new server with a generated level
|
/// creates a new server with a generated level
|
||||||
pub async fn new() -> std::io::Result<Self> {
|
pub async fn new(config: ServerConfig) -> std::io::Result<Self> {
|
||||||
println!("generating level");
|
println!("generating level");
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut level = Level::new(
|
let (level_x, level_y, level_z) = if let Some(size) = &config.level_size {
|
||||||
DEFAULT_SERVER_SIZE,
|
(size.x, size.y, size.z)
|
||||||
DEFAULT_SERVER_SIZE,
|
} else {
|
||||||
DEFAULT_SERVER_SIZE,
|
(
|
||||||
);
|
DEFAULT_SERVER_SIZE,
|
||||||
|
DEFAULT_SERVER_SIZE,
|
||||||
|
DEFAULT_SERVER_SIZE,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut level = Level::new(level_x, level_y, level_z);
|
||||||
for x in 0..level.x_size {
|
for x in 0..level.x_size {
|
||||||
for y in 0..(level.y_size / 2) {
|
for y in 0..(level.y_size / 2) {
|
||||||
for z in 0..level.z_size {
|
for z in 0..level.z_size {
|
||||||
|
@ -49,11 +59,11 @@ impl Server {
|
||||||
}
|
}
|
||||||
println!("done!");
|
println!("done!");
|
||||||
|
|
||||||
Self::new_with_level(level).await
|
Self::new_with_level(config, level).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// creates a new server with the given level
|
/// creates a new server with the given level
|
||||||
pub async fn new_with_level(level: Level) -> std::io::Result<Self> {
|
pub async fn new_with_level(config: ServerConfig, level: Level) -> std::io::Result<Self> {
|
||||||
let listener = TcpListener::bind("127.0.0.1:25565").await?;
|
let listener = TcpListener::bind("127.0.0.1:25565").await?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -61,6 +71,7 @@ impl Server {
|
||||||
level,
|
level,
|
||||||
players: Default::default(),
|
players: Default::default(),
|
||||||
free_player_ids: Vec::new(),
|
free_player_ids: Vec::new(),
|
||||||
|
config,
|
||||||
})),
|
})),
|
||||||
listener,
|
listener,
|
||||||
})
|
})
|
||||||
|
|
39
src/server/config.rs
Normal file
39
src/server/config.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// configuration for the server
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ServerConfig {
|
||||||
|
/// the server's name
|
||||||
|
pub name: String,
|
||||||
|
/// the server's motd
|
||||||
|
pub motd: String,
|
||||||
|
/// the server's password, if any
|
||||||
|
pub password: Option<String>,
|
||||||
|
/// the level's size
|
||||||
|
pub level_size: Option<ConfigCoordinates>,
|
||||||
|
/// the level's spawn point
|
||||||
|
pub spawn: Option<ConfigCoordinates>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ServerConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: "classic server wowie".to_string(),
|
||||||
|
motd: "here's the default server motd".to_string(),
|
||||||
|
password: None,
|
||||||
|
level_size: None,
|
||||||
|
spawn: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// coordinates as stored in configuration
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ConfigCoordinates {
|
||||||
|
/// the X coordinate
|
||||||
|
pub x: usize,
|
||||||
|
/// the Y coordinate
|
||||||
|
pub y: usize,
|
||||||
|
/// the Z coordinate
|
||||||
|
pub z: usize,
|
||||||
|
}
|
|
@ -98,12 +98,11 @@ async fn handle_stream_inner(
|
||||||
let mut reader = PacketReader::new(&read_buf);
|
let mut reader = PacketReader::new(&read_buf);
|
||||||
|
|
||||||
if let Some(packet) = ClientPacket::read(packet_buf[0], &mut reader) {
|
if let Some(packet) = ClientPacket::read(packet_buf[0], &mut reader) {
|
||||||
// println!("{packet:#?}");
|
|
||||||
match packet {
|
match packet {
|
||||||
ClientPacket::PlayerIdentification {
|
ClientPacket::PlayerIdentification {
|
||||||
protocol_version,
|
protocol_version,
|
||||||
username,
|
username,
|
||||||
verification_key: _,
|
verification_key,
|
||||||
_unused,
|
_unused,
|
||||||
} => {
|
} => {
|
||||||
if protocol_version != 0x07 {
|
if protocol_version != 0x07 {
|
||||||
|
@ -114,6 +113,12 @@ async fn handle_stream_inner(
|
||||||
|
|
||||||
let mut data = data.write().await;
|
let mut data = data.write().await;
|
||||||
|
|
||||||
|
if let Some(password) = &data.config.password {
|
||||||
|
if verification_key != *password {
|
||||||
|
return Ok(Some("Incorrect password!".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for player in &data.players {
|
for player in &data.players {
|
||||||
if player.username == username {
|
if player.username == username {
|
||||||
return Ok(Some(
|
return Ok(Some(
|
||||||
|
@ -144,8 +149,8 @@ async fn handle_stream_inner(
|
||||||
|
|
||||||
reply_queue.push_back(ServerPacket::ServerIdentification {
|
reply_queue.push_back(ServerPacket::ServerIdentification {
|
||||||
protocol_version: 0x07,
|
protocol_version: 0x07,
|
||||||
server_name: "test server".to_string(),
|
server_name: data.config.name.clone(),
|
||||||
server_motd: "whoaaaaaa".to_string(),
|
server_motd: data.config.motd.clone(),
|
||||||
user_type: PlayerType::Normal,
|
user_type: PlayerType::Normal,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -156,12 +161,19 @@ async fn handle_stream_inner(
|
||||||
let username = player.username.clone();
|
let username = player.username.clone();
|
||||||
data.players.push(player);
|
data.players.push(player);
|
||||||
|
|
||||||
|
let (spawn_x, spawn_y, spawn_z) =
|
||||||
|
if let Some(spawn) = &data.config.spawn {
|
||||||
|
(spawn.x, spawn.y, spawn.z)
|
||||||
|
} else {
|
||||||
|
(16, data.level.y_size / 2 + 2, 16)
|
||||||
|
};
|
||||||
|
|
||||||
let spawn_packet = ServerPacket::SpawnPlayer {
|
let spawn_packet = ServerPacket::SpawnPlayer {
|
||||||
player_id: *own_id,
|
player_id: *own_id,
|
||||||
player_name: username.clone(),
|
player_name: username.clone(),
|
||||||
x: f16::from_f32(16.5),
|
x: f16::from_f32(spawn_x as f32 + 0.5),
|
||||||
y: f16::from_f32((data.level.y_size / 2 + 2) as f32),
|
y: f16::from_f32(spawn_y as f32),
|
||||||
z: f16::from_f32(16.5),
|
z: f16::from_f32(spawn_z as f32 + 0.5),
|
||||||
yaw: 0,
|
yaw: 0,
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue