Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Refactor chunk loading and sending code
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitriTimoz committed Nov 13, 2023
1 parent 9b550c4 commit ddbe987
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 78 deletions.
39 changes: 6 additions & 33 deletions minecraft-server/src/player_handler/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,42 +314,15 @@ pub async fn handshake(stream: &mut TcpStream, logged_in_player_info: LoggedInPl
}
}
world.update_loaded_chunks(logged_in_player_info.uuid, loaded_chunks).await;

let mut heightmaps = HashMap::new();
heightmaps.insert(String::from("MOTION_BLOCKING"), NbtTag::LongArray(vec![0; 37]));
let heightmaps = NbtTag::Compound(heightmaps);

for cx in -3..=3 {
for cz in -3..=3 {
let mut column = Vec::new();
for cy in -4..20 {
let chunk = world.get_network_chunk(ChunkPosition { cx, cy, cz }).await.unwrap_or_else(|| {
error!("Chunk not loaded: {cx} {cy} {cz}");
NetworkChunk { // TODO hard error
block_count: 0,
blocks: PalettedData::Single { value: 0 },
biomes: PalettedData::Single { value: 4 },
}
});
column.push(chunk);
}
let serialized: Vec<u8> = NetworkChunk::into_data(column).unwrap();
let chunk_data = PlayClientbound::ChunkData {
value: ChunkData {
chunk_x: cx,
chunk_z: cz,
heightmaps: heightmaps.clone(),
data: Array::from(serialized.clone()),
block_entities: Array::default(),
sky_light_mask: Array::default(),
block_light_mask: Array::default(),
empty_sky_light_mask: Array::default(),
empty_block_light_mask: Array::default(),
sky_light: Array::default(),
block_light: Array::default(),
}
};
send_packet(stream, chunk_data).await;
let chunk_column = world.get_network_chunk_column_data(ChunkColumnPosition { cx, cz }).await.unwrap_or_else(|| {
error!("Chunk not loaded: {cx} {cz}");
panic!("Chunk not loaded: {cx} {cz}");
});

send_packet_raw(stream, &chunk_column).await;
}
}
debug!("ChunkData sent");
Expand Down
40 changes: 8 additions & 32 deletions minecraft-server/src/player_handler/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ impl PlayerHandler {
self.packet_sender.send(packet).await.unwrap();
}

async fn send_packet_raw(&mut self, packet: &[u8]) {
self.packet_sender.send(packet.to_vec()).await.unwrap();
}

async fn on_server_message(&mut self, message: ServerMessage) {
use ServerMessage::*;
match message {
Expand Down Expand Up @@ -72,40 +76,12 @@ impl PlayerHandler {

// Send the chunks to the client
for newly_loaded_chunk in newly_loaded_chunks {
let mut column = Vec::new();
let heightmaps = self.world.get_network_heightmap(newly_loaded_chunk.clone()).await.unwrap_or_else(|| {
let chunk_column_data = self.world.get_network_chunk_column_data(newly_loaded_chunk.clone()).await.unwrap_or_else(|| {
error!("Chunk not loaded: {newly_loaded_chunk:?}");
NbtTag::Compound(HashMap::new()) // TODO hard error
panic!("Chunk not loaded: {newly_loaded_chunk:?}");
});

for cy in -4..20 {
let chunk = self.world.get_network_chunk(newly_loaded_chunk.chunk(cy)).await.unwrap_or_else(|| {
error!("Chunk not loaded: {newly_loaded_chunk:?}");
NetworkChunk { // TODO hard error
block_count: 0,
blocks: PalettedData::Single { value: 0 },
biomes: PalettedData::Single { value: 4 },
}
});
column.push(chunk);
}
let serialized: Vec<u8> = NetworkChunk::into_data(column).unwrap();
let chunk_data = PlayClientbound::ChunkData {
value: ChunkData {
chunk_x: newly_loaded_chunk.cx,
chunk_z: newly_loaded_chunk.cz,
heightmaps,
data: Array::from(serialized.clone()),
block_entities: Array::default(),
sky_light_mask: Array::default(),
block_light_mask: Array::default(),
empty_sky_light_mask: Array::default(),
empty_block_light_mask: Array::default(),
sky_light: Array::default(),
block_light: Array::default(),
}
};
self.send_packet(chunk_data).await;

self.send_packet_raw(&chunk_column_data).await;
}

// Tell the client to unload chunks
Expand Down
2 changes: 1 addition & 1 deletion minecraft-server/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub use log::{debug, error, info, trace, warn};
pub use minecraft_protocol::{
components::{
chat::ChatMode,
chunk::{Chunk as NetworkChunk, ChunkData, PalettedData},
chunk::{Chunk as NetworkChunk, ChunkData as NetworkChunkColumnData, PalettedData},
difficulty::Difficulty,
entity::{EntityAttribute, EntityMetadata, EntityMetadataValue},
gamemode::{Gamemode, PreviousGamemode},
Expand Down
34 changes: 24 additions & 10 deletions minecraft-server/src/world/map.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{collections::HashMap, cmp::Ordering};
use minecraft_protocol::{components::chunk::{PalettedData, self}, ids::blocks::Block};
use minecraft_protocol::{components::chunk::PalettedData, ids::blocks::Block};
use tokio::sync::RwLock;
use crate::prelude::*;
use super::light::Light;
Expand Down Expand Up @@ -456,16 +456,30 @@ impl WorldMap {
inner_get_block(self, position).await.unwrap_or(BlockWithState::Air)
}

pub async fn get_network_chunk(&self, position: ChunkPosition) -> Option<NetworkChunk> {
let chunk_column_position = position.chunk_column();
let shard = chunk_column_position.shard(self.shard_count);
let cy_in_vec: usize = position.cy.saturating_add(4).try_into().ok()?;

pub async fn get_network_chunk_column_data(&self, position: ChunkColumnPosition) -> Option<Vec<u8>> {
let shard = position.shard(self.shard_count);
let shard = self.shards[shard].read().await;
let chunk_column = shard.get(&chunk_column_position)?;
let chunk = chunk_column.chunks.get(cy_in_vec)?;

Some(chunk.as_network_chunk().clone())
let chunk_column = shard.get(&position)?;

let serialized = NetworkChunk::into_data(chunk_column.chunks.iter().map(|c| c.data.clone()).collect()).unwrap();
let chunk_data = PlayClientbound::ChunkData { value: NetworkChunkColumnData {
chunk_x: position.cx,
chunk_z: position.cz,
heightmaps: chunk_column.heightmap.to_tag(),
data: Array::from(serialized.clone()),
block_entities: Array::default(),
sky_light_mask: Array::default(),
block_light_mask: Array::default(),
empty_sky_light_mask: Array::default(),
empty_block_light_mask: Array::default(),
sky_light: Array::default(),
block_light: Array::default(),
}};

let chunk_data = chunk_data.serialize_minecraft_packet().map_err(|e| {
error!("Failed to serialize chunk column data: {:?}", e);
}).ok()?;
Some(chunk_data)
}

pub async fn get_network_heightmap(&self, position: ChunkColumnPosition) -> Option<NbtTag> {
Expand Down
4 changes: 2 additions & 2 deletions minecraft-server/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ impl World {
Some(self.map.get_block(position).await)
}

pub async fn get_network_chunk(&self, position: ChunkPosition) -> Option<NetworkChunk> {
self.map.get_network_chunk(position).await
pub async fn get_network_chunk_column_data(&self, position: ChunkColumnPosition) -> Option<Vec<u8>> {
self.map.get_network_chunk_column_data(position).await
}

pub async fn get_network_heightmap(&self, position: ChunkColumnPosition) -> Option<NbtTag> {
Expand Down

0 comments on commit ddbe987

Please sign in to comment.