102 lines
3.2 KiB
Rust
102 lines
3.2 KiB
Rust
use log::{error, info};
|
|
use simple_logger::SimpleLogger;
|
|
use std::io::Write;
|
|
use std::net::{SocketAddr, TcpListener};
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
mod command;
|
|
mod config;
|
|
mod error;
|
|
mod extensions;
|
|
mod network;
|
|
mod player;
|
|
mod utils;
|
|
mod world;
|
|
|
|
use config::Config;
|
|
use error::AppError;
|
|
use extensions::{Extensions, PlayersWrapper, WorldWrapper};
|
|
use network::handle_client;
|
|
use player::{Player, SpecialPlayers};
|
|
use utils::{client_disconnect, server_identification};
|
|
use world::World;
|
|
|
|
fn main() {
|
|
SimpleLogger::new().with_threads(true).init().unwrap();
|
|
|
|
if let Err(err) = run() {
|
|
error!("FATAL: {}", err);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
fn run() -> Result<(), AppError> {
|
|
let config = Config::load()?;
|
|
|
|
let players: [Player; 255] = core::array::from_fn(|_| Player::default());
|
|
let players_arc = Arc::new(Mutex::new(players));
|
|
|
|
let world_instance: World = World::load(&config.world)?;
|
|
let world_arc = Arc::new(Mutex::new(world_instance));
|
|
|
|
let addr = SocketAddr::from(([0, 0, 0, 0], config.server.port));
|
|
let listener = TcpListener::bind(addr)?;
|
|
|
|
let mut thread_number: u8 = 0;
|
|
|
|
let world_arc_clone_main_thread = Arc::clone(&world_arc);
|
|
let world_config_clone = config.clone().world;
|
|
ctrlc::set_handler(move || {
|
|
println!();
|
|
info!("SAVING");
|
|
World::save(&world_config_clone, world_arc_clone_main_thread.clone()).unwrap(); // Fortnite save the world
|
|
std::process::exit(0);
|
|
})
|
|
.expect("Error handling control C, save on exit will not work");
|
|
|
|
let extensions = Arc::new(Extensions::init(
|
|
PlayersWrapper::new(players_arc.clone()),
|
|
WorldWrapper::new(world_arc.clone()),
|
|
)?);
|
|
|
|
info!("Server listening on {}", config.server.port);
|
|
|
|
for stream in listener.incoming() {
|
|
let players_arc_clone = Arc::clone(&players_arc);
|
|
let world_arc_clone = Arc::clone(&world_arc);
|
|
let extensions_arc_clone = Arc::clone(&extensions);
|
|
let mut insertion_attempts: u8 = 0;
|
|
while players_arc.lock()?[thread_number as usize].id != SpecialPlayers::SelfPlayer as u8
|
|
&& insertion_attempts < config.server.max_players
|
|
{
|
|
insertion_attempts += 1;
|
|
// One is reserved for communications
|
|
if thread_number < config.server.max_players - 1 {
|
|
thread_number += 1;
|
|
} else {
|
|
thread_number = 0;
|
|
}
|
|
}
|
|
if insertion_attempts == config.server.max_players {
|
|
// Server must be full
|
|
// Seems silly that we have to ident to kick clients, but I didn't make the protocol
|
|
let mut disconnect_packets: Vec<u8> = Vec::new();
|
|
disconnect_packets
|
|
.extend_from_slice(&server_identification(config.server.clone(), false));
|
|
disconnect_packets
|
|
.extend_from_slice(&client_disconnect("Server is full! Try again later"));
|
|
stream?.write_all(&disconnect_packets)?;
|
|
} else {
|
|
handle_client(
|
|
config.clone().server,
|
|
stream?,
|
|
thread_number,
|
|
players_arc_clone,
|
|
world_arc_clone,
|
|
extensions_arc_clone,
|
|
);
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|