Skip to content

Commit 677ea51

Browse files
committed
It works!
1 parent e823621 commit 677ea51

File tree

8 files changed

+115
-44
lines changed

8 files changed

+115
-44
lines changed

scripts/new_packet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
use std::io::Write;
2525
2626
#[derive(NetEncode)]
27-
#[packet(packet_id = "++id++")]
27+
#[packet(packet_id = "++id++", state="play")]
2828
pub struct ++name++ {}
2929
"""
3030

src/bin/src/systems/chunk_fetcher.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,25 @@ pub struct ChunkFetcher {
1818

1919
fn generate_chunk(x: i32, z: i32) -> Chunk {
2020
let mut new_chunk = Chunk::new(x, z, "overworld".to_string());
21-
for y in 0..10 {
22-
new_chunk
23-
.set_section(
24-
y,
25-
BlockData {
26-
name: "minecraft:stone".to_string(),
27-
properties: None,
28-
},
29-
)
30-
.unwrap()
21+
for x in 0..16 {
22+
for z in 0..16 {
23+
let mut base_y = (x as f64).sin() / 32.0;
24+
base_y += (z as f64).cos() / 32.0;
25+
let scaled_y = ((base_y + 1.0) * 64.0) as i32;
26+
for y in 0..scaled_y {
27+
new_chunk
28+
.set_block(
29+
x,
30+
y,
31+
z,
32+
BlockData {
33+
name: "minecraft:stone".to_string(),
34+
properties: None,
35+
},
36+
)
37+
.unwrap();
38+
}
39+
}
3140
}
3241
new_chunk
3342
}

src/lib/net/crates/codec/src/net_types/var_int.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub struct VarInt {
1818

1919
mod adapters {
2020
use crate::net_types::var_int::VarInt;
21+
use std::ops::Add;
22+
use std::ops::Sub;
2123

2224
impl From<usize> for VarInt {
2325
fn from(value: usize) -> Self {
@@ -54,6 +56,22 @@ mod adapters {
5456
self.val == *other as i32
5557
}
5658
}
59+
60+
impl Add<Self> for VarInt {
61+
type Output = Self;
62+
63+
fn add(self, other: Self) -> Self {
64+
Self::new(self.val + other.val)
65+
}
66+
}
67+
68+
impl Sub<Self> for VarInt {
69+
type Output = Self;
70+
71+
fn sub(self, other: Self) -> Self {
72+
Self::new(self.val - other.val)
73+
}
74+
}
5775
}
5876

5977
impl PartialEq for VarInt {

src/lib/net/src/packets/incoming/player_action.rs

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use crate::connection::StreamWriter;
22
use crate::packets::outgoing::block_change_ack::BlockChangeAck;
3-
use crate::packets::outgoing::chunk_and_light_data::ChunkAndLightData;
3+
use crate::packets::outgoing::block_update::BlockUpdate;
44
use crate::packets::IncomingPacket;
55
use crate::NetResult;
6+
use ferrumc_core::chunks::chunk_receiver::ChunkReceiver;
67
use ferrumc_macros::{packet, NetDecode};
78
use ferrumc_net_codec::encode::NetEncodeOpts;
89
use ferrumc_net_codec::net_types::network_position::NetworkPosition;
910
use ferrumc_net_codec::net_types::var_int::VarInt;
1011
use ferrumc_state::ServerState;
12+
use ferrumc_world::chunk_format::BLOCK2ID;
1113
use ferrumc_world::vanilla_chunk_format::BlockData;
1214
use std::sync::Arc;
1315
use tracing::debug;
@@ -39,35 +41,57 @@ impl IncomingPacket for PlayerAction {
3941
self.location.y as i32,
4042
self.location.z & 0xF,
4143
);
42-
chunk.set_block(relative_x, relative_y, relative_z, BlockData::default())?;
43-
// debug!(chunk = ?chunk, "Chunk after block placement");
44+
chunk.set_block(
45+
relative_x & 0xf,
46+
relative_y,
47+
relative_z & 0xf,
48+
BlockData::default(),
49+
)?;
50+
// Save the chunk to disk
4451
state.world.save_chunk(chunk.clone()).await?;
4552
state.world.sync().await?;
4653
{
47-
let ack_packet = BlockChangeAck {
48-
sequence: self.sequence,
49-
};
50-
if let Ok(mut conn) = state.universe.get_mut::<StreamWriter>(conn_id) {
51-
let chunk_packet = ChunkAndLightData::from_chunk(&chunk)?;
52-
conn.send_packet(chunk_packet, &NetEncodeOpts::WithLength)?;
53-
conn.send_packet(ack_packet, &NetEncodeOpts::WithLength)?;
54-
} else {
55-
debug!(
56-
"Player disconnected before we could send the BlockChangeAck packet"
57-
);
54+
// Send the block update packet to all players
55+
let query = state
56+
.universe
57+
.query::<(&mut StreamWriter, &mut ChunkReceiver)>()
58+
.into_entities();
59+
for entity_id in query {
60+
if let Ok(mut connection) = state.universe.get_mut::<StreamWriter>(conn_id)
61+
{
62+
// Don't send the block update packet if the player can't see the chunk
63+
if let Ok(chunk_recv) = state.universe.get::<ChunkReceiver>(entity_id) {
64+
if chunk_recv.can_see.contains(&(
65+
self.location.x >> 4,
66+
self.location.z >> 4,
67+
"overworld".to_string(),
68+
)) {
69+
let block_update_packet = BlockUpdate {
70+
location: self.location.clone(),
71+
block_id: VarInt::from(*BLOCK2ID.get(&BlockData::default()).expect(
72+
"BlockData::default() should always have a corresponding block ID",
73+
)),
74+
};
75+
connection.send_packet(
76+
block_update_packet,
77+
&NetEncodeOpts::WithLength,
78+
)?;
79+
}
80+
}
81+
82+
// If the player is the one who placed the block, send the BlockChangeAck packet
83+
// We do this here to avoid locking the streamwriter multiple times
84+
if entity_id == conn_id {
85+
let ack_packet = BlockChangeAck {
86+
sequence: self.sequence.clone(),
87+
};
88+
connection.send_packet(ack_packet, &NetEncodeOpts::WithLength)?;
89+
}
90+
} else {
91+
debug!("Player disconnected before we could send the BlockChangeAck packet");
92+
}
5893
}
5994
}
60-
// {
61-
// let q = state.universe.query::<&mut ChunkReceiver>();
62-
// for (_, mut chunk_receiver) in q {
63-
// debug!("Queueing chunk resend");
64-
// chunk_receiver.queue_chunk_resend(
65-
// self.location.x >> 4,
66-
// self.location.z >> 4,
67-
// "overworld".to_string(),
68-
// );
69-
// }
70-
// }
7195
}
7296
1 => {
7397
debug!("You shouldn't be seeing this in creative mode.");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use ferrumc_macros::{packet, NetEncode};
2+
use ferrumc_net_codec::net_types::network_position::NetworkPosition;
3+
use ferrumc_net_codec::net_types::var_int::VarInt;
4+
use std::io::Write;
5+
6+
#[derive(NetEncode)]
7+
#[packet(packet_id = "block_update", state = "play")]
8+
pub struct BlockUpdate {
9+
pub location: NetworkPosition,
10+
pub block_id: VarInt,
11+
}

src/lib/net/src/packets/outgoing/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ pub mod update_entity_rotation;
3434
// -----------------------------
3535

3636
pub mod block_change_ack;
37+
38+
pub mod block_update;

src/lib/world/src/chunk_format.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::cmp::max;
1212
use std::collections::hash_map::Entry;
1313
use std::collections::HashMap;
1414
use std::io::Read;
15-
use tracing::{error, warn};
15+
use tracing::{debug, error, warn};
1616
use vanilla_chunk_format::BlockData;
1717

1818
#[cfg(test)]
@@ -384,7 +384,7 @@ impl Chunk {
384384
// Get old block
385385
let old_block = self.get_block(x, y, z)?;
386386
if old_block == block {
387-
// debug!("Block is the same as the old block");
387+
debug!("Block is the same as the old block");
388388
return Ok(());
389389
}
390390
// Get section
@@ -404,7 +404,7 @@ impl Chunk {
404404
if let PaletteType::Single(val) = &section.block_states.block_data {
405405
new_contents = PaletteType::Indirect {
406406
bits_per_block: 4,
407-
data: vec![0; 255],
407+
data: vec![0; 256],
408408
palette: vec![val.clone()],
409409
};
410410
converted = true;
@@ -464,8 +464,9 @@ impl Chunk {
464464
});
465465
// Set block
466466
let blocks_per_i64 = (64f64 / *bits_per_block as f64).floor() as usize;
467-
let index = ((y & 0xf) * 256 + (z & 0xf) * 16 + (x & 0xf)) as usize;
468-
let i64_index = (index / blocks_per_i64) - 1;
467+
let index =
468+
((y.abs() & 0xf) * 256 + (z.abs() & 0xf) * 16 + (x.abs() & 0xf)) as usize;
469+
let i64_index = index / blocks_per_i64;
469470
let packed_u64 = data
470471
.get_mut(i64_index)
471472
.ok_or(InvalidBlockStateData(format!(
@@ -500,6 +501,10 @@ impl Chunk {
500501
})
501502
.map(|(_, count)| *count as u16)
502503
.sum();
504+
505+
self.sections
506+
.iter_mut()
507+
.for_each(|section| section.optimise().unwrap());
503508
Ok(())
504509
}
505510

@@ -524,10 +529,11 @@ impl Chunk {
524529
let section = self
525530
.sections
526531
.iter()
527-
.find(|section| section.y == (y >> 4) as i8)
532+
.find(|section| section.y == y.div_floor(16) as i8)
528533
.ok_or(WorldError::SectionOutOfBounds(y >> 4))?;
529534
match &section.block_states.block_data {
530535
PaletteType::Single(val) => {
536+
debug!(x, y, z, "Single palette type");
531537
let block_id = val.val;
532538
ID2BLOCK
533539
.get(&block_id)
@@ -547,7 +553,7 @@ impl Chunk {
547553
}
548554
let blocks_per_i64 = (64f64 / *bits_per_block as f64).floor() as usize;
549555
let index = ((y & 0xf) * 256 + (z & 0xf) * 16 + (x & 0xf)) as usize;
550-
let i64_index = (index / blocks_per_i64) - 1;
556+
let i64_index = index / blocks_per_i64;
551557
let packed_u64 = data.get(i64_index).ok_or(InvalidBlockStateData(format!(
552558
"Invalid block state data at index {}",
553559
i64_index
@@ -569,7 +575,7 @@ impl Chunk {
569575
}
570576

571577
pub fn new(x: i32, z: i32, dimension: String) -> Self {
572-
let sections: Vec<Section> = (0..24)
578+
let sections: Vec<Section> = (-4..20)
573579
.map(|y| Section {
574580
y: y as i8,
575581
block_states: BlockStates {

src/lib/world/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![feature(hasher_prefixfree_extras)]
2+
#![feature(int_roundings)]
23

34
pub mod chunk_format;
45
mod db_functions;

0 commit comments

Comments
 (0)