chunk-gen: add MatchingFluids BlockPredicate

this lets some more things generate, like sugar cane
This commit is contained in:
Alexander Medvedev 2025-12-06 14:31:12 +01:00
parent dbdbc04eb4
commit f734230cd6
6 changed files with 75 additions and 13 deletions

View File

@ -7,10 +7,6 @@ pub struct CollisionShape {
}
impl CollisionShape {
pub fn is_empty() -> bool {
unimplemented!()
}
pub fn to_bounding_box(&self) -> BoundingBox {
BoundingBox {
min: self.min,

View File

@ -27,6 +27,7 @@ use log::{debug, error};
use num_traits::abs;
use pumpkin_data::biome::Biome;
use pumpkin_data::fluid::{Fluid, FluidState};
use pumpkin_data::{Block, BlockState};
use pumpkin_util::HeightMap;
use pumpkin_util::math::position::BlockPos;
@ -880,6 +881,37 @@ impl GenerationCache for Cache {
self.chunks[mid].get_proto_chunk_mut()
}
fn get_fluid_and_fluid_state(&self, pos: &Vector3<i32>) -> (Fluid, FluidState) {
let id = GenerationCache::get_block_state(self, pos).0;
let Some(fluid) = Fluid::from_state_id(id) else {
let block = Block::from_state_id(id);
if let Some(properties) = block.properties(id) {
for (name, value) in properties.to_props() {
if name == "waterlogged" {
if value == "true" {
let fluid = Fluid::FLOWING_WATER;
let state = fluid.states[0].clone();
return (fluid, state);
}
break;
}
}
}
let fluid = Fluid::EMPTY;
let state = fluid.states[0].clone();
return (fluid, state);
};
//let state = fluid.get_state(id);
let state = fluid.states[0].clone();
(fluid.clone(), state)
}
fn get_block_state(&self, pos: &Vector3<i32>) -> RawBlockState {
let dx = (pos.x >> 4) - self.x;
let dz = (pos.z >> 4) - self.y;

View File

@ -1,4 +1,5 @@
use itertools::Itertools;
use pumpkin_data::fluid::{Fluid, FluidState};
use pumpkin_data::{Block, BlockDirection, BlockState, tag::Taggable};
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
use serde::Deserialize;
@ -17,7 +18,7 @@ pub enum BlockPredicate {
#[serde(rename = "minecraft:matching_block_tag")]
MatchingBlockTag(MatchingBlockTagPredicate),
#[serde(rename = "minecraft:matching_fluids")]
MatchingFluids(EmptyTODOStruct),
MatchingFluids(MatchingFluidsBlockPredicate),
#[serde(rename = "minecraft:has_sturdy_face")]
HasSturdyFace(HasSturdyFacePredicate),
#[serde(rename = "minecraft:solid")]
@ -51,7 +52,7 @@ impl BlockPredicate {
match self {
BlockPredicate::MatchingBlocks(predicate) => predicate.test(chunk, pos),
BlockPredicate::MatchingBlockTag(predicate) => predicate.test(chunk, pos),
BlockPredicate::MatchingFluids(_predicate) => false,
BlockPredicate::MatchingFluids(predicate) => predicate.test(chunk, pos),
BlockPredicate::HasSturdyFace(predicate) => predicate.test(chunk, pos),
BlockPredicate::Solid(predicate) => predicate.test(chunk, pos),
BlockPredicate::Replaceable(predicate) => predicate.test(chunk, pos),
@ -100,6 +101,28 @@ impl InsideWorldBoundsBlockPredicate {
}
}
#[derive(Deserialize)]
pub struct MatchingFluidsBlockPredicate {
#[serde(flatten)]
offset: OffsetBlocksBlockPredicate,
fluids: MatchingBlocksWrapper,
}
impl MatchingFluidsBlockPredicate {
pub fn test<T: GenerationCache>(&self, chunk: &T, pos: &BlockPos) -> bool {
let (fluid, _) = self.offset.get_fluid_and_fluid_state(chunk, pos);
match &self.fluids {
MatchingBlocksWrapper::Single(single_block) => {
single_block.strip_prefix("minecraft:").unwrap() == fluid.name
}
MatchingBlocksWrapper::Multiple(blocks) => blocks
.iter()
.map(|s| s.strip_prefix("minecraft:").unwrap())
.contains(fluid.name),
}
}
}
#[derive(Deserialize)]
pub struct MatchingBlockTagPredicate {
#[serde(flatten)]
@ -250,6 +273,16 @@ impl OffsetBlocksBlockPredicate {
let pos = self.get(pos);
GenerationCache::get_block_state(chunk, &pos.0).to_block()
}
pub fn get_fluid_and_fluid_state<T: GenerationCache>(
&self,
chunk: &T,
pos: &BlockPos,
) -> (Fluid, FluidState) {
let pos = self.get(pos);
GenerationCache::get_fluid_and_fluid_state(chunk, &pos.0)
}
pub fn get_state<T: GenerationCache>(&self, chunk: &T, pos: &BlockPos) -> &'static BlockState {
let pos = self.get(pos);
GenerationCache::get_block_state(chunk, &pos.0).to_state()

View File

@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::pin::Pin;
use pumpkin_data::fluid::{Fluid, FluidState};
use pumpkin_data::tag;
use pumpkin_data::{
Block, BlockState, block_properties::blocks_movement, chunk::Biome, tag::Taggable,
@ -48,6 +49,7 @@ use crate::{
pub trait GenerationCache: HeightLimitView + BlockAccessor {
fn get_center_chunk_mut(&mut self) -> &mut ProtoChunk;
fn get_block_state(&self, pos: &Vector3<i32>) -> RawBlockState;
fn get_fluid_and_fluid_state(&self, position: &Vector3<i32>) -> (Fluid, FluidState);
fn set_block_state(&mut self, pos: &Vector3<i32>, block_state: &BlockState);
fn top_motion_blocking_block_height_exclusive(&self, pos: &Vector2<i32>) -> i32;
fn top_motion_blocking_block_no_leaves_height_exclusive(&self, pos: &Vector2<i32>) -> i32;

View File

@ -73,7 +73,7 @@ fn waterlogged_check(block: &Block, state: u16) -> Option<bool> {
.to_props()
.into_iter()
.find(|p| p.0 == "waterlogged")
.map(|(_, value)| value == true.to_string())
.map(|(_, value)| value == "true")
})
}
@ -131,7 +131,7 @@ impl ItemBehaviour for EmptyBucketItem {
.to_props()
.into_iter()
.find(|p| p.0 == "waterlogged")
.map(|(_, value)| value == true.to_string())
.map(|(_, value)| value == "true")
})
.unwrap_or(false)
{

View File

@ -2722,7 +2722,7 @@ impl World {
.to_props()
.into_iter()
.find(|p| p.0 == "waterlogged")
.map(|(_, value)| value == true.to_string())
.map(|(_, value)| value == "true")
})
.unwrap_or(false)
{
@ -2867,7 +2867,7 @@ impl World {
.into_iter()
.find(|p| p.0 == "waterlogged")
.map(|(_, value)| {
if value == true.to_string() {
if value == "true" {
&Fluid::FLOWING_WATER
} else {
&Fluid::EMPTY
@ -2898,7 +2898,7 @@ impl World {
.into_iter()
.find(|p| p.0 == "waterlogged")
.map(|(_, value)| {
if value == true.to_string() {
if value == "true" {
&Fluid::FLOWING_WATER
} else {
&Fluid::EMPTY
@ -2918,7 +2918,7 @@ impl World {
if let Some(properties) = block.properties(id) {
for (name, value) in properties.to_props() {
if name == "waterlogged" {
if value == true.to_string() {
if value == "true" {
let fluid = Fluid::FLOWING_WATER;
let state = fluid.states[0].clone();
return (fluid, state);
@ -2930,7 +2930,6 @@ impl World {
}
let fluid = Fluid::EMPTY;
let state = fluid.states[0].clone();
return (fluid, state);