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

Add light updates #15

Draft
wants to merge 58 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
d34916c
Add light network packet
DimitriTimoz Nov 8, 2023
f2e9c2e
Array to BitSet ChunkData
DimitriTimoz Nov 8, 2023
657e9f0
Setter HeightMap and Getter WIP
DimitriTimoz Nov 8, 2023
a14c53f
The heightMap
DimitriTimoz Nov 10, 2023
07c1fbf
Fix somethings
DimitriTimoz Nov 10, 2023
addb975
Add heightmap to ChunkColumn (must be tested)
DimitriTimoz Nov 10, 2023
6e43296
Use the height and not the coordinate
DimitriTimoz Nov 11, 2023
d2b5de2
New base & setter when edit block WIP
DimitriTimoz Nov 11, 2023
0263e4e
Add HeightMap is updated impl
DimitriTimoz Nov 11, 2023
12a5ec4
Add SectionLightData structure & setter/getter
DimitriTimoz Nov 11, 2023
a3ecae9
sky light init done
DimitriTimoz Nov 11, 2023
1a57c64
Change is_air_block to is_transparent
DimitriTimoz Nov 11, 2023
97a77a1
Add Test for set and getter
DimitriTimoz Nov 11, 2023
635cef5
Set Layer of light
DimitriTimoz Nov 11, 2023
42a7310
Set region & more
DimitriTimoz Nov 12, 2023
c4b4207
Init skylight FlatChunk
DimitriTimoz Nov 12, 2023
2b46155
Add get_hiest_block_at
DimitriTimoz Nov 12, 2023
6bbf96a
Use more appropriate conversion to Block
DimitriTimoz Nov 12, 2023
ad61f59
WIP explore_sky_light_from_heap
DimitriTimoz Nov 12, 2023
d60d6bc
Fix update light from highest block break
DimitriTimoz Nov 12, 2023
fa8484f
fix heightMap
DimitriTimoz Nov 13, 2023
1e17721
Flat world light update
DimitriTimoz Nov 13, 2023
adfd07f
get network heightMap
DimitriTimoz Nov 13, 2023
9a43a43
Merge branch 'main' into light-updates
DimitriTimoz Nov 13, 2023
9b550c4
Impl default for Slot
DimitriTimoz Nov 13, 2023
ddbe987
Refactor chunk loading and sending code
DimitriTimoz Nov 13, 2023
985da34
Remove get heightMap network
DimitriTimoz Nov 14, 2023
366c161
wip pose block & update light
DimitriTimoz Nov 14, 2023
903eaa1
roll back
DimitriTimoz Nov 14, 2023
8409239
fix load amount chunk
DimitriTimoz Nov 18, 2023
dbfccb3
Flat world update sky light
DimitriTimoz Nov 18, 2023
aa5b002
Fix clear light from
DimitriTimoz Nov 18, 2023
ead4294
backpropagation of light to edit
DimitriTimoz Nov 18, 2023
2bebed7
Refactor sky light calculations and add unit tests
DimitriTimoz Nov 18, 2023
7b45ce0
A bit closer
DimitriTimoz Nov 19, 2023
9c51cba
merge main
DimitriTimoz Nov 19, 2023
7ec12c5
Back to clean code
DimitriTimoz Nov 19, 2023
8df445e
Put architecture
DimitriTimoz Nov 19, 2023
eb13f2e
WIP abstraction
DimitriTimoz Nov 19, 2023
76ec292
Abstraction set block
DimitriTimoz Nov 22, 2023
8573b33
Fix compile
DimitriTimoz Nov 22, 2023
8b213f5
Await the light updating
DimitriTimoz Nov 22, 2023
cfc501b
Fix warnings
DimitriTimoz Nov 22, 2023
2f60466
add abstraction signatures
DimitriTimoz Nov 22, 2023
a9f16a1
Refactor LightManager to use world_map parameter
DimitriTimoz Nov 22, 2023
b52d854
sorry
DimitriTimoz Dec 21, 2023
d868965
Do compile it
DimitriTimoz Dec 23, 2023
7f656b2
Init independant light
DimitriTimoz Dec 23, 2023
34d2e14
Merge pull request #98 from Mubelotix/main
DimitriTimoz Dec 23, 2023
dee1745
Tracing
DimitriTimoz Dec 23, 2023
94ebe62
some instruments
DimitriTimoz Dec 24, 2023
05ed0fd
tracy p64
DimitriTimoz Dec 24, 2023
2ee546e
enable tracing with feature
DimitriTimoz Dec 24, 2023
b596e28
line feeding
DimitriTimoz Dec 24, 2023
111270c
player tick span
DimitriTimoz Dec 24, 2023
2eb5b4d
span in feature
DimitriTimoz Dec 24, 2023
a610fdf
Merge branch 'light-updates' into tracing-system
DimitriTimoz Dec 24, 2023
75cf2f5
Merge pull request #100 from Mubelotix/tracing-system
DimitriTimoz Dec 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions minecraft-entities-derive/examples/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum AnyEntity {
Cow(Cow),
}

#[derive(Debug)]
pub struct Handler<T> {
uuid: Eid,
world: Arc<Mutex<()>>,
Expand Down
13 changes: 13 additions & 0 deletions minecraft-positions/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod shards;

use std::ops::{AddAssign, Add};

pub use minecraft_protocol::packets::Position as NetworkPosition;

#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
Expand Down Expand Up @@ -175,6 +177,17 @@ pub struct ChunkColumnPosition {
pub cz: i32,
}

impl Add<ChunkColumnPosition> for ChunkColumnPosition {
type Output = ChunkColumnPosition;

fn add(self, rhs: ChunkColumnPosition) -> Self::Output {
ChunkColumnPosition {
cx: self.cx + rhs.cx,
cz: self.cz + rhs.cz,
}
}
}

impl ChunkColumnPosition {
pub fn chunk(&self, cy: i32) -> ChunkPosition {
ChunkPosition {
Expand Down
5 changes: 4 additions & 1 deletion minecraft-positions/src/shards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use crate::*;

impl ChunkColumnPosition {
pub fn shard(&self, shard_count: usize) -> usize {
(self.cx + self.cz).unsigned_abs() as usize % shard_count
const REGION_SIZE: i32 = 8;
let region_x = self.cx.div_euclid(REGION_SIZE);
let region_z = self.cz.div_euclid(REGION_SIZE);
(region_x + region_z).unsigned_abs() as usize % shard_count
}
}
7 changes: 7 additions & 0 deletions minecraft-protocol/build/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ pub enum Item {{
{variants}
}}

impl Default for Item {{
#[inline]
fn default() -> Self {{
Item::Air
}}
}}

impl Item {{
#[inline]
pub fn from_id(id: u32) -> Option<Item> {{
Expand Down
10 changes: 5 additions & 5 deletions minecraft-protocol/src/components/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{nbt::NbtTag, *, components::blocks::BlockEntity};
use crate::{nbt::NbtTag, *, components::blocks::BlockEntity, packets::serializer::BitSet};

/// A complex data structure including block data and optionally entities of a chunk.
///
Expand All @@ -24,19 +24,19 @@ pub struct ChunkData<'a> {
/// BitSet containing bits for each section in the world + 2.
/// Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Sky Light array below.
/// The least significant bit is for blocks 16 blocks to 1 block below the min world height (one section below the world), while the most significant bit covers blocks 1 to 16 blocks above the max world height (one section above the world).
pub sky_light_mask: Array<'a, u64, VarInt>,
pub sky_light_mask: BitSet<'a>,
/// BitSet containing bits for each section in the world + 2.
/// Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Block Light array below.
/// The order of bits is the same as in Sky Light Mask.
pub block_light_mask: Array<'a, u64, VarInt>,
pub block_light_mask: BitSet<'a>,
/// BitSet containing bits for each section in the world + 2.
/// Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Block Light array below.
/// The order of bits is the same as in Sky Light Mask.
pub empty_sky_light_mask: Array<'a, u64, VarInt>,
pub empty_sky_light_mask: BitSet<'a>,
/// BitSet containing bits for each section in the world + 2.
/// Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Block Light array below.
/// The order of bits is the same as in Sky Light Mask.
pub empty_block_light_mask: Array<'a, u64, VarInt>,
pub empty_block_light_mask: BitSet<'a>,
/// Length should match the number of bits set in Sky Light Mask.
/// Each entry is an array of 2048 bytes.
/// There is 1 array for each bit set to true in the sky light mask, starting with the lowest value. Half a byte per light value. Indexed ((y<<8) | (z<<4) | x) / 2
Expand Down
2 changes: 1 addition & 1 deletion minecraft-protocol/src/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ pub mod slots;
pub mod sound;
pub mod tags;
pub mod teams;
pub mod trades;
pub mod trades;
2 changes: 1 addition & 1 deletion minecraft-protocol/src/components/slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub struct Slot {
}

#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug, Clone, MinecraftPacketPart)]
#[derive(Debug, Clone, Default, MinecraftPacketPart)]
pub struct SlotItem {
/// The [item](crate::ids::items::Item).
/// Item IDs are distinct from [block IDs](crate::ids::blocks::Block); see [crate::ids] for more information.
Expand Down
6 changes: 6 additions & 0 deletions minecraft-protocol/src/nbt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ pub enum NbtTag {
RootCompound(String, HashMap<String, NbtTag>),
}

impl Default for NbtTag {
fn default() -> Self {
NbtTag::Null
}
}

impl NbtTag {
#[inline]
pub fn is_null(&self) -> bool {
Expand Down
16 changes: 14 additions & 2 deletions minecraft-protocol/src/packets/play_clientbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,20 @@ pub enum ClientboundPacket<'a> {

/// Updates light levels for a chunk
UpdateLight {
/// TODO: parse this
data: RawBytes<'a>,
/// Chunk coordinate (block coordinate divided by 16, rounded down)
cx: VarInt,
/// Chunk coordinate (block coordinate divided by 16, rounded down)
cz: VarInt,
/// BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Sky Light array below. The least significant bit is for blocks 16 blocks to 1 block below the min world height (one section below the world), while the most significant bit covers blocks 1 to 16 blocks above the max world height (one section above the world).
sky_light_mask: BitSet<'a>,
/// BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has data in the Block Light array below. The order of bits is the same as in Sky Light Mask.
block_light_mask: BitSet<'a>,
/// BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has all zeros for its Sky Light data. The order of bits is the same as in Sky Light Mask.
empty_sky_light_mask: BitSet<'a>,
/// BitSet containing bits for each section in the world + 2. Each set bit indicates that the corresponding 16×16×16 chunk section has all zeros for its Block Light data. The order of bits is the same as in Sky Light Mask.
empty_block_light_mask: BitSet<'a>,
sky_light_arrays: Array<'a, Array<'a, u8, VarInt>, VarInt>,
block_light_arrays: Array<'a, Array<'a, u8, VarInt>, VarInt>,
},

/// See [Protocol Encryption](https://wiki.vg/Protocol_Encryption) for information on logging in.
Expand Down
10 changes: 9 additions & 1 deletion minecraft-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@ edition = "2021"

[dependencies]
env_logger = "0.10.0"
log = "0.4.20"
tokio = { version = "1.33.0", features = ["full"] }
futures = "0.3.29"
minecraft-protocol = { path="../minecraft-protocol" }
minecraft-positions = { path="../minecraft-positions" }
minecraft-entities-derive = { path="../minecraft-entities-derive" }
rand = "0.8.4"
tracy-client = { version = "0.16.4", features = ["enable"], optional = true}
tracing-tracy = { version = "0.10.4", features = ["enable", "system-tracing"], optional = true}
tracing-subscriber = "0.3.18"
log = "0.4.17"
tracing = { version = "0.1", features = ["attributes"] }

[features]
default = []
tracing = ["tracy-client", "tracing-tracy"]
3 changes: 3 additions & 0 deletions minecraft-server/src/entities/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use super::*;
init(self, server_msg_rcvr: BroadcastReceiver<ServerMessage>);
}
)]

#[derive(Debug)]
pub struct Entity {
pub position: Position,
pub velocity: Translation,
Expand All @@ -29,6 +31,7 @@ pub struct Entity {
}

impl Handler<Entity> {
#[instrument(skip_all)]
pub async fn init(self, server_msg_rcvr: BroadcastReceiver<ServerMessage>) {
self.insert_task("newton", tokio::spawn(newton_task(self.clone(), server_msg_rcvr))).await;
}
Expand Down
70 changes: 36 additions & 34 deletions minecraft-server/src/entities/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ impl Player {
}

impl Handler<Player> {
#[instrument(skip_all)]
async fn update_center_chunk(self) {
let Some((old_center_chunk, new_center_chunk, render_distance)) = self.mutate(|player| {
let old_center_chunk = player.center_chunk.clone();
Expand Down Expand Up @@ -115,10 +116,10 @@ impl Handler<Player> {
if loaded_chunks_after == player.loaded_chunks { return (None, EntityChanges::nothing()) };
let mut newly_loaded_chunks: Vec<_> = loaded_chunks_after.difference(&player.loaded_chunks).cloned().collect();
let unloaded_chunks: Vec<_> = player.loaded_chunks.difference(&loaded_chunks_after).cloned().collect();
for skipped in newly_loaded_chunks.iter().skip(50) {
for skipped in newly_loaded_chunks.iter().skip(2) {
loaded_chunks_after.remove(skipped);
}
newly_loaded_chunks.truncate(50);
newly_loaded_chunks.truncate(2);
let uuid = player.info.uuid;
player.loaded_chunks = loaded_chunks_after.clone();
(Some((loaded_chunks_after, newly_loaded_chunks, unloaded_chunks, uuid)), EntityChanges::other())
Expand All @@ -128,39 +129,17 @@ impl Handler<Player> {
self.world.update_loaded_chunks(uuid, loaded_chunks_after).await;

// Send the chunks to the client
let mut heightmaps = HashMap::new();
heightmaps.insert(String::from("MOTION_BLOCKING"), NbtTag::LongArray(vec![0; 37]));
let heightmaps = NbtTag::Compound(heightmaps);
let mut chunks = Vec::new();
for newly_loaded_chunk in newly_loaded_chunks {
let mut column = Vec::new();
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: 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(),
}
};
self.send_packet(chunk_data).await;
let chunk = self.world.get_network_chunk_column_data(newly_loaded_chunk.clone()).await.unwrap_or_else(|| {
error!("Chunk not loaded: {newly_loaded_chunk:?}");
panic!("Chunk not loaded: {newly_loaded_chunk:?}");
});
chunks.push(chunk);
}

for chunk in chunks {
self.send_raw_packet(chunk).await;
}

// Tell the client to unload chunks
Expand All @@ -172,6 +151,7 @@ impl Handler<Player> {
}
}

#[instrument(skip_all)]
async fn send_packet<'a>(&self, packet: PlayClientbound<'a>) {
let packet = packet.serialize_minecraft_packet().unwrap();
let packets_sent = self.mutate(|player| {
Expand All @@ -185,10 +165,28 @@ impl Handler<Player> {
packet_sender.send(packet).await.unwrap();
}

#[instrument(skip_all)]
async fn send_raw_packet(&self, packet: Vec<u8>) {
let packets_sent = self.mutate(|player| {
player.packets_sent += 1;
(player.packets_sent, EntityChanges::other())
}).await.unwrap_or(0);
if packets_sent > 500 {
warn!("Many packets sent ({packets_sent})");
}
let Some(packet_sender) = self.observe(|player| player.packet_sender.clone()).await else {return};
packet_sender.send(packet).await.unwrap();
}

async fn on_server_message(self, message: ServerMessage) {
use ServerMessage::*;
match message {
Tick(tick_id) => {
#[cfg(feature = "tracing")] {
let span = info_span!("player tick");
let _enter: tracing::span::Entered<'_> = span.enter();
}

if tick_id % (20*10) == 0 {
self.send_packet(PlayClientbound::KeepAlive { keep_alive_id: tick_id as u64 }).await;
}
Expand All @@ -201,6 +199,7 @@ impl Handler<Player> {
}
}

#[instrument(skip_all)]
async fn on_world_change(self, change: WorldChange) {
match change {
WorldChange::Block(position, block) => {
Expand Down Expand Up @@ -293,6 +292,7 @@ impl Handler<Player> {
}
}

#[instrument(skip_all)]
async fn on_packet<'a>(mut self, packet: PlayServerbound<'a>) {
use PlayServerbound::*;
match packet {
Expand Down Expand Up @@ -367,6 +367,7 @@ impl Handler<Player> {
}
}

#[instrument(skip_all)]
async fn handle_player(h: Handler<Player>, uuid: UUID, stream: TcpStream, packet_receiver: MpscReceiver<Vec<u8>>, server_msg_rcvr: BroadcastReceiver<ServerMessage>, change_receiver: MpscReceiver<WorldChange>) {
let r = handle_player_inner(h.clone(), stream, packet_receiver, server_msg_rcvr, change_receiver).await;
match r {
Expand All @@ -376,6 +377,7 @@ async fn handle_player(h: Handler<Player>, uuid: UUID, stream: TcpStream, packet
h.world.remove_loader(uuid).await;
}

#[instrument(skip_all)]
async fn handle_player_inner(h: Handler<Player>, stream: TcpStream, mut packet_receiver: MpscReceiver<Vec<u8>>, mut server_msg_rcvr: BroadcastReceiver<ServerMessage>, mut change_receiver: MpscReceiver<WorldChange>) -> Result<(), ()> {
let (mut reader_stream, mut writer_stream) = stream.into_split();

Expand Down
16 changes: 16 additions & 0 deletions minecraft-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ impl std::future::Future for ServerFuture {

#[tokio::main]
async fn main() {
#[cfg(feature = "tracing")]
#[global_allocator]
static GLOBAL: tracy_client::ProfiledAllocator<std::alloc::System> =
tracy_client::ProfiledAllocator::new(std::alloc::System, 100);

use tracing_subscriber::{fmt, layer::SubscriberExt, Registry};

let subscriber = Registry::default()
.with(fmt::layer());
#[cfg(feature = "tracing")]
let subscriber = subscriber
.with(tracing_tracy::TracyLayer::new());

tracing::subscriber::set_global_default(subscriber)
.expect("setting up tracing");

env_logger::init();

let server = ServerBehavior::init().await;
Expand Down
2 changes: 2 additions & 0 deletions minecraft-server/src/player_handler/connect.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::*;


#[instrument(skip_all)]
pub async fn handle_connection(
mut stream: TcpStream,
addr: SocketAddr,
Expand Down
Loading
Loading