151 lines
6.1 KiB
Rust
151 lines
6.1 KiB
Rust
#![feature(lock_value_accessors)]
|
|
pub mod connection;
|
|
pub mod player;
|
|
pub mod server;
|
|
pub mod world;
|
|
|
|
use std::{
|
|
sync::{Arc, atomic::Ordering},
|
|
time::Duration,
|
|
};
|
|
|
|
use connection::Client;
|
|
use player::Player;
|
|
use potato_data::text_component::TextComponent;
|
|
use potato_protocol::packet::clientbound;
|
|
use server::Server;
|
|
use tokio::{net::TcpListener, time::interval};
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
let server = PotatoServer::new();
|
|
|
|
server.listen_for_connections().await;
|
|
}
|
|
|
|
pub struct PotatoServer {
|
|
server: Server,
|
|
}
|
|
|
|
impl PotatoServer {
|
|
pub fn new() -> Self {
|
|
PotatoServer {
|
|
server: Server::new(),
|
|
}
|
|
}
|
|
|
|
pub async fn listen_for_connections(&self) {
|
|
let listener = TcpListener::bind("0.0.0.0:25565")
|
|
.await
|
|
.expect("Failed to start listening on port 25565");
|
|
println!("listening started, ready to accept");
|
|
|
|
loop {
|
|
if let Ok((stream, _)) = listener.accept().await {
|
|
let (stream_read, mut stream_send) = stream.into_split();
|
|
let (tx, mut rx) = tokio::sync::mpsc::channel(64);
|
|
let Ok(client) = Client::new(tx, stream_read) else {
|
|
println!("Failed to create client");
|
|
continue;
|
|
};
|
|
let client = Arc::new(client);
|
|
|
|
{
|
|
let client = client.clone();
|
|
tokio::spawn(async move {
|
|
while let Some(packet) = rx.recv().await {
|
|
if let Err(e) = packet.write_to_stream(&mut stream_send).await {
|
|
client
|
|
.disconnect(TextComponent::from_str(
|
|
"Error while sending packet",
|
|
))
|
|
.await;
|
|
println!("Error while sending packet: {}", e);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Keep alive task
|
|
{
|
|
let client = client.clone();
|
|
tokio::spawn(async move {
|
|
let mut interval = interval(Duration::from_secs(10));
|
|
loop {
|
|
interval.tick().await;
|
|
if !client.connected.load(Ordering::Relaxed) {
|
|
break;
|
|
}
|
|
|
|
if client.needs_keep_alive().await {
|
|
// TODO: Use a unique id for each keep alive packet (or at least a
|
|
// timestamp)
|
|
client
|
|
.send_packet(&clientbound::KeepAlivePacket { id: 0 })
|
|
.await;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
{
|
|
let registries = self.server.registries.clone();
|
|
let world = self.server.world.clone();
|
|
tokio::spawn(async move {
|
|
while !client.convert_to_player.load(Ordering::Relaxed)
|
|
&& client.connected.load(Ordering::Relaxed)
|
|
{
|
|
if let Err(e) = client.read_packets().await {
|
|
// Log the issue in the console and inform the client.
|
|
println!("Error while reading packet: {}", e);
|
|
client
|
|
.disconnect(TextComponent::from_str(
|
|
"Error while reading packets",
|
|
))
|
|
.await;
|
|
break;
|
|
}
|
|
if let Err(e) = client.handle_packets(®istries).await {
|
|
// Log the issue in the console and inform the client.
|
|
println!("Error while handeling packet: {}", e);
|
|
client
|
|
.disconnect(TextComponent::from_str(
|
|
"Error while handeling packet",
|
|
))
|
|
.await;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if client.connected.load(Ordering::Relaxed) {
|
|
let player = Player::upgrade_client(client, world).await;
|
|
while player.client.connected.load(Ordering::Relaxed) {
|
|
if let Err(e) = player.read_packets().await {
|
|
// Log the issue in the console and inform the client.
|
|
println!("Error while reading packet: {}", e);
|
|
player
|
|
.disconnect(TextComponent::from_str(
|
|
"Error while reading packets",
|
|
))
|
|
.await;
|
|
break;
|
|
}
|
|
if let Err(e) = player.handle_packets().await {
|
|
// Log the issue in the console and inform the client.
|
|
println!("Error while handeling packet: {}", e);
|
|
player
|
|
.disconnect(TextComponent::from_str(
|
|
"Error while handeling packet",
|
|
))
|
|
.await;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|