Skip to content

Commit bc4ed2f

Browse files
Mcrtinpull[bot]
authored andcommitted
introduce Position structs for the Chunk impl (ferrumc-rs#284)
* introduce Position structs for the Chunk impl # Conflicts: # src/lib/world/src/edits.rs # Conflicts: # src/bin/src/main.rs # src/lib/net/src/conn_init/login.rs * add section pos * fix doc tests * add a comment and remove unnecessary parentheses * protect BlockStateId * add min_y field in chunk * remove y from section * refactor: move code from Chunk to Section * make edit_batch more ownership friendly * fix clippy * protect Pos fields # Conflicts: # src/bin/src/main.rs * fix: fix world gen in neg chunks * make chunk gen use ChunkPos * fix chunk pos * correctly pack chunkpos * fix
1 parent 24edf55 commit bc4ed2f

File tree

29 files changed

+768
-479
lines changed

29 files changed

+768
-479
lines changed

src/bin/src/launch.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use ferrumc_state::player_cache::PlayerCache;
88
use ferrumc_state::player_list::PlayerList;
99
use ferrumc_state::{GlobalState, ServerState};
1010
use ferrumc_threadpool::ThreadPool;
11+
use ferrumc_world::pos::ChunkPos;
1112
use ferrumc_world::World;
1213
use ferrumc_world_gen::WorldGenerator;
1314
use std::sync::Arc;
@@ -44,14 +45,15 @@ pub fn generate_spawn_chunks(state: GlobalState) -> Result<(), BinaryError> {
4445
for (x, z) in chunks {
4546
let state_clone = state.clone();
4647
batch.execute(move || {
48+
let pos = ChunkPos::new(x, z);
4749
let chunk = state_clone
4850
.terrain_generator
49-
.generate_chunk(x, z)
51+
.generate_chunk(pos)
5052
.map(Arc::new);
5153

5254
match chunk {
5355
Ok(chunk) => {
54-
if let Err(e) = state_clone.world.save_chunk(chunk) {
56+
if let Err(e) = state_clone.world.save_chunk(pos, "overworld", chunk) {
5557
error!("Error saving chunk ({}, {}): {:?}", x, z, e);
5658
}
5759
}

src/bin/src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::cli::{CLIArgs, Command};
44
use crate::errors::BinaryError;
55
use clap::Parser;
66
use ferrumc_config::whitelist::create_whitelist;
7+
use ferrumc_world::pos::ChunkPos;
78
use std::sync::Arc;
89
use std::time::Instant;
910
use tracing::{error, info};
@@ -72,8 +73,10 @@ fn entry(start_time: Instant) -> Result<(), BinaryError> {
7273
let global_state = Arc::new(state);
7374

7475
create_whitelist();
75-
76-
if !global_state.world.chunk_exists(0, 0, "overworld")? {
76+
if !global_state
77+
.world
78+
.chunk_exists(ChunkPos::new(0, 0), "overworld")?
79+
{
7780
launch::generate_spawn_chunks(global_state.clone())?;
7881
}
7982

src/bin/src/packet_handlers/play_packets/pick_item_from_block.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,9 @@ pub fn handle(
4343
);
4444

4545
// 2. Get block from world
46+
let pos = packet.location.clone().into();
4647
let block_state_id = match state.0.world.get_block_and_fetch(
47-
packet.location.x,
48-
packet.location.y as i32,
49-
packet.location.z,
48+
pos,
5049
"overworld", // TODO: Remove overworld hard coding for the dimension
5150
) {
5251
Ok(id) => id,

src/bin/src/packet_handlers/play_packets/place_block.rs

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use ferrumc_net::PlaceBlockReceiver;
1010
use ferrumc_net_codec::net_types::network_position::NetworkPosition;
1111
use ferrumc_net_codec::net_types::var_int::VarInt;
1212
use ferrumc_state::GlobalStateResource;
13+
use ferrumc_world::pos::BlockPos;
1314
use tracing::{debug, error, trace};
1415

1516
use ferrumc_inventories::hotbar::Hotbar;
@@ -21,12 +22,17 @@ use std::str::FromStr;
2122

2223
const ITEM_TO_BLOCK_MAPPING_FILE: &str =
2324
include_str!("../../../../../assets/data/item_to_block_mapping.json");
24-
static ITEM_TO_BLOCK_MAPPING: Lazy<HashMap<i32, i32>> = Lazy::new(|| {
25+
static ITEM_TO_BLOCK_MAPPING: Lazy<HashMap<i32, BlockStateId>> = Lazy::new(|| {
2526
let str_form: HashMap<String, String> = serde_json::from_str(ITEM_TO_BLOCK_MAPPING_FILE)
2627
.expect("Failed to parse item_to_block_mapping.json");
2728
str_form
2829
.into_iter()
29-
.map(|(k, v)| (i32::from_str(&k).unwrap(), i32::from_str(&v).unwrap()))
30+
.map(|(k, v)| {
31+
(
32+
i32::from_str(&k).unwrap(),
33+
BlockStateId::new(u32::from_str(&v).unwrap()),
34+
)
35+
})
3036
.collect()
3137
});
3238

@@ -65,41 +71,31 @@ pub fn handle(
6571
"Placing block with item ID: {}, mapped to block state ID: {}",
6672
item_id.0, mapped_block_state_id
6773
);
68-
let mut chunk = match state.0.world.load_chunk_owned(
69-
event.position.x >> 4,
70-
event.position.z >> 4,
71-
"overworld",
72-
) {
74+
let pos: BlockPos = event.position.into();
75+
let mut chunk = match state.0.world.load_chunk_owned(pos.chunk(), "overworld") {
7376
Ok(chunk) => chunk,
7477
Err(e) => {
7578
debug!("Failed to load chunk: {:?}", e);
7679
continue 'ev_loop;
7780
}
7881
};
79-
let Ok(block_clicked) = chunk.get_block(
80-
event.position.x,
81-
event.position.y as i32,
82-
event.position.z,
83-
) else {
84-
debug!("Failed to get block at position: {:?}", event.position);
82+
let Ok(block_clicked) = chunk.get_block(pos.chunk_block_pos()) else {
83+
debug!("Failed to get block at position: {}", pos);
8584
continue 'ev_loop;
8685
};
8786
trace!("Block clicked: {:?}", block_clicked);
8887
// Use the face to determine the offset of the block to place
89-
let (x_block_offset, y_block_offset, z_block_offset) = match event.face.0 {
90-
0 => (0, -1, 0),
91-
1 => (0, 1, 0),
92-
2 => (0, 0, -1),
93-
3 => (0, 0, 1),
94-
4 => (-1, 0, 0),
95-
5 => (1, 0, 0),
96-
_ => (0, 0, 0),
97-
};
98-
let (x, y, z) = (
99-
event.position.x + x_block_offset,
100-
event.position.y + y_block_offset,
101-
event.position.z + z_block_offset,
102-
);
88+
let offset_pos = pos
89+
+ match event.face.0 {
90+
0 => (0, -1, 0),
91+
1 => (0, 1, 0),
92+
2 => (0, 0, -1),
93+
3 => (0, 0, 1),
94+
4 => (-1, 0, 0),
95+
5 => (1, 0, 0),
96+
_ => (0, 0, 0),
97+
};
98+
10399
// Check if the block collides with any entities
104100
let does_collide = {
105101
pos_q.into_iter().any(|(pos, bounds)| {
@@ -113,7 +109,11 @@ pub fn handle(
113109
z_offset_start: 0.0,
114110
z_offset_end: 1.0,
115111
},
116-
(x as f64, y as f64, z as f64),
112+
(
113+
offset_pos.pos.x as f64,
114+
offset_pos.pos.y as f64,
115+
offset_pos.pos.z as f64,
116+
),
117117
)
118118
})
119119
};
@@ -129,12 +129,8 @@ pub fn handle(
129129
continue 'ev_loop;
130130
}
131131

132-
if let Err(err) = chunk.set_block(
133-
x & 0xF,
134-
y as i32,
135-
z & 0xF,
136-
BlockStateId(*mapped_block_state_id as u32),
137-
) {
132+
if let Err(err) = chunk.set_block(pos.chunk_block_pos(), *mapped_block_state_id)
133+
{
138134
error!("Failed to set block: {:?}", err);
139135
continue 'ev_loop;
140136
}
@@ -143,7 +139,11 @@ pub fn handle(
143139
};
144140

145141
let chunk_packet = BlockUpdate {
146-
location: NetworkPosition { x, y, z },
142+
location: NetworkPosition {
143+
x: offset_pos.pos.x,
144+
y: offset_pos.pos.y as i16,
145+
z: offset_pos.pos.z,
146+
},
147147
block_state_id: VarInt::from(*mapped_block_state_id),
148148
};
149149
if let Err(err) = conn.send_packet_ref(&chunk_packet) {
@@ -155,10 +155,15 @@ pub fn handle(
155155
continue 'ev_loop;
156156
}
157157

158-
if let Err(err) = state.0.world.save_chunk(Arc::from(chunk)) {
158+
if let Err(err) =
159+
state
160+
.0
161+
.world
162+
.save_chunk(pos.chunk(), "overworld", Arc::from(chunk))
163+
{
159164
error!("Failed to save chunk after block placement: {:?}", err);
160165
} else {
161-
trace!("Block placed at ({}, {}, {})", x, y, z);
166+
trace!("Block placed at {}", offset_pos);
162167
}
163168
}
164169
}

src/bin/src/packet_handlers/play_packets/player_action.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use ferrumc_net::packets::outgoing::block_update::BlockUpdate;
1111
use ferrumc_net::PlayerActionReceiver;
1212
use ferrumc_net_codec::net_types::var_int::VarInt;
1313
use ferrumc_state::GlobalStateResource;
14-
use ferrumc_world::block_state_id::BlockStateId;
14+
use ferrumc_world::{block_state_id::BlockStateId, pos::BlockPos};
1515
use tracing::{error, trace, warn};
1616

1717
pub fn handle(
@@ -34,40 +34,37 @@ pub fn handle(
3434
continue;
3535
};
3636

37+
let pos: BlockPos = event.location.clone().into();
3738
if abilities.creative_mode {
3839
// --- CREATIVE MODE LOGIC ---
3940
// Only instabreak (status 0) is relevant in creative.
4041
if event.status.0 == 0 {
4142
let res: Result<(), BinaryError> = try {
42-
let mut chunk = match state.0.clone().world.load_chunk_owned(
43-
event.location.x >> 4,
44-
event.location.z >> 4,
45-
"overworld",
46-
) {
43+
let mut chunk = match state
44+
.0
45+
.clone()
46+
.world
47+
.load_chunk_owned(pos.chunk(), "overworld")
48+
{
4749
Ok(chunk) => chunk,
4850
Err(e) => {
4951
trace!("Chunk not found, generating new chunk: {:?}", e);
5052
state
5153
.0
5254
.clone()
5355
.terrain_generator
54-
.generate_chunk(event.location.x >> 4, event.location.z >> 4)
56+
.generate_chunk(pos.chunk())
5557
.map_err(BinaryError::WorldGen)?
5658
}
5759
};
58-
let (relative_x, relative_y, relative_z) = (
59-
event.location.x.abs() % 16,
60-
event.location.y as i32,
61-
event.location.z.abs() % 16,
62-
);
6360
chunk
64-
.set_block(relative_x, relative_y, relative_z, BlockStateId::default())
61+
.set_block(pos.chunk_block_pos(), BlockStateId::default())
6562
.map_err(BinaryError::World)?;
6663

6764
state
6865
.0
6966
.world
70-
.save_chunk(Arc::new(chunk))
67+
.save_chunk(pos.chunk(), "overworld", Arc::new(chunk))
7168
.map_err(BinaryError::World)?;
7269

7370
// Broadcast the change

src/bin/src/packet_handlers/play_packets/player_loaded.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use bevy_ecs::prelude::{Entity, Query, Res};
22
use ferrumc_core::transform::position::Position;
3+
use ferrumc_macros::block;
34
use ferrumc_net::connection::StreamWriter;
45
use ferrumc_net::packets::outgoing::synchronize_player_position::SynchronizePlayerPositionPacket;
56
use ferrumc_net::PlayerLoadedReceiver;
67
use ferrumc_state::GlobalStateResource;
78
use ferrumc_world::block_state_id::BlockStateId;
9+
use ferrumc_world::pos::BlockPos;
810
use tracing::warn;
911

1012
pub fn handle(
@@ -24,14 +26,14 @@ pub fn handle(
2426
);
2527
continue;
2628
}
27-
let head_block = state.0.world.get_block_and_fetch(
29+
let pos = BlockPos::of(
2830
player_pos.x as i32,
2931
player_pos.y as i32,
3032
player_pos.z as i32,
31-
"overworld",
3233
);
34+
let head_block = state.0.world.get_block_and_fetch(pos, "overworld");
3335
if let Ok(head_block) = head_block {
34-
if head_block == BlockStateId(0) {
36+
if head_block == block!("air") {
3537
tracing::info!(
3638
"Player {} loaded at position: ({}, {}, {})",
3739
player,

src/bin/src/systems/chunk_sending.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use ferrumc_net::packets::outgoing::chunk_batch_start::ChunkBatchStart;
1111
use ferrumc_net::packets::outgoing::set_center_chunk::SetCenterChunk;
1212
use ferrumc_net_codec::encode::NetEncodeOpts;
1313
use ferrumc_state::GlobalStateResource;
14+
use ferrumc_world::pos::ChunkPos;
1415
use std::sync::atomic::Ordering;
1516

1617
// Just take the needed chunks from the ChunkReceiver and send them
@@ -68,24 +69,24 @@ pub fn handle(
6869
})
6970
.expect("Failed to send SetCenterChunk");
7071

71-
for coordinates in needed_chunks {
72+
for coordinates in needed_chunks.into_iter().map(|c| ChunkPos::new(c.0, c.1)) {
7273
let state = state.clone();
7374
let is_compressed = conn.compress.load(Ordering::Relaxed);
7475
batch.execute({
7576
move || {
7677
let chunk = state
7778
.0
7879
.world
79-
.load_chunk(coordinates.0, coordinates.1, "overworld")
80+
.load_chunk(coordinates, "overworld")
8081
.unwrap_or(
8182
state
8283
.0
8384
.terrain_generator
84-
.generate_chunk(coordinates.0, coordinates.1)
85+
.generate_chunk(coordinates)
8586
.expect("Could not generate chunk")
8687
.into(),
8788
);
88-
let packet = ChunkAndLightData::from_chunk(&chunk)
89+
let packet = ChunkAndLightData::from_chunk(coordinates, &chunk)
8990
.expect("Failed to create ChunkAndLightData");
9091
compress_packet(
9192
&packet,

0 commit comments

Comments
 (0)