Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial Redstone #621

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
108f3a6
Add scheduled block ticks
4lve Mar 10, 2025
e351942
Fix typos
4lve Mar 10, 2025
d872b16
fix scheduled block ticks
4lve Mar 10, 2025
680a659
Merge branch 'Pumpkin-MC:master' into master
4lve Mar 11, 2025
de3622e
Default to empty vec
4lve Mar 11, 2025
12f3d94
Merge branch 'Pumpkin-MC:master' into master
4lve Mar 12, 2025
a1b784f
Proper Block Updates
4lve Mar 12, 2025
9f3e00e
Basic redstone works LFG!
4lve Mar 12, 2025
53d301b
add buttons and lamps
4lve Mar 12, 2025
f4cf344
observers
4lve Mar 12, 2025
573be31
Only send update packet at end of tick
4lve Mar 13, 2025
80a5f33
hmm
4lve Mar 14, 2025
203485c
Start implementing MCHPRS
4lve Mar 14, 2025
697babe
redstone connections done
4lve Mar 14, 2025
b80dfe2
visual state done
4lve Mar 14, 2025
a084cfa
Begin implementing multi_block_update
4lve Mar 15, 2025
702e76b
Redstone works partially
4lve Mar 15, 2025
f1c38e7
Merge remote-tracking branch 'upstream/master'
4lve Mar 15, 2025
62b6dd9
Fix typos
4lve Mar 15, 2025
85e78c3
Think I know what caused the client side desync
4lve Mar 15, 2025
ba50376
Fix clippy
4lve Mar 15, 2025
08c8857
Change fluid tick type
4lve Mar 16, 2025
f3d49bb
Merge remote-tracking branch 'upstream/master'
4lve Mar 16, 2025
8c621f4
Something is broken
4lve Mar 16, 2025
80bea46
Don't use RWLock for block_ticks
4lve Mar 17, 2025
c363aa8
fix delay not decrementing
4lve Mar 17, 2025
bacbae7
Remove server from scheduled block ticks
4lve Mar 17, 2025
01ecf19
Fix redstone bug
4lve Mar 17, 2025
1267bf1
fix hardpower
4lve Mar 17, 2025
3dc8038
Merge remote-tracking branch 'upstream/master'
4lve Mar 17, 2025
9b18011
Fix tick lag
4lve Mar 17, 2025
334b430
Fix comperators
4lve Mar 17, 2025
92f2e91
Don't loop every tick
4lve Mar 17, 2025
488cdf1
Fix panic
4lve Mar 18, 2025
ce8d784
Fix redstone not powering block below
4lve Mar 18, 2025
020613e
make redstone_wire emit hard power
4lve Mar 18, 2025
a30aa7e
Add target block
4lve Mar 18, 2025
4f7a1cf
fix clippy
4lve Mar 18, 2025
d411d7c
Merge remote-tracking branch 'upstream/master'
4lve Mar 19, 2025
a10e03f
Merge
4lve Mar 19, 2025
06bc9e1
Merge remote-tracking branch 'upstream/master'
4lve Mar 20, 2025
0139597
Merge remote-tracking branch 'upstream/master'
4lve Mar 20, 2025
1b25984
merge
4lve Mar 20, 2025
b890bc0
add redstone torches
4lve Mar 20, 2025
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
45 changes: 26 additions & 19 deletions pumpkin-data/build/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ use serde::Deserialize;
use std::collections::{HashMap, HashSet};
use syn::{Ident, LitBool, LitInt, LitStr};

fn is_state_solid(state: &BlockState, all_shapes: &[CollisionShape]) -> bool {
// Needs min xyz to be 0,0,0 and max xyz to be 1,1,1
state.collision_shapes.iter().any(|shape| {
let shape = all_shapes.get(*shape as usize).unwrap();
shape.min[0] == 0.0
&& shape.min[1] == 0.0
&& shape.min[2] == 0.0
&& shape.max[0] == 1.0
&& shape.max[1] == 1.0
&& shape.max[2] == 1.0
})
}

fn const_block_name_from_block_name(block: &str) -> String {
block.to_shouty_snake_case()
}
Expand Down Expand Up @@ -327,8 +340,9 @@ pub struct BlockStateRef {
pub state_idx: u16,
}

impl ToTokens for BlockState {
fn to_tokens(&self, tokens: &mut TokenStream) {
impl BlockState {
fn to_tokens(&self, all_shapes: &[CollisionShape]) -> TokenStream {
let mut tokens = TokenStream::new();
//let id = LitInt::new(&self.id.to_string(), Span::call_site());
let air = LitBool::new(self.air, Span::call_site());
let luminance = LitInt::new(&self.luminance.to_string(), Span::call_site());
Expand Down Expand Up @@ -359,6 +373,8 @@ impl ToTokens for BlockState {
.iter()
.map(|shape_id| LitInt::new(&shape_id.to_string(), Span::call_site()));

let is_solid = is_state_solid(self, all_shapes);

tokens.extend(quote! {
PartialBlockState {
air: #air,
Expand All @@ -372,8 +388,10 @@ impl ToTokens for BlockState {
opacity: #opacity,
block_entity_type: #block_entity_type,
is_liquid: #is_liquid,
is_solid: #is_solid,
}
});
tokens
}
}

Expand Down Expand Up @@ -1001,7 +1019,9 @@ pub(crate) fn build() -> TokenStream {
.iter()
.map(|shape| shape.to_token_stream());

let unique_states = unique_states.iter().map(|state| state.to_token_stream());
let unique_states = unique_states
.iter()
.map(|state| state.to_tokens(&blocks_assets.shapes));

let block_props = block_properties.iter().map(|prop| prop.to_token_stream());
let properties = property_enums.values().map(|prop| prop.to_token_stream());
Expand Down Expand Up @@ -1065,6 +1085,7 @@ pub(crate) fn build() -> TokenStream {
pub opacity: Option<u32>,
pub block_entity_type: Option<u32>,
pub is_liquid: bool,
pub is_solid: bool,
}

#[derive(Clone, Debug)]
Expand All @@ -1081,6 +1102,7 @@ pub(crate) fn build() -> TokenStream {
pub opacity: Option<u32>,
pub block_entity_type: Option<u32>,
pub is_liquid: bool,
pub is_solid: bool,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1124,22 +1146,6 @@ pub(crate) fn build() -> TokenStream {
pub max: [f64; 3],
}

#[derive(Clone, Copy, Debug)]
pub struct BlockStateData {
pub air: bool,
pub luminance: u8,
pub burnable: bool,
pub tool_required: bool,
pub hardness: f32,
pub sided_transparency: bool,
pub replaceable: bool,
pub collision_shapes: &'static [u16],
pub opacity: Option<u32>,
pub block_entity_type: Option<u32>,
pub is_liquid: bool,
}


pub trait BlockProperties where Self: 'static {
// Convert properties to an index (`0` to `N-1`).
fn to_index(&self) -> u16;
Expand Down Expand Up @@ -1257,6 +1263,7 @@ pub(crate) fn build() -> TokenStream {
opacity: partial_state.opacity,
block_entity_type: partial_state.block_entity_type,
is_liquid: partial_state.is_liquid,
is_solid: partial_state.is_solid,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/client/play/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ mod initialize_world_border;
mod keep_alive;
mod level_event;
mod login;
mod multi_block_update;
mod open_screen;
mod open_sign_editor;
mod particle;
Expand Down Expand Up @@ -116,6 +117,7 @@ pub use initialize_world_border::*;
pub use keep_alive::*;
pub use level_event::*;
pub use login::*;
pub use multi_block_update::*;
pub use open_screen::*;
pub use open_sign_editor::*;
pub use particle::*;
Expand Down
49 changes: 49 additions & 0 deletions pumpkin-protocol/src/client/play/multi_block_update.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use pumpkin_data::packet::clientbound::PLAY_SECTION_BLOCKS_UPDATE;
use pumpkin_util::math::{
position::{BlockPos, chunk_section_from_pos, pack_local_chunk_section},
vector3::{self, Vector3},
};

use pumpkin_macros::packet;
use serde::{Serialize, ser::SerializeTuple};

use crate::codec::{var_int::VarInt, var_long::VarLong};

#[packet(PLAY_SECTION_BLOCKS_UPDATE)]
pub struct CMultiBlockUpdate {
chunk_section: Vector3<i32>,
positions_to_state_ids: Vec<(i16, i32)>,
}

impl CMultiBlockUpdate {
pub fn new(positions_to_state_ids: Vec<(BlockPos, u16)>) -> Self {
let chunk_section = chunk_section_from_pos(&positions_to_state_ids[0].0);
Self {
chunk_section,
positions_to_state_ids: positions_to_state_ids
.into_iter()
.map(|(position, state_id)| (pack_local_chunk_section(&position), state_id as i32))
.collect(),
}
}
}

impl Serialize for CMultiBlockUpdate {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut tuple = serializer.serialize_tuple(2 + self.positions_to_state_ids.len())?;

tuple.serialize_element(&vector3::packed_chunk_pos(&self.chunk_section))?;
tuple.serialize_element(&VarInt::from(self.positions_to_state_ids.len() as i32))?;

for (position, state_id) in &self.positions_to_state_ids {
let long = ((*state_id as u64) << 12) | (*position as u64);
let var_long = VarLong::from(long as i64);
tuple.serialize_element(&var_long)?;
}

tuple.end()
}
}
53 changes: 51 additions & 2 deletions pumpkin-util/src/math/position.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
use super::vector3::Vector3;
use super::{
get_section_cord,
vector3::{self, Vector3},
};
use std::fmt;
use std::hash::Hash;

use crate::math::vector2::Vector2;
use num_traits::Euclid;
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
/// Aka Block Position
pub struct BlockPos(pub Vector3<i32>);

impl BlockPos {
pub fn new(x: i32, y: i32, z: i32) -> Self {
Self(Vector3::new(x, y, z))
}

pub fn chunk_and_chunk_relative_position(&self) -> (Vector2<i32>, Vector3<i32>) {
let (z_chunk, z_rem) = self.0.z.div_rem_euclid(&16);
let (x_chunk, x_rem) = self.0.x.div_rem_euclid(&16);
Expand All @@ -28,6 +35,18 @@ impl BlockPos {
};
(chunk_coordinate, relative)
}
pub fn section_relative_position(&self) -> Vector3<i32> {
let (_z_chunk, z_rem) = self.0.z.div_rem_euclid(&16);
let (_x_chunk, x_rem) = self.0.x.div_rem_euclid(&16);
let (_y_chunk, y_rem) = self.0.y.div_rem_euclid(&16);

// Since we divide by 16 remnant can never exceed u8
Vector3 {
x: x_rem,
z: z_rem,
y: y_rem,
}
}
pub fn from_i64(encoded_position: i64) -> Self {
BlockPos(Vector3 {
x: (encoded_position >> 38) as i32,
Expand Down Expand Up @@ -55,6 +74,14 @@ impl BlockPos {
pub fn offset(&self, offset: Vector3<i32>) -> Self {
BlockPos(self.0 + offset)
}

pub fn up(&self) -> Self {
self.offset(Vector3::new(0, 1, 0))
}

pub fn down(&self) -> Self {
self.offset(Vector3::new(0, -1, 0))
}
}
impl Serialize for BlockPos {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
Expand Down Expand Up @@ -99,3 +126,25 @@ impl fmt::Display for BlockPos {
write!(f, "{}, {}, {}", self.0.x, self.0.y, self.0.z)
}
}

#[must_use]
pub const fn chunk_section_from_pos(block_pos: &BlockPos) -> Vector3<i32> {
let block_pos = block_pos.0;
Vector3::new(
get_section_cord(block_pos.x),
get_section_cord(block_pos.y),
get_section_cord(block_pos.z),
)
}

pub const fn get_local_cord(cord: i32) -> i32 {
cord & 15
}

#[must_use]
pub fn pack_local_chunk_section(block_pos: &BlockPos) -> i16 {
let x = get_local_cord(block_pos.0.x);
let z = get_local_cord(block_pos.0.z);
let y = get_local_cord(block_pos.0.y);
vector3::packed_local(&Vector3::new(x, y, z))
}
4 changes: 4 additions & 0 deletions pumpkin-util/src/math/vector2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,7 @@ impl Math for f32 {}
impl Math for i32 {}
impl Math for i64 {}
impl Math for i8 {}

pub const fn to_chunk_pos(vec: &Vector2<i32>) -> Vector2<i32> {
Vector2::new(vec.x >> 4, vec.z >> 4)
}
18 changes: 18 additions & 0 deletions pumpkin-util/src/math/vector3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,21 @@ impl serde::Serialize for Vector3<i32> {
serializer.serialize_bytes(&buf)
}
}

#[inline]
pub const fn packed_chunk_pos(vec: &Vector3<i32>) -> i64 {
let mut result = 0i64;
// Need to go to i64 first to conserve sign
result |= (vec.x as i64 & 0x3FFFFF) << 42;
result |= (vec.z as i64 & 0x3FFFFF) << 20;
result |= vec.y as i64 & 0xFFFFF;
result
}

#[inline]
pub const fn packed_local(vec: &Vector3<i32>) -> i16 {
let x = vec.x as i16;
let y = vec.y as i16;
let z = vec.z as i16;
(x << 8) | (z << 4) | y
}
Loading