quectocraft2/src/main.rs

105 lines
2.8 KiB
Rust
Raw Normal View History

2023-07-24 00:50:20 -04:00
use std::{collections::HashMap, time::Duration, net::ToSocketAddrs};
use event::ServerEvent;
use log::{info, error};
use tokio::{net::TcpListener, sync::mpsc::{Sender, self}, select};
use uuid::Uuid;
use crate::{client::run_client, event::ClientEvent};
mod event;
mod protocol;
mod ser;
mod varint;
mod client;
pub type JsonValue = serde_json::Value;
#[derive(Clone, Debug)]
pub struct ClientInfo {
addr: String,
port: u16,
proto_version: i32,
proto_name: &'static str,
}
#[derive(Debug)]
pub struct Player {
name: String,
uuid: Uuid,
}
struct Client {
tx: Sender<ServerEvent>,
keepalive: Option<i64>,
info: Option<ClientInfo>,
player: Option<Player>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let socket_addr = "0.0.0.0:25565".to_socket_addrs()?.next().expect("invalid server address");
let listener = TcpListener::bind(socket_addr).await?;
let mut clients = HashMap::new();
let mut next_id = 0;
let (c_tx, mut c_rx) = mpsc::channel(16);
let mut keepalive = tokio::time::interval(Duration::from_secs(15));
info!("listening on {socket_addr}");
loop { select! {
conn = listener.accept() => {
let c_tx = c_tx.clone();
let (stream, addr) = conn?;
let id = next_id;
next_id += 1;
let (s_tx, s_rx) = mpsc::channel(16);
clients.insert(id, Client {
tx: s_tx,
keepalive: None,
info: None,
player: None,
});
info!("#{id} connected from {addr}");
tokio::spawn(async move {
let c_tx2 = c_tx.clone();
match run_client(id, stream, c_tx, s_rx).await {
Ok(_) => info!("client {id} disconnected"),
Err(e) => error!("client {id} error: {e}"),
}
c_tx2.send((id, ClientEvent::Disconnect)).await.unwrap();
});
},
_ = keepalive.tick() => {
for (_, client) in &mut clients {
if client.keepalive.is_some() {
client.tx.send(ServerEvent::Disconnect(Some("Failed to respond to keep alives".to_owned()))).await?;
} else if client.player.is_some() {
let data = 1;
client.keepalive = Some(data);
client.tx.send(ServerEvent::KeepAlive(data)).await?;
}
}
},
ev = c_rx.recv() => {
let Some(ev) = ev else {
return Err("reciever closed".into());
};
let id = ev.0;
let client = clients.get_mut(&id).unwrap();
match ev.1 {
ClientEvent::Handshake(info) => client.info = Some(info),
ClientEvent::Join(player) => clients.get_mut(&id).unwrap().player = Some(player),
ClientEvent::Disconnect => { clients.remove(&id); },
ClientEvent::KeepAlive(data) => {
let client = clients.get_mut(&id).unwrap();
if client.keepalive == Some(data) {
client.keepalive = None;
} else {
client.keepalive = Some(0);
}
}
}
}
} }
}