mirror of https://github.com/zyllian/classics.git synced 2025-05-10 02:36:40 -07:00

implement server ticks, block updates, and classic fluid mechanics

This commit is contained in:
Zoey 2024-04-22 16:35:54 -07:00
parent 8dc89d959e
commit 492da31ce0
No known key found for this signature in database
GPG key ID: 8611B896D1AAFAF2
6 changed files with 285 additions and 39 deletions

View file

@ -5,10 +5,19 @@ use std::sync::Arc;
use tokio::{net::TcpListener, sync::RwLock};
use crate::{level::Level, player::Player};
use crate::{
level::{
block::{BlockType, BLOCK_INFO},
BlockUpdate, Level,
},
player::Player,
util::neighbors_minus_up,
};
use self::config::ServerConfig;
const TICK_DURATION: std::time::Duration = std::time::Duration::from_millis(50);
/// the server
#[derive(Debug)]
pub struct Server {
@ -64,6 +73,10 @@ impl Server {
/// starts the server
pub async fn run(&mut self) -> std::io::Result<()> {
let data = self.data.clone();
tokio::spawn(async move {
handle_ticks(data).await;
});
loop {
let (stream, addr) = self.listener.accept().await?;
println!("connection from {addr}");
@ -76,3 +89,85 @@ impl Server {
}
}
}
/// function to tick the server
async fn handle_ticks(data: Arc<RwLock<ServerData>>) {
let mut current_tick = 0;
loop {
tick(&mut *data.write().await, current_tick);
current_tick = current_tick.wrapping_add(1);
tokio::time::sleep(TICK_DURATION).await;
}
}
/// function which ticks the server once
fn tick(data: &mut ServerData, tick: usize) {
let level = &mut data.level;
let mut packets = level.apply_updates();
let awaiting_update = std::mem::take(&mut level.awaiting_update);
if !awaiting_update.is_empty() {
println!("hm");
}
for index in awaiting_update {
let (x, y, z) = level.coordinates(index);
let block_id = level.get_block(x, y, z);
let block = BLOCK_INFO.get(&block_id).expect("should never fail");
println!("{block:#?}");
match &block.block_type {
BlockType::FluidFlowing {
stationary,
ticks_to_spread,
} => {
if tick % ticks_to_spread == 0 {
let update = BlockUpdate {
index,
block: *stationary,
};
level.updates.push(update);
for (nx, ny, nz) in neighbors_minus_up(level, x, y, z) {
let block_at = level.get_block(nx, ny, nz);
let update = if block_at == 0 {
level.awaiting_update.insert(level.index(nx, ny, nz));
BlockUpdate {
index: level.index(nx, ny, nz),
block: block_id,
}
} else {
continue;
};
level.updates.push(update);
}
} else {
level.awaiting_update.insert(index);
}
}
BlockType::FluidStationary { moving } => {
let mut needs_update = false;
for (nx, ny, nz) in neighbors_minus_up(level, x, y, z) {
if level.get_block(nx, ny, nz) == 0 {
needs_update = true;
break;
}
}
if needs_update {
let index = level.index(x, y, z);
level.updates.push(BlockUpdate {
index,
block: *moving,
});
level.awaiting_update.insert(index);
}
}
_ => {}
}
}
packets.extend(level.apply_updates());
for packet in packets {
for player in &mut data.players {
player.packets_to_send.push(packet.clone());
}
}
}