Fix redstone wire with non-solid blocks (#1124)

* Fix redstone wire when interacting with glass and non-full blocks

* Use is_solid_block to determine whether redstone wire should be blocked

* Fix: incorrect uses of BlockState.is_solid()

* run cargo fmt

* split state_flags into 2 u8's and remove BlockState.blocks_wire() methods

* Resolve clippy warning

* Revert state_flags back to a single u16

---------

Co-authored-by: Alexander Medvedev <lilalexmed@proton.me>
This commit is contained in:
Bram
2025-08-18 18:11:42 +02:00
committed by GitHub
parent 47254b14ba
commit 56ad480ba2
9 changed files with 4615 additions and 32546 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -210,7 +210,7 @@
"type": "boolean"
},
{
"hash_key": 1113709830,
"hash_key": -345518141,
"enum_name": "horizontal_axis",
"serialized_name": "axis",
"type": "enum",
@@ -220,7 +220,7 @@
]
},
{
"hash_key": -929870136,
"hash_key": 1136350348,
"enum_name": "axis",
"serialized_name": "axis",
"type": "enum",
@@ -267,7 +267,7 @@
"type": "boolean"
},
{
"hash_key": 615899206,
"hash_key": -122500183,
"enum_name": "facing",
"serialized_name": "facing",
"type": "enum",
@@ -281,7 +281,7 @@
]
},
{
"hash_key": -1836519164,
"hash_key": 442763041,
"enum_name": "hopper_facing",
"serialized_name": "facing",
"type": "enum",
@@ -294,7 +294,7 @@
]
},
{
"hash_key": 1449460846,
"hash_key": -964161874,
"enum_name": "horizontal_facing",
"serialized_name": "facing",
"type": "enum",
@@ -322,7 +322,7 @@
"max": 4
},
{
"hash_key": 704752987,
"hash_key": 1433802136,
"enum_name": "orientation",
"serialized_name": "orientation",
"type": "enum",
@@ -342,7 +342,7 @@
]
},
{
"hash_key": -589629896,
"hash_key": 164601017,
"enum_name": "block_face",
"serialized_name": "face",
"type": "enum",
@@ -353,7 +353,7 @@
]
},
{
"hash_key": -706159110,
"hash_key": -1479871907,
"enum_name": "attachment",
"serialized_name": "attachment",
"type": "enum",
@@ -365,7 +365,7 @@
]
},
{
"hash_key": -1010454105,
"hash_key": 1242384140,
"enum_name": "east_wall_shape",
"serialized_name": "east",
"type": "enum",
@@ -376,7 +376,7 @@
]
},
{
"hash_key": -2146472545,
"hash_key": 106365700,
"enum_name": "north_wall_shape",
"serialized_name": "north",
"type": "enum",
@@ -387,7 +387,7 @@
]
},
{
"hash_key": -2003237417,
"hash_key": 249600828,
"enum_name": "south_wall_shape",
"serialized_name": "south",
"type": "enum",
@@ -398,7 +398,7 @@
]
},
{
"hash_key": -993711563,
"hash_key": 1259126682,
"enum_name": "west_wall_shape",
"serialized_name": "west",
"type": "enum",
@@ -409,7 +409,7 @@
]
},
{
"hash_key": -891207346,
"hash_key": 1326347552,
"enum_name": "east_wire_connection",
"serialized_name": "east",
"type": "enum",
@@ -420,7 +420,7 @@
]
},
{
"hash_key": -2027225786,
"hash_key": 190329112,
"enum_name": "north_wire_connection",
"serialized_name": "north",
"type": "enum",
@@ -431,7 +431,7 @@
]
},
{
"hash_key": -1883990658,
"hash_key": 333564240,
"enum_name": "south_wire_connection",
"serialized_name": "south",
"type": "enum",
@@ -442,7 +442,7 @@
]
},
{
"hash_key": -874464804,
"hash_key": 1343090094,
"enum_name": "west_wire_connection",
"serialized_name": "west",
"type": "enum",
@@ -453,7 +453,7 @@
]
},
{
"hash_key": 1994141019,
"hash_key": -985505033,
"enum_name": "double_block_half",
"serialized_name": "half",
"type": "enum",
@@ -463,7 +463,7 @@
]
},
{
"hash_key": 1394210966,
"hash_key": -603716111,
"enum_name": "block_half",
"serialized_name": "half",
"type": "enum",
@@ -473,7 +473,7 @@
]
},
{
"hash_key": -862394631,
"hash_key": 1721731568,
"enum_name": "rail_shape",
"serialized_name": "shape",
"type": "enum",
@@ -491,7 +491,7 @@
]
},
{
"hash_key": -460429633,
"hash_key": -1225380339,
"enum_name": "straight_rail_shape",
"serialized_name": "shape",
"type": "enum",
@@ -737,7 +737,7 @@
"max": 15
},
{
"hash_key": -73964960,
"hash_key": -535087379,
"enum_name": "bed_part",
"serialized_name": "part",
"type": "enum",
@@ -747,7 +747,7 @@
]
},
{
"hash_key": 1679311508,
"hash_key": 540703261,
"enum_name": "chest_type",
"serialized_name": "type",
"type": "enum",
@@ -758,7 +758,7 @@
]
},
{
"hash_key": -2002778816,
"hash_key": 418273440,
"enum_name": "comparator_mode",
"serialized_name": "mode",
"type": "enum",
@@ -768,7 +768,7 @@
]
},
{
"hash_key": -1919073909,
"hash_key": -2001835059,
"enum_name": "door_hinge",
"serialized_name": "hinge",
"type": "enum",
@@ -778,7 +778,7 @@
]
},
{
"hash_key": 33001972,
"hash_key": 398721620,
"enum_name": "instrument",
"serialized_name": "instrument",
"type": "enum",
@@ -809,7 +809,7 @@
]
},
{
"hash_key": 1871285261,
"hash_key": 1933275976,
"enum_name": "piston_type",
"serialized_name": "type",
"type": "enum",
@@ -819,7 +819,7 @@
]
},
{
"hash_key": -905394011,
"hash_key": 873087795,
"enum_name": "slab_type",
"serialized_name": "type",
"type": "enum",
@@ -830,7 +830,7 @@
]
},
{
"hash_key": -1740411902,
"hash_key": 1011244390,
"enum_name": "stair_shape",
"serialized_name": "shape",
"type": "enum",
@@ -843,7 +843,7 @@
]
},
{
"hash_key": -1314672541,
"hash_key": 916732131,
"enum_name": "structure_block_mode",
"serialized_name": "mode",
"type": "enum",
@@ -855,7 +855,7 @@
]
},
{
"hash_key": -920727949,
"hash_key": 308052410,
"enum_name": "bamboo_leaves",
"serialized_name": "leaves",
"type": "enum",
@@ -866,7 +866,7 @@
]
},
{
"hash_key": 2128694890,
"hash_key": 1137523819,
"enum_name": "tilt",
"serialized_name": "tilt",
"type": "enum",
@@ -878,7 +878,7 @@
]
},
{
"hash_key": -1223244732,
"hash_key": 927991866,
"enum_name": "vertical_direction",
"serialized_name": "vertical_direction",
"type": "enum",
@@ -888,7 +888,7 @@
]
},
{
"hash_key": -533147979,
"hash_key": -773192484,
"enum_name": "thickness",
"serialized_name": "thickness",
"type": "enum",
@@ -901,7 +901,7 @@
]
},
{
"hash_key": -1245005409,
"hash_key": -853514466,
"enum_name": "sculk_sensor_phase",
"serialized_name": "sculk_sensor_phase",
"type": "enum",
@@ -968,7 +968,7 @@
"type": "boolean"
},
{
"hash_key": -357089177,
"hash_key": -914915143,
"enum_name": "trial_spawner_state",
"serialized_name": "trial_spawner_state",
"type": "enum",
@@ -982,7 +982,7 @@
]
},
{
"hash_key": 1811178115,
"hash_key": -1540764535,
"enum_name": "vault_state",
"serialized_name": "vault_state",
"type": "enum",
@@ -994,7 +994,7 @@
]
},
{
"hash_key": -336895357,
"hash_key": -82121400,
"enum_name": "creaking_heart_state",
"serialized_name": "creaking_heart_state",
"type": "enum",
@@ -1011,7 +1011,7 @@
"type": "boolean"
},
{
"hash_key": 1836955881,
"hash_key": 1475742886,
"enum_name": "test_block_mode",
"serialized_name": "mode",
"type": "enum",

View File

@@ -406,7 +406,7 @@ impl ToTokens for CollisionShape {
#[derive(Deserialize, Clone, Debug)]
pub struct BlockState {
pub id: u16,
pub state_flags: u8,
pub state_flags: u16,
pub side_flags: u8,
pub instrument: String, // TODO: make this an enum
pub luminance: u8,
@@ -414,7 +414,6 @@ pub struct BlockState {
pub hardness: f32,
pub collision_shapes: Vec<u16>,
pub outline_shapes: Vec<u16>,
pub has_random_ticks: bool,
pub opacity: Option<u8>,
pub block_entity_type: Option<u16>,
}
@@ -442,6 +441,12 @@ impl PistonBehavior {
}
impl BlockState {
const HAS_RANDOM_TICKS: u16 = 1 << 9;
fn has_random_ticks(&self) -> bool {
self.state_flags & Self::HAS_RANDOM_TICKS != 0
}
fn to_tokens(&self) -> TokenStream {
let mut tokens = TokenStream::new();
let id = LitInt::new(&self.id.to_string(), Span::call_site());
@@ -474,7 +479,6 @@ impl BlockState {
.outline_shapes
.iter()
.map(|shape_id| LitInt::new(&shape_id.to_string(), Span::call_site()));
let has_random_ticks = self.has_random_ticks;
let piston_behavior = &self.piston_behavior.to_tokens();
tokens.extend(quote! {
@@ -488,7 +492,6 @@ impl BlockState {
hardness: #hardness,
collision_shapes: &[#(#collision_shapes),*],
outline_shapes: &[#(#outline_shapes),*],
has_random_tick: #has_random_ticks,
opacity: #opacity,
block_entity_type: #block_entity_type,
}
@@ -687,7 +690,7 @@ pub(crate) fn build() -> TokenStream {
// Collect state IDs that have random ticks.
for state in &block.states {
if state.has_random_ticks {
if state.has_random_ticks() {
let state_id = LitInt::new(&state.id.to_string(), Span::call_site());
random_tick_states.push(state_id);
}

View File

@@ -6,7 +6,7 @@ use crate::{Block, BlockDirection, CollisionShape};
#[derive(Debug)]
pub struct BlockState {
pub id: u16,
pub state_flags: u8,
pub state_flags: u16,
pub side_flags: u8,
pub instrument: Instrument,
pub luminance: u8,
@@ -14,7 +14,6 @@ pub struct BlockState {
pub hardness: f32,
pub collision_shapes: &'static [u16],
pub outline_shapes: &'static [u16],
pub has_random_tick: bool,
/// u8::MAX is used as None
pub opacity: u8,
/// u16::MAX is used as None
@@ -63,6 +62,7 @@ impl BlockState {
self.state_flags & IS_LIQUID != 0
}
/// Returns the legacy value for whether a block is solid.
pub const fn is_solid(&self) -> bool {
self.state_flags & IS_SOLID != 0
}
@@ -71,6 +71,17 @@ impl BlockState {
self.state_flags & IS_FULL_CUBE != 0
}
/// Returns whether the block is solid.
/// Solid blocks conduct redstone and block redstone wire.
/// Non-solid blocks don't allow redstone wire on top to propagate their signal downwards in java.
pub const fn is_solid_block(&self) -> bool {
self.state_flags & IS_SOLID_BLOCK != 0
}
pub const fn has_random_ticks(&self) -> bool {
self.state_flags & HAS_RANDOM_TICKS != 0
}
///isSideSolidFullSquare() in Java!
pub const fn is_side_solid(&self, side: BlockDirection) -> bool {
match side {
@@ -132,20 +143,24 @@ pub struct BlockStateRef {
}
//This is the Layout of state_props in the right order
const IS_AIR: u8 = 0b00000001;
const BURNABLE: u8 = 0b00000010;
const TOOL_REQUIRED: u8 = 0b00000100;
const SIDED_TRANSPARENCY: u8 = 0b00001000;
const REPLACEABLE: u8 = 0b00010000;
const IS_LIQUID: u8 = 0b00100000;
const IS_SOLID: u8 = 0b01000000;
const IS_FULL_CUBE: u8 = 0b10000000;
// state_flags
const IS_AIR: u16 = 1 << 0;
const BURNABLE: u16 = 1 << 1;
const TOOL_REQUIRED: u16 = 1 << 2;
const SIDED_TRANSPARENCY: u16 = 1 << 3;
const REPLACEABLE: u16 = 1 << 4;
const IS_LIQUID: u16 = 1 << 5;
const IS_SOLID: u16 = 1 << 6;
const IS_FULL_CUBE: u16 = 1 << 7;
const IS_SOLID_BLOCK: u16 = 1 << 8;
const HAS_RANDOM_TICKS: u16 = 1 << 9;
const DOWN_SIDE_SOLID: u8 = 0b00000001;
const UP_SIDE_SOLID: u8 = 0b00000010;
const NORTH_SIDE_SOLID: u8 = 0b00000100;
const SOUTH_SIDE_SOLID: u8 = 0b00001000;
const WEST_SIDE_SOLID: u8 = 0b00010000;
const EAST_SIDE_SOLID: u8 = 0b00100000;
const DOWN_CENTER_SOLID: u8 = 0b01000000;
const UP_CENTER_SOLID: u8 = 0b10000000;
// side_flags
const DOWN_SIDE_SOLID: u8 = 1 << 0;
const UP_SIDE_SOLID: u8 = 1 << 1;
const NORTH_SIDE_SOLID: u8 = 1 << 2;
const SOUTH_SIDE_SOLID: u8 = 1 << 3;
const WEST_SIDE_SOLID: u8 = 1 << 4;
const EAST_SIDE_SOLID: u8 = 1 << 5;
const DOWN_CENTER_SOLID: u8 = 1 << 6;
const UP_CENTER_SOLID: u8 = 1 << 7;

View File

@@ -232,7 +232,7 @@ impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
return level;
}
if redstone_level < 15 && source_state.is_solid() {
if redstone_level < 15 && source_state.is_solid_block() {
let source_pos = source_pos.offset(facing.to_offset());
let (source_block, source_state) = world.get_block_and_state(&source_pos).await;

View File

@@ -68,7 +68,7 @@ pub async fn get_redstone_power(
pos: &BlockPos,
facing: BlockDirection,
) -> u8 {
if state.is_solid() {
if state.is_solid_block() {
return std::cmp::max(
get_max_strong_power(world, pos, true).await,
get_weak_power(block, state, world, pos, facing, true).await,
@@ -84,7 +84,7 @@ async fn get_redstone_power_no_dust(
pos: BlockPos,
facing: BlockDirection,
) -> u8 {
if state.is_solid() {
if state.is_solid_block() {
return std::cmp::max(
get_max_strong_power(world, &pos, false).await,
get_weak_power(block, state, world, &pos, facing, false).await,
@@ -189,7 +189,7 @@ pub async fn diode_get_input_strength(world: &World, pos: &BlockPos, facing: Blo
let input_pos = pos.offset(facing.to_offset());
let (input_block, input_state) = world.get_block_and_state(&input_pos).await;
let power: u8 = get_redstone_power(input_block, input_state, world, &input_pos, facing).await;
if power == 0 && input_state.is_solid() {
if power == 0 && input_state.is_solid_block() {
return get_max_weak_power(world, &input_pos, true).await;
}
power

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use pumpkin_data::{
Block,
Block, BlockDirection,
block_properties::{HorizontalFacing, RailShape, StraightRailShape},
};
use pumpkin_util::math::position::BlockPos;
@@ -40,7 +40,7 @@ pub(super) async fn rail_placement_is_valid(world: &World, block: &Block, pos: &
pub(super) async fn can_place_rail_at(world: &dyn BlockAccessor, pos: &BlockPos) -> bool {
let state = world.get_block_state(&pos.down()).await;
state.is_solid()
state.is_side_solid(BlockDirection::Up)
}
pub(super) async fn compute_placed_rail_shape(

View File

@@ -278,7 +278,8 @@ pub async fn get_side(world: &World, pos: &BlockPos, side: BlockDirection) -> Wi
let up_pos = pos.offset(BlockDirection::Up.to_offset());
let up_state = world.get_block_state(&up_pos).await;
if !up_state.is_solid()
if !up_state.is_solid_block()
&& state.is_side_solid(side.opposite())
&& can_connect_diagonal_to(
world
.get_block(&neighbor_pos.offset(BlockDirection::Up.to_offset()))
@@ -286,7 +287,7 @@ pub async fn get_side(world: &World, pos: &BlockPos, side: BlockDirection) -> Wi
)
{
WireConnection::Up
} else if !state.is_solid()
} else if !state.is_solid_block()
&& can_connect_diagonal_to(
world
.get_block(&neighbor_pos.offset(BlockDirection::Down.to_offset()))
@@ -510,7 +511,7 @@ async fn calculate_power(world: &World, pos: &BlockPos) -> u8 {
let mut wire_power: u8 = 0;
let up_pos = pos.offset(BlockDirection::Up.to_offset());
let (_up_block, up_state) = world.get_block_and_state(&up_pos).await;
let up_state = world.get_block_state(&up_pos).await;
for side in BlockDirection::all() {
let neighbor_pos = pos.offset(side.to_offset());
@@ -520,9 +521,7 @@ async fn calculate_power(world: &World, pos: &BlockPos) -> u8 {
get_redstone_power_no_dust(neighbor, neighbor_state, world, neighbor_pos, side).await,
);
if side.is_horizontal() {
if !up_state.is_solid()
/*TODO: && !neighbor.is_transparent() */
{
if !up_state.is_solid_block() && neighbor_state.is_solid_block() {
wire_power = max_wire_power(
wire_power,
world,
@@ -531,7 +530,7 @@ async fn calculate_power(world: &World, pos: &BlockPos) -> u8 {
.await;
}
if !neighbor_state.is_solid() {
if !neighbor_state.is_solid_block() {
wire_power = max_wire_power(
wire_power,
world,

View File

@@ -373,21 +373,19 @@ impl RedstoneWireTurbo {
if wire_power < 15 {
let neighbors = self.nodes[upd.index].neighbors.as_ref().unwrap();
let center_up = &self.nodes[neighbors[1].index].state;
let center_up = self.nodes[neighbors[1].index].state;
for m in 0..4 {
let n = Self::RS_NEIGHBORS[m];
let neighbor_id = neighbors[n];
let neighbor = &self.get_node(neighbor_id).state;
let neighbor = self.get_node(neighbor_id).state;
block_power = self.get_max_current_strength(neighbor_id, block_power);
if !neighbor.is_solid() {
if !neighbor.is_solid_block() {
let neighbor_down = neighbors[Self::RS_NEIGHBORS_DN[m]];
block_power = self.get_max_current_strength(neighbor_down, block_power);
} else if !center_up.is_solid()
/* TODO: && !neighbor.is_transparent()*/
{
} else if !center_up.is_solid_block() && neighbor.is_solid_block() {
let neighbor_up = neighbors[Self::RS_NEIGHBORS_UP[m]];
block_power = self.get_max_current_strength(neighbor_up, block_power);
}