Skip to content

Commit

Permalink
wtf
Browse files Browse the repository at this point in the history
  • Loading branch information
ReCore-sys committed Feb 2, 2025
1 parent 2f4aa8a commit e78f426
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 40 deletions.
9 changes: 6 additions & 3 deletions src/bin/src/systems/chunk_fetcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::errors::BinaryError;
use crate::systems::definition::System;
use async_trait::async_trait;
use ferrumc_core::chunks::chunk_receiver::ChunkReceiver;
use ferrumc_core::chunks::chunk_receiver::ChunkSendState::{Fetching, Sending};
use ferrumc_state::GlobalState;
use ferrumc_world::chunk_format::Chunk;
use ferrumc_world::vanilla_chunk_format::BlockData;
Expand Down Expand Up @@ -43,7 +44,7 @@ impl System for ChunkFetcher {
let mut copied_chunks = HashMap::new();
for chunk in chunk_recv.needed_chunks.iter() {
let (key, chunk) = chunk;
if chunk.is_none() {
if let Fetching = chunk {
copied_chunks.insert(key.clone(), None);
}
}
Expand Down Expand Up @@ -85,8 +86,10 @@ impl System for ChunkFetcher {
trace!("A player disconnected before we could get the ChunkReceiver");
return Ok(());
};
for (key, chunk) in copied_chunks.iter() {
chunk_recv.needed_chunks.insert(key.clone(), chunk.clone());
for (key, chunk) in copied_chunks {
if let Some(chunk) = chunk {
chunk_recv.needed_chunks.insert(key.clone(), Sending(chunk));
}
}
}
Ok(())
Expand Down
22 changes: 7 additions & 15 deletions src/bin/src/systems/chunk_sender.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::systems::definition::System;
use async_trait::async_trait;
use ferrumc_core::chunks::chunk_receiver::ChunkReceiver;
use ferrumc_core::chunks::chunk_receiver::ChunkSendState::{Sending, Sent};
use ferrumc_ecs::errors::ECSError;
use ferrumc_net::connection::StreamWriter;
use ferrumc_net::packets::outgoing::chunk_and_light_data::ChunkAndLightData;
Expand All @@ -14,7 +15,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tokio::task::JoinSet;
use tracing::{error, info, trace};
use tracing::{debug, error, info, trace};

pub(super) struct ChunkSenderSystem {
pub stop: AtomicBool,
Expand Down Expand Up @@ -55,7 +56,6 @@ impl System for ChunkSenderSystem {
}
// We can't delete from the map while iterating, so we collect the keys to drop
// and then drop them after sending the chunks
let mut to_drop = Vec::new();
{
let Ok(chunk_recv) = state.universe.get::<ChunkReceiver>(eid) else {
trace!("A player disconnected before we could get the ChunkReceiver");
Expand All @@ -75,28 +75,20 @@ impl System for ChunkSenderSystem {
.expect("ChunkReceiver not found");
trace!("Got chunk_recv 3 for sender");
for (key, chunk) in chunk_recv.needed_chunks.iter_mut() {
if let Some(chunk) = chunk {
to_drop.push(key.clone());
match ChunkAndLightData::from_chunk(&chunk.clone()) {
if let Sending(confirmed_chunk) = chunk {
match ChunkAndLightData::from_chunk(&confirmed_chunk.clone()) {
Ok(packet) => {
debug!("Queuing chunk for sending");
packets.push(packet);
}
Err(e) => {
error!("Error sending chunk: {:?}", e);
}
}
*chunk = Sent;
}
}
}
{
let Ok(mut chunk_recv) = state.universe.get_mut::<ChunkReceiver>(eid)
else {
trace!("A player disconnected before we could get the ChunkReceiver");
return Ok(());
};
for key in to_drop {
chunk_recv.needed_chunks.remove(&key);
}
chunk_recv.needed_chunks.retain(|_, v| v != &Sent);
}

{
Expand Down
13 changes: 10 additions & 3 deletions src/lib/core/src/chunks/chunk_receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tokio::time::Instant;

const VIEW_DISTANCE: i32 = 8;
pub struct ChunkReceiver {
pub needed_chunks: HashMap<(i32, i32, String), Option<Chunk>>,
pub needed_chunks: HashMap<(i32, i32, String), ChunkSendState>,
pub can_see: HashSet<(i32, i32, String)>,
pub last_update: Instant,
pub last_chunk: Option<(i32, i32, String)>,
Expand All @@ -19,6 +19,13 @@ impl Default for ChunkReceiver {
}
}

#[derive(Clone, Eq, PartialEq)]
pub enum ChunkSendState {
Fetching,
Sending(Chunk),
Sent,
}

impl ChunkReceiver {
pub fn new() -> Self {
Self {
Expand All @@ -35,7 +42,7 @@ impl ChunkReceiver {
if self.can_see.contains(&(x, z, dimension.clone())) {
let entry = self.needed_chunks.get_mut(&(x, z, dimension.clone()));
if let Some(entry) = entry {
*entry = None;
*entry = ChunkSendState::Fetching;
}
}
}
Expand All @@ -49,7 +56,7 @@ impl ChunkReceiver {
for z in last_chunk.1 - VIEW_DISTANCE..=last_chunk.1 + VIEW_DISTANCE {
if !self.can_see.contains(&(x, z, last_chunk.2.clone())) {
self.needed_chunks
.insert((x, z, last_chunk.2.clone()), None);
.insert((x, z, last_chunk.2.clone()), ChunkSendState::Fetching);
}
new_can_see.insert((x, z, last_chunk.2.clone()));
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/net/crates/codec/src/net_types/var_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use deepsize::DeepSizeOf;
use std::io::{Read, Write};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};

#[derive(Debug, Encode, Decode, Clone, DeepSizeOf)]
#[derive(Debug, Encode, Decode, Clone, DeepSizeOf, Eq)]
pub struct VarInt {
/// The value of the VarInt.
pub val: i32,
Expand Down
7 changes: 4 additions & 3 deletions src/lib/net/src/packets/outgoing/chunk_and_light_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use ferrumc_net_codec::net_types::var_int::VarInt;
use ferrumc_world::chunk_format::{Chunk, Heightmaps, PaletteType};
use std::io::{Cursor, Write};
use std::ops::Not;
use tracing::{debug, trace, warn};
use tracing::{debug, warn};

const SECTIONS: usize = 24; // Number of sections, adjust for your Y range (-64 to 319)

Expand Down Expand Up @@ -64,6 +64,7 @@ impl ChunkAndLightData {
}

pub fn from_chunk(chunk: &Chunk) -> Result<Self, NetError> {
debug!("Serializing chunk at {}, {}", chunk.x, chunk.z);
let mut raw_data = Cursor::new(Vec::new());
let mut sky_light_data = Vec::new();
let mut block_light_data = Vec::new();
Expand Down Expand Up @@ -93,7 +94,7 @@ impl ChunkAndLightData {

match &section.block_states.block_data {
PaletteType::Single(val) => {
debug!("Single palette type: {:?}", (chunk.x, chunk.z));
// debug!("Single palette type: {:?}", (chunk.x, chunk.z));
raw_data.write_u8(0)?;
val.write(&mut raw_data)?;
VarInt::new(0).write(&mut raw_data)?;
Expand All @@ -103,7 +104,7 @@ impl ChunkAndLightData {
data,
palette,
} => {
debug!("Indirect palette type: {:?}", (chunk.x, chunk.z));
// debug!("Indirect palette type: {:?}", (chunk.x, chunk.z));
raw_data.write_u8(*bits_per_block)?;
VarInt::new(palette.len() as i32).write(&mut raw_data)?;
for palette_entry in palette {
Expand Down
39 changes: 24 additions & 15 deletions src/lib/world/src/chunk_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use ferrumc_macros::{NBTDeserialize, NBTSerialize};
use ferrumc_net_codec::net_types::var_int::VarInt;
use lazy_static::lazy_static;
use std::cmp::max;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::io::Read;
use tracing::{debug, error, warn};
Expand Down Expand Up @@ -40,7 +41,7 @@ lazy_static! {
ID2BLOCK.iter().map(|(k, v)| (v.clone(), *k)).collect();
}

#[derive(Encode, Decode, Clone, DeepSizeOf)]
#[derive(Encode, Decode, Clone, DeepSizeOf, Eq, PartialEq)]
// This is a placeholder for the actual chunk format
pub struct Chunk {
pub x: i32,
Expand All @@ -52,28 +53,29 @@ pub struct Chunk {

#[derive(Encode, Decode, NBTDeserialize, NBTSerialize, Clone, DeepSizeOf)]
#[nbt(net_encode)]
#[derive(Eq, PartialEq)]
pub struct Heightmaps {
#[nbt(rename = "MOTION_BLOCKING")]
pub motion_blocking: Vec<i64>,
#[nbt(rename = "WORLD_SURFACE")]
pub world_surface: Vec<i64>,
}
#[derive(Encode, Decode, Clone, DeepSizeOf)]
#[derive(Encode, Decode, Clone, DeepSizeOf, Eq, PartialEq)]
pub struct Section {
pub y: i8,
pub block_states: BlockStates,
pub biome_states: BiomeStates,
pub block_light: Vec<u8>,
pub sky_light: Vec<u8>,
}
#[derive(Encode, Decode, Clone, DeepSizeOf)]
#[derive(Encode, Decode, Clone, DeepSizeOf, Eq, PartialEq)]
pub struct BlockStates {
pub non_air_blocks: u16,
pub block_data: PaletteType,
pub block_counts: HashMap<BlockData, i32>,
}

#[derive(Encode, Decode, Clone, DeepSizeOf)]
#[derive(Encode, Decode, Clone, DeepSizeOf, Eq, PartialEq)]
pub enum PaletteType {
Single(VarInt),
Indirect {
Expand All @@ -87,7 +89,7 @@ pub enum PaletteType {
},
}

#[derive(Encode, Decode, Clone, DeepSizeOf)]
#[derive(Encode, Decode, Clone, DeepSizeOf, Eq, PartialEq)]
pub struct BiomeStates {
pub bits_per_biome: u8,
pub data: Vec<i64>,
Expand Down Expand Up @@ -127,7 +129,7 @@ impl VanillaChunk {
let mut sections = Vec::new();
for section in self.sections.as_ref().unwrap() {
let y = section.y;
let mut block_data: PaletteType;
let block_data: PaletteType;
let raw_block_data = section
.block_states
.as_ref()
Expand Down Expand Up @@ -277,7 +279,7 @@ impl BlockStates {

// Extract value at the current bit offset
let value =
read_nbit_i32(&long, *bits_per_block as usize, bit_offset as u32)?;
read_nbit_i32(long, *bits_per_block as usize, bit_offset as u32)?;
let max_int_value = (1 << new_bit_size) - 1;
if value > max_int_value {
return Err(InvalidBlockStateData(format!(
Expand Down Expand Up @@ -391,6 +393,7 @@ impl Chunk {
.iter_mut()
.find(|section| section.y == (y >> 4) as i8)
.ok_or(WorldError::SectionOutOfBounds(y >> 4))?;
// Do different things based on the palette type
match &mut section.block_states.block_data {
PaletteType::Single(val) => {
debug!("Converting single block to indirect palette");
Expand All @@ -408,15 +411,17 @@ impl Chunk {
palette,
} => {
let block_counts = &mut section.block_states.block_counts;
match block_counts.get_mut(&old_block) {
Some(e) => {
if *e <= 0 {
match block_counts.entry(old_block.clone()) {
Entry::Occupied(mut occ_entry) => {
let count = occ_entry.get_mut();
if *count <= 0 {
return Err(WorldError::InvalidBlock(old_block));
}
*e -= 1;
*count -= 1;
}
None => {
Entry::Vacant(empty_entry) => {
warn!("Block not found in block counts: {:?}", old_block);
empty_entry.insert(0);
}
}
let block_id = BLOCK2ID
Expand Down Expand Up @@ -536,12 +541,16 @@ impl Chunk {
}

pub fn new(x: i32, z: i32, dimension: String) -> Self {
let mut sections: Vec<Section> = (0..24)
let sections: Vec<Section> = (0..24)
.map(|y| Section {
y: y as i8,
block_states: BlockStates {
non_air_blocks: 0,
block_data: PaletteType::Single(VarInt::from(0)),
block_data: PaletteType::Indirect {
bits_per_block: 4,
data: vec![0; 256],
palette: vec![VarInt::from(0)],
},
block_counts: HashMap::from([(BlockData::default(), 4096)]),
},
biome_states: BiomeStates {
Expand Down Expand Up @@ -579,7 +588,7 @@ impl Chunk {
/// * `Err(WorldError)` - If an error occurs while setting the section.
pub fn set_section(&mut self, section: u8, block: BlockData) -> Result<(), WorldError> {
if let Some(section) = self.sections.get_mut(section as usize) {
section.fill(block)
section.fill(block.clone())
} else {
Err(WorldError::SectionOutOfBounds(section as i32))
}
Expand Down

0 comments on commit e78f426

Please sign in to comment.