chore: make chunk gen usable in debug mode
This commit is contained in:
parent
4ec9db1e36
commit
be322123cf
File diff suppressed because one or more lines are too long
@ -307,6 +307,18 @@ pub(crate) fn build() -> TokenStream {
|
||||
pub spawn_costs: phf::Map<&'static str, SpawnCosts>,
|
||||
}
|
||||
|
||||
impl PartialEq<u8> for Biome {
|
||||
fn eq(&self, other: &u8) -> bool {
|
||||
self.id == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Biome> for u8 {
|
||||
fn eq(&self, other: &Biome) -> bool {
|
||||
*self == other.id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SpawnGroups {
|
||||
pub monster: &'static [Spawner],
|
||||
|
||||
@ -966,9 +966,9 @@ pub(crate) fn build() -> TokenStream {
|
||||
#mod_ident::#contains_ident(state_id)
|
||||
}
|
||||
|
||||
pub fn blocks_movement(block_state: &BlockState, block: &Block) -> bool {
|
||||
pub fn blocks_movement(block_state: &BlockState, block: u16) -> bool {
|
||||
if block_state.is_solid() {
|
||||
return block != &Block::COBWEB && block != &Block::BAMBOO_SAPLING;
|
||||
return block != Block::COBWEB && block != Block::BAMBOO_SAPLING;
|
||||
}
|
||||
false
|
||||
}
|
||||
@ -982,7 +982,10 @@ pub(crate) fn build() -> TokenStream {
|
||||
#[doc = r" If you need access to the block use `BlockState::from_id_with_block` instead."]
|
||||
#[inline]
|
||||
pub fn from_id(id: u16) -> &'static Self {
|
||||
Block::STATE_FROM_STATE_ID[id as usize]
|
||||
// In debug, this avoids the slow range-checking logic
|
||||
unsafe {
|
||||
Block::STATE_FROM_STATE_ID.get_unchecked(id as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Get a block state from a state id and the corresponding block."]
|
||||
@ -1039,23 +1042,26 @@ pub(crate) fn build() -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Get a raw ID from an State ID."]
|
||||
#[doc = r" Get a raw ID from an State ID."]
|
||||
#[inline]
|
||||
pub const fn get_raw_id_from_state_id(state_id: u16) -> u16 {
|
||||
if state_id as usize >= Self::RAW_ID_FROM_STATE_ID.len() {
|
||||
pub fn get_raw_id_from_state_id(state_id: u16) -> u16 {
|
||||
let index = state_id as usize;
|
||||
if index >= Self::RAW_ID_FROM_STATE_ID.len() {
|
||||
0
|
||||
} else {
|
||||
Self::RAW_ID_FROM_STATE_ID[state_id as usize]
|
||||
unsafe { *Self::RAW_ID_FROM_STATE_ID.get_unchecked(index) }
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Get a block from a state id."]
|
||||
#[inline]
|
||||
pub const fn from_state_id(id: u16) -> &'static Self {
|
||||
if id as usize >= Self::RAW_ID_FROM_STATE_ID.len() {
|
||||
pub fn from_state_id(id: u16) -> &'static Self {
|
||||
let index = id as usize;
|
||||
if index >= Self::RAW_ID_FROM_STATE_ID.len() {
|
||||
return &Self::AIR;
|
||||
}
|
||||
Self::from_id(Self::RAW_ID_FROM_STATE_ID[id as usize])
|
||||
let raw_id = unsafe { *Self::RAW_ID_FROM_STATE_ID.get_unchecked(index) };
|
||||
Self::from_id(raw_id)
|
||||
}
|
||||
|
||||
#[doc = r" Try to parse a block from an item id."]
|
||||
|
||||
@ -37,7 +37,6 @@ pub enum RandomGenerator {
|
||||
Legacy(LegacyRand),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[enum_dispatch(RandomDeriverImpl)]
|
||||
pub enum RandomDeriver {
|
||||
Xoroshiro(XoroshiroSplitter),
|
||||
|
||||
@ -17,13 +17,13 @@ impl RawBlockState {
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn to_block(&self) -> &'static Block {
|
||||
pub fn to_block(&self) -> &'static Block {
|
||||
Block::from_state_id(self.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn to_block_id(&self) -> u16 {
|
||||
pub fn to_block_id(&self) -> u16 {
|
||||
Block::get_raw_id_from_state_id(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ use pumpkin_data::block_properties::{blocks_movement, is_air};
|
||||
use pumpkin_data::chunk::ChunkStatus;
|
||||
use pumpkin_data::fluid::Fluid;
|
||||
use pumpkin_data::tag::Block::MINECRAFT_LEAVES;
|
||||
use pumpkin_data::tag::Taggable;
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_nbt::nbt_long_array;
|
||||
@ -536,7 +535,7 @@ impl ChunkData {
|
||||
let pos = BlockPos::new(x as i32, y, z as i32);
|
||||
let state_id = self.section.get_block_absolute_y(x, y, z).unwrap();
|
||||
let block_state = BlockState::from_id(state_id);
|
||||
let block = Block::from_state_id(state_id);
|
||||
let block = Block::get_raw_id_from_state_id(state_id);
|
||||
|
||||
if !block_state.is_air() && !has_found[ChunkHeightmapType::WorldSurface as usize] {
|
||||
heightmaps.set(ChunkHeightmapType::WorldSurface, pos, self.section.min_y);
|
||||
@ -544,8 +543,7 @@ impl ChunkData {
|
||||
}
|
||||
|
||||
let is_motion_blocking = blocks_movement(block_state, block)
|
||||
|| Fluid::from_registry_key(block.registry_key())
|
||||
.is_some_and(|fluid| !fluid.states.is_empty());
|
||||
|| Fluid::from_id(block).is_some_and(|fluid| !fluid.states.is_empty());
|
||||
|
||||
if !has_found[ChunkHeightmapType::MotionBlocking as usize] && is_motion_blocking {
|
||||
heightmaps.set(ChunkHeightmapType::MotionBlocking, pos, self.section.min_y);
|
||||
@ -554,7 +552,7 @@ impl ChunkData {
|
||||
|
||||
if !has_found[ChunkHeightmapType::MotionBlockingNoLeaves as usize]
|
||||
&& is_motion_blocking
|
||||
&& !block.has_tag(&MINECRAFT_LEAVES)
|
||||
&& !MINECRAFT_LEAVES.1.contains(&block)
|
||||
{
|
||||
heightmaps.set(
|
||||
ChunkHeightmapType::MotionBlockingNoLeaves,
|
||||
|
||||
@ -803,8 +803,8 @@ impl Chunk {
|
||||
|
||||
for z in 0..4 {
|
||||
for x in 0..4 {
|
||||
let biome = proto_chunk.get_biome(x as i32, absolute_biome_y, z as i32);
|
||||
section.biomes.set(x, relative_y, z, biome.id);
|
||||
let biome = proto_chunk.get_biome_id(x as i32, absolute_biome_y, z as i32);
|
||||
section.biomes.set(x, relative_y, z, biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1131,7 +1131,7 @@ impl GenerationCache for Cache {
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
Chunk::Proto(data) => data.get_biome_for_terrain_gen(x, y, z),
|
||||
Chunk::Proto(data) => data.get_terrain_gen_biome(x, y, z),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use itertools::Itertools;
|
||||
use pumpkin_data::fluid::{Fluid, FluidState};
|
||||
use pumpkin_data::{Block, BlockDirection, BlockState, tag::Taggable};
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_ids};
|
||||
use pumpkin_data::{Block, BlockDirection, BlockState};
|
||||
use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::block::RawBlockState;
|
||||
use crate::generation::proto_chunk::GenerationCache;
|
||||
use crate::{block::BlockStateCodec, world::BlockRegistryExt};
|
||||
|
||||
@ -128,8 +130,10 @@ pub struct MatchingBlockTagPredicate {
|
||||
|
||||
impl MatchingBlockTagPredicate {
|
||||
pub fn test<T: GenerationCache>(&self, chunk: &T, pos: &BlockPos) -> bool {
|
||||
let block = self.offset.get_block(chunk, pos);
|
||||
block.is_tagged_with(&self.tag).unwrap()
|
||||
let block = self.offset.get_raw(chunk, pos);
|
||||
get_tag_ids(RegistryKey::Block, &self.tag)
|
||||
.unwrap()
|
||||
.contains(&block.to_block_id())
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,6 +271,11 @@ impl OffsetBlocksBlockPredicate {
|
||||
}
|
||||
*pos
|
||||
}
|
||||
pub fn get_raw<T: GenerationCache>(&self, chunk: &T, pos: &BlockPos) -> RawBlockState {
|
||||
let pos = self.get(pos);
|
||||
GenerationCache::get_block_state(chunk, &pos.0)
|
||||
}
|
||||
|
||||
pub fn get_block<T: GenerationCache>(&self, chunk: &T, pos: &BlockPos) -> &'static Block {
|
||||
let pos = self.get(pos);
|
||||
GenerationCache::get_block_state(chunk, &pos.0).to_block()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use pumpkin_data::{BlockState, chunk::DoublePerlinNoiseParameters};
|
||||
use pumpkin_data::BlockState;
|
||||
use pumpkin_util::{
|
||||
DoublePerlinNoiseParametersCodec,
|
||||
math::{
|
||||
@ -85,10 +85,10 @@ pub struct DualNoiseBlockStateProvider {
|
||||
|
||||
impl DualNoiseBlockStateProvider {
|
||||
pub fn get(&self, pos: BlockPos) -> &'static BlockState {
|
||||
let noise = perlin_codec_to_static(self.slow_noise.clone());
|
||||
let sampler = DoublePerlinNoiseSampler::new(
|
||||
&mut RandomGenerator::Legacy(LegacyRand::from_seed(self.base.base.seed as u64)),
|
||||
&noise,
|
||||
self.slow_noise.first_octave,
|
||||
&self.slow_noise.amplitudes,
|
||||
false,
|
||||
);
|
||||
let slow_noise =
|
||||
@ -103,14 +103,10 @@ impl DualNoiseBlockStateProvider {
|
||||
let mut list = Vec::with_capacity(mapped as usize);
|
||||
for i in 0..mapped {
|
||||
let value = self.get_slow_noise(i as f64 * 54545.0, 0.0, i as f64 * 34234.0, &sampler);
|
||||
list.push(
|
||||
self.base
|
||||
.get_state_by_value(&self.base.states, value)
|
||||
.clone(),
|
||||
);
|
||||
list.push(self.base.get_state_by_value(&self.base.states, value));
|
||||
}
|
||||
let value = self.base.base.get_noise(pos);
|
||||
self.base.get_state_by_value(&list, value).get_state()
|
||||
self.base.get_state_by_value_2(&list, value).get_state()
|
||||
}
|
||||
|
||||
fn get_slow_noise(&self, x: f64, y: f64, z: f64, sampler: &DoublePerlinNoiseSampler) -> f64 {
|
||||
@ -151,17 +147,12 @@ pub struct NoiseBlockStateProviderBase {
|
||||
scale: f32,
|
||||
}
|
||||
|
||||
fn perlin_codec_to_static(noise: DoublePerlinNoiseParametersCodec) -> DoublePerlinNoiseParameters {
|
||||
let amplitudes_static: &'static [f64] = noise.amplitudes.leak();
|
||||
DoublePerlinNoiseParameters::new(noise.first_octave, amplitudes_static, "none")
|
||||
}
|
||||
|
||||
impl NoiseBlockStateProviderBase {
|
||||
pub fn get_noise(&self, pos: BlockPos) -> f64 {
|
||||
let noise = perlin_codec_to_static(self.noise.clone());
|
||||
let sampler = DoublePerlinNoiseSampler::new(
|
||||
&mut RandomGenerator::Legacy(LegacyRand::from_seed(self.seed as u64)),
|
||||
&noise,
|
||||
self.noise.first_octave,
|
||||
&self.noise.amplitudes,
|
||||
false,
|
||||
);
|
||||
sampler.sample(
|
||||
@ -193,6 +184,15 @@ impl NoiseBlockStateProvider {
|
||||
let val = f64::midpoint(1.0, value).clamp(0.0, 0.9999);
|
||||
&states[(val * states.len() as f64) as usize]
|
||||
}
|
||||
|
||||
fn get_state_by_value_2<'a>(
|
||||
&self,
|
||||
states: &'a [&BlockStateCodec],
|
||||
value: f64,
|
||||
) -> &'a BlockStateCodec {
|
||||
let val = f64::midpoint(1.0, value).clamp(0.0, 0.9999);
|
||||
states[(val * states.len() as f64) as usize]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
||||
@ -2,7 +2,6 @@ use pumpkin_data::{
|
||||
Block, BlockState,
|
||||
block_properties::{BambooLeaves, BambooLikeProperties, BlockProperties, Integer0To1},
|
||||
tag,
|
||||
tag::Taggable,
|
||||
};
|
||||
use pumpkin_util::{
|
||||
math::position::BlockPos,
|
||||
@ -42,7 +41,7 @@ impl BambooFeature {
|
||||
let block_below =
|
||||
BlockPos::new(x, chunk.top_block_height_exclusive(x, z) - 1, z);
|
||||
let block = GenerationCache::get_block_state(chunk, &block_below.0);
|
||||
if !block.to_block().has_tag(&tag::Block::MINECRAFT_DIRT) {
|
||||
if !tag::Block::MINECRAFT_DIRT.1.contains(&block.to_block_id()) {
|
||||
continue;
|
||||
}
|
||||
chunk.set_block_state(&block_below.0, Block::PODZOL.default_state);
|
||||
|
||||
@ -2,8 +2,7 @@ use crate::generation::proto_chunk::GenerationCache;
|
||||
use pumpkin_data::{
|
||||
Block, BlockDirection, BlockState,
|
||||
block_properties::{BlockProperties, EnumVariants, Integer1To4, SeaPickleLikeProperties},
|
||||
tag,
|
||||
tag::{RegistryKey, Taggable, get_tag_values},
|
||||
tag::{self, RegistryKey, get_tag_ids},
|
||||
};
|
||||
use pumpkin_util::{
|
||||
math::position::BlockPos,
|
||||
@ -23,11 +22,11 @@ impl CoralFeature {
|
||||
state: &BlockState,
|
||||
pos: BlockPos,
|
||||
) -> bool {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block();
|
||||
let above_block = GenerationCache::get_block_state(chunk, &pos.up().0).to_block();
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block_id();
|
||||
let above_block = GenerationCache::get_block_state(chunk, &pos.up().0).to_block_id();
|
||||
|
||||
if block != &Block::WATER && !block.has_tag(&tag::Block::MINECRAFT_CORALS)
|
||||
|| above_block != &Block::WATER
|
||||
if block != Block::WATER && !&tag::Block::MINECRAFT_CORALS.1.contains(&block)
|
||||
|| above_block != Block::WATER
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -48,7 +47,7 @@ impl CoralFeature {
|
||||
for dir in BlockDirection::horizontal() {
|
||||
let dir_pos = pos.offset(dir.to_offset());
|
||||
if random.next_f32() >= 0.2
|
||||
|| GenerationCache::get_block_state(chunk, &dir_pos.0).to_block() != &Block::WATER
|
||||
|| GenerationCache::get_block_state(chunk, &dir_pos.0).to_block_id() != Block::WATER
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -84,8 +83,8 @@ impl CoralFeature {
|
||||
}
|
||||
|
||||
pub fn get_random_tag_entry_block(tag: &str, random: &mut RandomGenerator) -> &'static Block {
|
||||
let values = get_tag_values(RegistryKey::Block, tag).unwrap();
|
||||
let values = get_tag_ids(RegistryKey::Block, tag).unwrap();
|
||||
let value = values[random.next_bounded_i32(values.len() as i32) as usize];
|
||||
Block::from_name(value).unwrap()
|
||||
Block::from_id(value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,9 +29,9 @@ impl DesertWellFeature {
|
||||
while chunk.is_air(&block_pos.0) && block_pos.0.y > chunk.bottom_y() as i32 + 2 {
|
||||
block_pos = block_pos.down();
|
||||
}
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block();
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block_id();
|
||||
const CAN_GENERATE: Block = Block::SAND;
|
||||
if CAN_GENERATE.id != block.id {
|
||||
if CAN_GENERATE.id != block {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
use crate::generation::proto_chunk::GenerationCache;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::tag;
|
||||
use pumpkin_data::{Block, tag::Taggable};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
|
||||
pub mod cluster;
|
||||
pub mod large;
|
||||
pub mod small;
|
||||
|
||||
pub(super) fn can_replace(block: &Block) -> bool {
|
||||
block == &Block::DRIPSTONE_BLOCK
|
||||
|| block.has_tag(&tag::Block::MINECRAFT_DRIPSTONE_REPLACEABLE_BLOCKS)
|
||||
pub(super) fn can_replace(block: u16) -> bool {
|
||||
block == Block::DRIPSTONE_BLOCK
|
||||
|| tag::Block::MINECRAFT_DRIPSTONE_REPLACEABLE_BLOCKS
|
||||
.1
|
||||
.contains(&block)
|
||||
}
|
||||
|
||||
pub(super) fn gen_dripstone<T: GenerationCache>(chunk: &mut T, pos: BlockPos) -> bool {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block();
|
||||
if block.has_tag(&tag::Block::MINECRAFT_DRIPSTONE_REPLACEABLE_BLOCKS) {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block_id();
|
||||
if tag::Block::MINECRAFT_DRIPSTONE_REPLACEABLE_BLOCKS
|
||||
.1
|
||||
.contains(&block)
|
||||
{
|
||||
chunk.set_block_state(&pos.0, Block::DRIPSTONE_BLOCK.default_state);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -36,9 +36,10 @@ impl SmallDripstoneFeature {
|
||||
random: &mut RandomGenerator,
|
||||
) -> Option<BlockDirection> {
|
||||
let up =
|
||||
super::can_replace(GenerationCache::get_block_state(chunk, &pos.up().0).to_block());
|
||||
let down: bool =
|
||||
super::can_replace(GenerationCache::get_block_state(chunk, &pos.down().0).to_block());
|
||||
super::can_replace(GenerationCache::get_block_state(chunk, &pos.up().0).to_block_id());
|
||||
let down: bool = super::can_replace(
|
||||
GenerationCache::get_block_state(chunk, &pos.down().0).to_block_id(),
|
||||
);
|
||||
if up && down {
|
||||
return if random.next_bool() {
|
||||
Some(BlockDirection::Down)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use pumpkin_data::{Block, tag, tag::Taggable};
|
||||
use pumpkin_data::{Block, tag};
|
||||
use pumpkin_util::{
|
||||
math::position::BlockPos,
|
||||
random::{RandomGenerator, RandomImpl},
|
||||
@ -29,7 +29,10 @@ impl NetherForestVegetationFeature {
|
||||
) -> bool {
|
||||
let state = GenerationCache::get_block_state(chunk, &pos.down().0);
|
||||
|
||||
if !state.to_block().has_tag(&tag::Block::MINECRAFT_NYLIUM) {
|
||||
if !tag::Block::MINECRAFT_NYLIUM
|
||||
.1
|
||||
.contains(&state.to_block_id())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
let mut result = false;
|
||||
|
||||
@ -44,7 +44,7 @@ impl ReplaceBlobsFeature {
|
||||
break;
|
||||
}
|
||||
let current_state = GenerationCache::get_block_state(chunk, &iter_pos.0);
|
||||
if current_state.to_block() != target {
|
||||
if current_state.to_block_id() != target.id {
|
||||
continue;
|
||||
}
|
||||
chunk.set_block_state(&iter_pos.0, state);
|
||||
@ -61,7 +61,7 @@ impl ReplaceBlobsFeature {
|
||||
) -> Option<BlockPos> {
|
||||
while pos.0.y > chunk.bottom_y() as i32 + 1 {
|
||||
let state = GenerationCache::get_block_state(chunk, &pos.0);
|
||||
if state.to_block() == target {
|
||||
if state.to_block_id() == target.id {
|
||||
return Some(pos);
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
use core::f32;
|
||||
|
||||
use pumpkin_data::{BlockDirection, BlockState};
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_util::{
|
||||
math::{lerp, position::BlockPos, vector3::Vector3},
|
||||
random::{RandomGenerator, RandomImpl},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::generation::proto_chunk::GenerationCache;
|
||||
use crate::{block::BlockStateCodec, generation::rule::RuleTest, world::BlockRegistryExt};
|
||||
use crate::{block::RawBlockState, generation::proto_chunk::GenerationCache};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct OreFeature {
|
||||
@ -187,13 +187,7 @@ impl OreFeature {
|
||||
let block_state = GenerationCache::get_block_state(chunk, &pos_vec);
|
||||
|
||||
for target in &self.targets {
|
||||
if self.should_place(
|
||||
chunk,
|
||||
block_state.to_state(),
|
||||
random,
|
||||
target,
|
||||
&mutable_pos,
|
||||
) {
|
||||
if self.should_place(chunk, block_state, random, target, &mutable_pos) {
|
||||
chunk.set_block_state(&pos_vec, target.state.get_state());
|
||||
placed_blocks_count += 1;
|
||||
break; // Equivalent to 'continue block11;'
|
||||
@ -209,12 +203,12 @@ impl OreFeature {
|
||||
fn should_place<T: GenerationCache>(
|
||||
&self,
|
||||
chunk: &T,
|
||||
state: &'static BlockState,
|
||||
state: RawBlockState,
|
||||
random: &mut RandomGenerator,
|
||||
target: &OreTarget,
|
||||
pos: &BlockPos,
|
||||
) -> bool {
|
||||
if !target.target.test(state, random) {
|
||||
if !target.target.test(&state, random) {
|
||||
return false;
|
||||
}
|
||||
if Self::should_not_discard(random, self.discard_chance_on_air_exposure) {
|
||||
|
||||
@ -30,7 +30,7 @@ impl SeaPickleFeature {
|
||||
let x = random.next_bounded_i32(8) - random.next_bounded_i32(8);
|
||||
let z = random.next_bounded_i32(8) - random.next_bounded_i32(8);
|
||||
let y = chunk.ocean_floor_height_exclusive(pos.0.x + x, pos.0.z + z);
|
||||
if GenerationCache::get_block_state(chunk, &pos.0).to_block() != &Block::WATER {
|
||||
if GenerationCache::get_block_state(chunk, &pos.0).to_block_id() != Block::WATER {
|
||||
continue;
|
||||
}
|
||||
let mut props = SeaPickleLikeProperties::default(&Block::SEA_PICKLE);
|
||||
|
||||
@ -28,11 +28,12 @@ impl SeagrassFeature {
|
||||
let z = random.next_bounded_i32(8) - random.next_bounded_i32(8);
|
||||
let y = chunk.ocean_floor_height_exclusive(pos.0.x + x, pos.0.z + z);
|
||||
let top_pos = BlockPos::new(pos.0.x + x, y, pos.0.z + z);
|
||||
if GenerationCache::get_block_state(chunk, &top_pos.0).to_block() == &Block::WATER {
|
||||
if GenerationCache::get_block_state(chunk, &top_pos.0).to_block_id() == Block::WATER {
|
||||
let tall = random.next_f64() < self.probability as f64;
|
||||
if tall {
|
||||
let tall_pos = top_pos.up();
|
||||
if GenerationCache::get_block_state(chunk, &tall_pos.0).to_block() == &Block::WATER
|
||||
if GenerationCache::get_block_state(chunk, &tall_pos.0).to_block_id()
|
||||
== Block::WATER
|
||||
{
|
||||
let mut props = TallSeagrassLikeProperties::default(&Block::TALL_SEAGRASS);
|
||||
props.half = DoubleBlockHalf::Upper;
|
||||
|
||||
@ -25,7 +25,7 @@ impl BlockWrapper {
|
||||
fn contains(&self, name: &str) -> bool {
|
||||
match self {
|
||||
Self::Single(s) => s == name,
|
||||
Self::Multi(h) => h.contains(&name.to_string()),
|
||||
Self::Multi(h) => h.iter().any(|s| s == name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
use super::TreeDecorator;
|
||||
use crate::generation::block_state_provider::BlockStateProvider;
|
||||
use crate::generation::proto_chunk::GenerationCache;
|
||||
use pumpkin_data::{
|
||||
Block,
|
||||
tag::{Block::MINECRAFT_LEAVES, Taggable},
|
||||
};
|
||||
use pumpkin_data::{Block, tag::Block::MINECRAFT_LEAVES};
|
||||
use pumpkin_util::{
|
||||
math::{block_box::BlockBox, position::BlockPos},
|
||||
random::{RandomGenerator, RandomImpl},
|
||||
@ -72,9 +69,9 @@ impl PlaceOnGroundTreeDecorator {
|
||||
let up_pos = pos.up();
|
||||
let up_state = GenerationCache::get_block_state(chunk, &up_pos.0);
|
||||
// TODO
|
||||
if (up_state.to_state().is_air() || up_state.to_block() == &Block::VINE)
|
||||
if (up_state.to_state().is_air() || up_state.to_block_id() == Block::VINE)
|
||||
&& state.to_state().is_full_cube()
|
||||
&& !state.to_block().has_tag(&MINECRAFT_LEAVES)
|
||||
&& !MINECRAFT_LEAVES.1.contains(&state.to_block_id())
|
||||
// TODO: using heightmap seems not to work
|
||||
{
|
||||
chunk.set_block_state(&up_pos.0, self.block_state_provider.get(random, up_pos));
|
||||
|
||||
@ -132,7 +132,7 @@ impl FoliagePlacer {
|
||||
block_state: &BlockState,
|
||||
) {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0);
|
||||
if !TreeFeature::can_replace(block.to_state(), block.to_block()) {
|
||||
if !TreeFeature::can_replace(block.to_state(), block.to_block_id()) {
|
||||
return;
|
||||
}
|
||||
chunk.set_block_state(&pos.0, block_state);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use decorator::TreeDecorator;
|
||||
use foliage::FoliagePlacer;
|
||||
use pumpkin_data::tag;
|
||||
use pumpkin_data::{Block, BlockState, tag::Taggable};
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_util::{math::position::BlockPos, random::RandomGenerator};
|
||||
use serde::Deserialize;
|
||||
use trunk::TrunkPlacer;
|
||||
@ -51,16 +51,19 @@ impl TreeFeature {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn can_replace_or_log(state: &BlockState, block: &Block) -> bool {
|
||||
Self::can_replace(state, block) || block.has_tag(&tag::Block::MINECRAFT_LOGS)
|
||||
pub fn can_replace_or_log(state: &BlockState, block: u16) -> bool {
|
||||
Self::can_replace(state, block) || tag::Block::MINECRAFT_LOGS.1.contains(&block)
|
||||
}
|
||||
|
||||
pub fn is_air_or_leaves(state: &BlockState, block: &Block) -> bool {
|
||||
state.is_air() || block.has_tag(&tag::Block::MINECRAFT_LEAVES)
|
||||
pub fn is_air_or_leaves(state: &BlockState, block: u16) -> bool {
|
||||
state.is_air() || tag::Block::MINECRAFT_LEAVES.1.contains(&block)
|
||||
}
|
||||
|
||||
pub fn can_replace(state: &BlockState, block: &Block) -> bool {
|
||||
state.is_air() || block.has_tag(&tag::Block::MINECRAFT_REPLACEABLE_BY_TREES)
|
||||
pub fn can_replace(state: &BlockState, block: u16) -> bool {
|
||||
state.is_air()
|
||||
|| tag::Block::MINECRAFT_REPLACEABLE_BY_TREES
|
||||
.1
|
||||
.contains(&block)
|
||||
}
|
||||
|
||||
fn generate_main<T: GenerationCache>(
|
||||
@ -119,9 +122,9 @@ impl TreeFeature {
|
||||
for z in -j..=j {
|
||||
let pos = BlockPos(init_pos.0.add_raw(x, y as i32, z));
|
||||
let rstate = GenerationCache::get_block_state(chunk, &pos.0);
|
||||
let block = rstate.to_block();
|
||||
let block = rstate.to_block_id();
|
||||
if Self::can_replace_or_log(rstate.to_state(), block)
|
||||
&& (self.ignore_vines || block != &Block::VINE)
|
||||
&& (self.ignore_vines || block != Block::VINE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ impl DarkOakTrunkPlacer {
|
||||
let pos = BlockPos::new(x, current_y, z);
|
||||
// TODO: support multiple chunks
|
||||
let state = GenerationCache::get_block_state(chunk, &pos.0);
|
||||
if !TreeFeature::is_air_or_leaves(state.to_state(), state.to_block()) {
|
||||
if !TreeFeature::is_air_or_leaves(state.to_state(), state.to_block_id()) {
|
||||
continue;
|
||||
}
|
||||
if placer.try_place(chunk, &pos, trunk_block) {
|
||||
|
||||
@ -145,7 +145,7 @@ impl FancyTrunkPlacer {
|
||||
if make {
|
||||
let axis = Self::get_log_axis(start_pos, block_pos_2.0);
|
||||
|
||||
if TreeFeature::can_replace(block.to_state(), block.to_block()) {
|
||||
if TreeFeature::can_replace(block.to_state(), block.to_block_id()) {
|
||||
let block = Block::from_state_id(trunk_provider.id);
|
||||
let original_props = &block.properties(trunk_provider.id).unwrap().to_props();
|
||||
let axis = axis.to_value();
|
||||
@ -167,7 +167,7 @@ impl FancyTrunkPlacer {
|
||||
}
|
||||
}
|
||||
|
||||
if TreeFeature::can_replace_or_log(block.to_state(), block.to_block()) {
|
||||
if TreeFeature::can_replace_or_log(block.to_state(), block.to_block_id()) {
|
||||
continue;
|
||||
}
|
||||
return (false, logs);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use fancy::FancyTrunkPlacer;
|
||||
use pumpkin_data::tag;
|
||||
use pumpkin_data::{Block, BlockState, tag::Taggable};
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_util::{
|
||||
math::position::BlockPos,
|
||||
random::{RandomGenerator, RandomImpl},
|
||||
@ -49,11 +49,11 @@ impl TrunkPlacer {
|
||||
force_dirt: bool,
|
||||
dirt_state: &BlockState,
|
||||
) {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block();
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0).to_block_id();
|
||||
if force_dirt
|
||||
|| !(block.has_tag(&tag::Block::MINECRAFT_DIRT)
|
||||
&& block != &Block::GRASS_BLOCK
|
||||
&& block != &Block::MYCELIUM)
|
||||
|| !(tag::Block::MINECRAFT_DIRT.1.contains(&block)
|
||||
&& block != Block::GRASS_BLOCK
|
||||
&& block != Block::MYCELIUM)
|
||||
{
|
||||
chunk.set_block_state(&pos.0, dirt_state);
|
||||
}
|
||||
@ -66,7 +66,7 @@ impl TrunkPlacer {
|
||||
trunk_block: &BlockState,
|
||||
) -> bool {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0);
|
||||
if TreeFeature::can_replace(block.to_state(), block.to_block()) {
|
||||
if TreeFeature::can_replace(block.to_state(), block.to_block_id()) {
|
||||
chunk.set_block_state(&pos.0, trunk_block);
|
||||
return true;
|
||||
}
|
||||
@ -80,7 +80,7 @@ impl TrunkPlacer {
|
||||
trunk_block: &BlockState,
|
||||
) -> bool {
|
||||
let block = GenerationCache::get_block_state(chunk, &pos.0);
|
||||
if TreeFeature::can_replace_or_log(block.to_state(), block.to_block()) {
|
||||
if TreeFeature::can_replace_or_log(block.to_state(), block.to_block_id()) {
|
||||
return self.place(chunk, pos, trunk_block);
|
||||
}
|
||||
false
|
||||
|
||||
@ -343,7 +343,7 @@ impl CountOnEveryLayerPlacementModifier {
|
||||
|
||||
if !Self::blocks_spawn(&next_block_state)
|
||||
&& Self::blocks_spawn(¤t_block_state)
|
||||
&& next_block_state.to_block() != &Block::BEDROCK
|
||||
&& next_block_state.to_block_id() != Block::BEDROCK
|
||||
{
|
||||
if found_count == target_y {
|
||||
return mutable_pos.0.y + 1;
|
||||
@ -477,7 +477,6 @@ impl ConditionalPlacementModifier for BiomePlacementModifier {
|
||||
_random: &mut RandomGenerator,
|
||||
pos: BlockPos,
|
||||
) -> bool {
|
||||
// we check if the current feature can be applied to the biome at the pos
|
||||
let name = format!("minecraft:{this_feature}");
|
||||
let biome = chunk.get_biome_for_terrain_gen(pos.0.x, pos.0.y, pos.0.z);
|
||||
|
||||
|
||||
@ -46,13 +46,14 @@ impl BlockStateSampler {
|
||||
pub fn sample(
|
||||
&mut self,
|
||||
router: &mut ChunkNoiseRouter,
|
||||
random_config: &GlobalRandomConfig,
|
||||
pos: &impl NoisePos,
|
||||
sample_options: &ChunkNoiseFunctionSampleOptions,
|
||||
height_estimator: &mut SurfaceHeightEstimateSampler,
|
||||
) -> Option<&'static BlockState> {
|
||||
match self {
|
||||
Self::Aquifer(aquifer) => aquifer.apply(router, pos, sample_options, height_estimator),
|
||||
Self::Ore(ore) => ore.sample(router, pos, sample_options),
|
||||
Self::Ore(ore) => ore.sample(router, random_config, pos, sample_options),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,12 +71,15 @@ impl ChainedBlockStateSampler {
|
||||
fn sample(
|
||||
&mut self,
|
||||
router: &mut ChunkNoiseRouter,
|
||||
random_config: &GlobalRandomConfig,
|
||||
pos: &impl NoisePos,
|
||||
sample_options: &ChunkNoiseFunctionSampleOptions,
|
||||
height_estimator: &mut SurfaceHeightEstimateSampler,
|
||||
) -> Option<&'static BlockState> {
|
||||
for sampler in &mut self.samplers {
|
||||
if let Some(state) = sampler.sample(router, pos, sample_options, height_estimator) {
|
||||
if let Some(state) =
|
||||
sampler.sample(router, random_config, pos, sample_options, height_estimator)
|
||||
{
|
||||
return Some(state);
|
||||
}
|
||||
}
|
||||
@ -225,10 +229,9 @@ impl<'a> ChunkNoiseGenerator<'a> {
|
||||
};
|
||||
|
||||
let samplers: Box<[BlockStateSampler]> = if ore_veins {
|
||||
let ore_sampler = OreVeinSampler::new(random_config.ore_random_deriver.clone());
|
||||
Box::new([
|
||||
BlockStateSampler::Aquifer(aquifer_sampler),
|
||||
BlockStateSampler::Ore(ore_sampler),
|
||||
BlockStateSampler::Ore(OreVeinSampler),
|
||||
])
|
||||
} else {
|
||||
Box::new([BlockStateSampler::Aquifer(aquifer_sampler)])
|
||||
@ -369,6 +372,7 @@ impl<'a> ChunkNoiseGenerator<'a> {
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub fn sample_block_state(
|
||||
&mut self,
|
||||
random_config: &GlobalRandomConfig,
|
||||
start_x: i32,
|
||||
start_y: i32,
|
||||
start_z: i32,
|
||||
@ -394,8 +398,13 @@ impl<'a> ChunkNoiseGenerator<'a> {
|
||||
0,
|
||||
);
|
||||
|
||||
self.state_sampler
|
||||
.sample(&mut self.router, &pos, &options, height_estimator)
|
||||
self.state_sampler.sample(
|
||||
&mut self.router,
|
||||
random_config,
|
||||
&pos,
|
||||
&options,
|
||||
height_estimator,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@ -1,27 +1,24 @@
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_util::{
|
||||
math::clamped_map,
|
||||
random::{RandomDeriver, RandomDeriverImpl, RandomImpl},
|
||||
random::{RandomDeriverImpl, RandomImpl},
|
||||
};
|
||||
|
||||
use crate::generation::noise::router::{
|
||||
chunk_density_function::ChunkNoiseFunctionSampleOptions, chunk_noise_router::ChunkNoiseRouter,
|
||||
density_function::NoisePos,
|
||||
use crate::{
|
||||
GlobalRandomConfig,
|
||||
generation::noise::router::{
|
||||
chunk_density_function::ChunkNoiseFunctionSampleOptions,
|
||||
chunk_noise_router::ChunkNoiseRouter, density_function::NoisePos,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct OreVeinSampler {
|
||||
random_deriver: RandomDeriver,
|
||||
}
|
||||
pub struct OreVeinSampler;
|
||||
|
||||
impl OreVeinSampler {
|
||||
#[must_use]
|
||||
pub const fn new(random_deriver: RandomDeriver) -> Self {
|
||||
Self { random_deriver }
|
||||
}
|
||||
|
||||
pub fn sample(
|
||||
&self,
|
||||
router: &mut ChunkNoiseRouter,
|
||||
random_config: &GlobalRandomConfig,
|
||||
pos: &impl NoisePos,
|
||||
sample_options: &ChunkNoiseFunctionSampleOptions,
|
||||
) -> Option<&'static BlockState> {
|
||||
@ -40,7 +37,10 @@ impl OreVeinSampler {
|
||||
let mapped_diff = clamped_map(closest_to_bound as f64, 0f64, 20f64, -0.2f64, 0f64);
|
||||
let abs_sample = vein_toggle.abs();
|
||||
if abs_sample + mapped_diff >= 0.4f32 as f64 {
|
||||
let mut random = self.random_deriver.split_pos(pos.x(), block_y, pos.z());
|
||||
let mut random =
|
||||
random_config
|
||||
.ore_random_deriver
|
||||
.split_pos(pos.x(), block_y, pos.z());
|
||||
|
||||
let vein_ridged_sample = router.vein_ridged(pos, sample_options);
|
||||
if random.next_f32() <= 0.7f32 && vein_ridged_sample < 0f64 {
|
||||
|
||||
@ -18,14 +18,20 @@ impl DoublePerlinNoiseSampler {
|
||||
self.max_value
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
pub fn from_params(
|
||||
rand: &mut RandomGenerator,
|
||||
parameters: &DoublePerlinNoiseParameters,
|
||||
legacy: bool,
|
||||
) -> Self {
|
||||
let first_octave = parameters.first_octave;
|
||||
let amplitudes = parameters.amplitudes;
|
||||
Self::new(rand, parameters.first_octave, parameters.amplitudes, legacy)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
rand: &mut RandomGenerator,
|
||||
first_octave: i32,
|
||||
amplitudes: &[f64],
|
||||
legacy: bool,
|
||||
) -> Self {
|
||||
let first_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes, legacy);
|
||||
let second_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes, legacy);
|
||||
|
||||
@ -75,7 +81,7 @@ mod double_perlin_noise_sampler_test {
|
||||
|
||||
let mut rand_gen = RandomGenerator::Legacy(rand);
|
||||
let params = DoublePerlinNoiseParameters::new(0, &[4f64], "");
|
||||
let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, ¶ms, true);
|
||||
let sampler = DoublePerlinNoiseSampler::from_params(&mut rand_gen, ¶ms, true);
|
||||
|
||||
let values = [
|
||||
(
|
||||
@ -174,7 +180,7 @@ mod double_perlin_noise_sampler_test {
|
||||
|
||||
let params = DoublePerlinNoiseParameters::new(1, &[2f64, 4f64], "");
|
||||
|
||||
let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, ¶ms, false);
|
||||
let sampler = DoublePerlinNoiseSampler::from_params(&mut rand_gen, ¶ms, false);
|
||||
|
||||
let values = [
|
||||
(
|
||||
|
||||
@ -79,7 +79,7 @@ impl<'a> DoublePerlinNoiseBuilder<'a> {
|
||||
.random_config
|
||||
.base_random_deriver
|
||||
.split_string(parameters.id());
|
||||
DoublePerlinNoiseSampler::new(&mut random, parameters, false)
|
||||
DoublePerlinNoiseSampler::from_params(&mut random, parameters, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,9 +5,7 @@ use pumpkin_data::block_properties::is_air;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::fluid::{Fluid, FluidState};
|
||||
use pumpkin_data::tag;
|
||||
use pumpkin_data::{
|
||||
Block, BlockState, block_properties::blocks_movement, chunk::Biome, tag::Taggable,
|
||||
};
|
||||
use pumpkin_data::{Block, BlockState, block_properties::blocks_movement, chunk::Biome};
|
||||
use pumpkin_util::random::{RandomImpl, get_carver_seed};
|
||||
use pumpkin_util::{
|
||||
HeightMap,
|
||||
@ -474,7 +472,7 @@ impl ProtoChunk {
|
||||
}
|
||||
if !block_state.is_air() {
|
||||
self.maybe_update_surface_height_map(local_x, y, local_z);
|
||||
let block = Block::from_state_id(block_state.id);
|
||||
let block = Block::get_raw_id_from_state_id(block_state.id);
|
||||
|
||||
let blocks_movement = blocks_movement(block_state, block);
|
||||
if blocks_movement {
|
||||
@ -482,7 +480,7 @@ impl ProtoChunk {
|
||||
}
|
||||
if blocks_movement || block_state.is_liquid() {
|
||||
self.maybe_update_motion_blocking_height_map(local_x, y, local_z);
|
||||
if !block.has_tag(&tag::Block::MINECRAFT_LEAVES) {
|
||||
if !tag::Block::MINECRAFT_LEAVES.1.contains(&block) {
|
||||
{
|
||||
self.maybe_update_motion_blocking_no_leaves_height_map(local_x, y, local_z);
|
||||
}
|
||||
@ -572,7 +570,11 @@ impl ProtoChunk {
|
||||
&noise_router.surface_estimator,
|
||||
&surface_config,
|
||||
);
|
||||
self.populate_noise(&mut noise_sampler, &mut surface_height_estimate_sampler);
|
||||
self.populate_noise(
|
||||
&mut noise_sampler,
|
||||
random_config,
|
||||
&mut surface_height_estimate_sampler,
|
||||
);
|
||||
|
||||
self.stage = StagedChunkEnum::Noise;
|
||||
}
|
||||
@ -673,6 +675,7 @@ impl ProtoChunk {
|
||||
pub fn populate_noise(
|
||||
&mut self,
|
||||
noise_sampler: &mut ChunkNoiseGenerator,
|
||||
random_config: &GlobalRandomConfig,
|
||||
surface_height_estimate_sampler: &mut SurfaceHeightEstimateSampler,
|
||||
) {
|
||||
let h_count = noise_sampler.horizontal_cell_block_count() as i32;
|
||||
@ -724,6 +727,7 @@ impl ProtoChunk {
|
||||
|
||||
let block_state = noise_sampler
|
||||
.sample_block_state(
|
||||
random_config,
|
||||
sample_start_x,
|
||||
sample_start_y,
|
||||
sample_start_z,
|
||||
@ -744,7 +748,7 @@ impl ProtoChunk {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_biome_for_terrain_gen(&self, x: i32, y: i32, z: i32) -> &'static Biome {
|
||||
pub fn get_terrain_gen_biome_id(&self, x: i32, y: i32, z: i32) -> u8 {
|
||||
// TODO: See if we can cache this value
|
||||
let seed_biome_pos = biome::get_biome_blend(
|
||||
self.bottom_y(),
|
||||
@ -755,7 +759,11 @@ impl ProtoChunk {
|
||||
z,
|
||||
);
|
||||
|
||||
self.get_biome(seed_biome_pos.x, seed_biome_pos.y, seed_biome_pos.z)
|
||||
self.get_biome_id(seed_biome_pos.x, seed_biome_pos.y, seed_biome_pos.z)
|
||||
}
|
||||
#[must_use]
|
||||
pub fn get_terrain_gen_biome(&self, x: i32, y: i32, z: i32) -> &'static Biome {
|
||||
Biome::from_id(self.get_terrain_gen_biome_id(x, y, z)).unwrap()
|
||||
}
|
||||
|
||||
/// Constructs the terrain surface, although "surface" is a misnomer as it also places underground blocks like bedrock and deepslate.
|
||||
@ -798,8 +806,8 @@ impl ProtoChunk {
|
||||
top_block
|
||||
};
|
||||
|
||||
let this_biome = self.get_biome_for_terrain_gen(x, biome_y, z);
|
||||
if this_biome == &Biome::ERODED_BADLANDS {
|
||||
let this_biome = self.get_terrain_gen_biome_id(x, biome_y, z);
|
||||
if this_biome == Biome::ERODED_BADLANDS {
|
||||
terrain_cache
|
||||
.terrain_builder
|
||||
.place_badlands_pillar(self, x, z, top_block);
|
||||
@ -857,7 +865,7 @@ impl ProtoChunk {
|
||||
// panic!("Blending with biome {:?} at: {:?}", biome, biome_pos);
|
||||
|
||||
if state.id == self.default_block.id {
|
||||
context.biome = self.get_biome_for_terrain_gen(
|
||||
context.biome = self.get_terrain_gen_biome(
|
||||
context.block_pos_x,
|
||||
context.block_pos_y,
|
||||
context.block_pos_z,
|
||||
@ -873,13 +881,13 @@ impl ProtoChunk {
|
||||
}
|
||||
}
|
||||
}
|
||||
if this_biome == &Biome::FROZEN_OCEAN || this_biome == &Biome::DEEP_FROZEN_OCEAN {
|
||||
if this_biome == Biome::FROZEN_OCEAN || this_biome == Biome::DEEP_FROZEN_OCEAN {
|
||||
let surface_estimate =
|
||||
estimate_surface_height(&mut context, surface_height_estimate_sampler);
|
||||
|
||||
terrain_cache.terrain_builder.place_iceberg(
|
||||
self,
|
||||
this_biome,
|
||||
Biome::from_id(this_biome).unwrap(),
|
||||
x,
|
||||
z,
|
||||
surface_estimate,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::block::RawBlockState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct BlockMatchRuleTest {
|
||||
// This should be a Block codec, so this is wrong
|
||||
@ -8,8 +9,7 @@ pub struct BlockMatchRuleTest {
|
||||
}
|
||||
|
||||
impl BlockMatchRuleTest {
|
||||
pub fn test(&self, state: &BlockState) -> bool {
|
||||
Block::from_state_id(state.id).name
|
||||
== self.block.strip_prefix("minecraft:").unwrap_or(&self.block)
|
||||
pub fn test(&self, state: &RawBlockState) -> bool {
|
||||
state.to_block().name == self.block.strip_prefix("minecraft:").unwrap_or(&self.block)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use pumpkin_data::BlockState;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::block::BlockStateCodec;
|
||||
use crate::block::{BlockStateCodec, RawBlockState};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct BlockStateMatchRuleTest {
|
||||
@ -9,7 +8,7 @@ pub struct BlockStateMatchRuleTest {
|
||||
}
|
||||
|
||||
impl BlockStateMatchRuleTest {
|
||||
pub fn test(&self, state: &BlockState) -> bool {
|
||||
state.id == self.block_state.get_state_id()
|
||||
pub fn test(&self, state: &RawBlockState) -> bool {
|
||||
state.0 == self.block_state.get_state_id()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
use block_match::BlockMatchRuleTest;
|
||||
use block_state_match::BlockStateMatchRuleTest;
|
||||
use pumpkin_data::BlockState;
|
||||
use pumpkin_util::random::RandomGenerator;
|
||||
use random_block_match::RandomBlockMatchRuleTest;
|
||||
use random_block_state_match::RandomBlockStateMatchRuleTest;
|
||||
use serde::Deserialize;
|
||||
use tag_match::TagMatchRuleTest;
|
||||
|
||||
use crate::block::RawBlockState;
|
||||
|
||||
mod block_match;
|
||||
mod block_state_match;
|
||||
mod random_block_match;
|
||||
@ -31,7 +32,7 @@ pub enum RuleTest {
|
||||
}
|
||||
|
||||
impl RuleTest {
|
||||
pub fn test(&self, state: &BlockState, random: &mut RandomGenerator) -> bool {
|
||||
pub fn test(&self, state: &RawBlockState, random: &mut RandomGenerator) -> bool {
|
||||
match self {
|
||||
Self::AlwaysTrue => true,
|
||||
Self::BlockMatch(rule) => rule.test(state),
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use pumpkin_data::{Block, BlockState};
|
||||
use pumpkin_util::random::{RandomGenerator, RandomImpl};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::block::RawBlockState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RandomBlockMatchRuleTest {
|
||||
// This should be a Block codec, so this is wrong
|
||||
@ -10,9 +11,8 @@ pub struct RandomBlockMatchRuleTest {
|
||||
}
|
||||
|
||||
impl RandomBlockMatchRuleTest {
|
||||
pub fn test(&self, state: &BlockState, random: &mut RandomGenerator) -> bool {
|
||||
Block::from_state_id(state.id).name
|
||||
== self.block.strip_prefix("minecraft:").unwrap_or(&self.block)
|
||||
pub fn test(&self, state: &RawBlockState, random: &mut RandomGenerator) -> bool {
|
||||
state.to_block().name == self.block.strip_prefix("minecraft:").unwrap_or(&self.block)
|
||||
&& random.next_f32() < self.probability
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use pumpkin_data::BlockState;
|
||||
use pumpkin_util::random::{RandomGenerator, RandomImpl};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::block::BlockStateCodec;
|
||||
use crate::block::{BlockStateCodec, RawBlockState};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RandomBlockStateMatchRuleTest {
|
||||
@ -11,7 +10,7 @@ pub struct RandomBlockStateMatchRuleTest {
|
||||
}
|
||||
|
||||
impl RandomBlockStateMatchRuleTest {
|
||||
pub fn test(&self, state: &BlockState, random: &mut RandomGenerator) -> bool {
|
||||
state.id == self.block_state.get_state_id() && random.next_f32() < self.probability
|
||||
pub fn test(&self, state: &RawBlockState, random: &mut RandomGenerator) -> bool {
|
||||
state.0 == self.block_state.get_state_id() && random.next_f32() < self.probability
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
use pumpkin_data::{Block, BlockState, tag::Taggable};
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_ids};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::block::RawBlockState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct TagMatchRuleTest {
|
||||
tag: String,
|
||||
}
|
||||
|
||||
impl TagMatchRuleTest {
|
||||
pub fn test(&self, state: &BlockState) -> bool {
|
||||
Block::from_state_id(state.id)
|
||||
.is_tagged_with(&self.tag)
|
||||
.unwrap()
|
||||
pub fn test(&self, state: &RawBlockState) -> bool {
|
||||
let values = get_tag_ids(RegistryKey::Block, &self.tag).unwrap();
|
||||
values.contains(&state.to_block_id())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{collections::HashMap, sync::LazyLock};
|
||||
|
||||
use pumpkin_data::{chunk::Biome, tag::Taggable};
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_ids};
|
||||
use pumpkin_util::include_json_static;
|
||||
use serde::Deserialize;
|
||||
|
||||
@ -185,14 +185,21 @@ impl StructureKeys {
|
||||
|
||||
if let Some(pos) = structure_pos {
|
||||
// Get the biome at the structure's starting position
|
||||
let current_biome = chunk.get_biome(
|
||||
let current_biome = chunk.get_biome_id(
|
||||
biome_coords::from_block(pos.start_pos.0.x),
|
||||
biome_coords::from_block(pos.start_pos.0.y),
|
||||
biome_coords::from_block(pos.start_pos.0.z),
|
||||
);
|
||||
let biomes = Biome::get_tag_values(&structure.biomes).unwrap();
|
||||
) as u16;
|
||||
let biomes = get_tag_ids(
|
||||
RegistryKey::WorldgenBiome,
|
||||
structure
|
||||
.biomes
|
||||
.strip_prefix("#")
|
||||
.unwrap_or(&structure.biomes),
|
||||
)
|
||||
.unwrap();
|
||||
// Check if the biome is allowed for this structure
|
||||
if biomes.contains(¤t_biome.registry_id) {
|
||||
if biomes.contains(¤t_biome) {
|
||||
return Some(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ impl ConcentricRingsStructurePlacement {
|
||||
// ^ (salt as i64);
|
||||
|
||||
// (seed.abs() % 400) == 0
|
||||
rand::random_bool(1.0 / 100.0)
|
||||
rand::random_bool(1.0 / 1000.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -73,19 +73,19 @@ impl StructurePieceBase for BuriedTreasurePiece {
|
||||
let state = chunk.get_block_state(&pos.0);
|
||||
let down_pos = pos.down();
|
||||
let down_raw_state = chunk.get_block_state(&down_pos.0);
|
||||
let down_block = down_raw_state.to_block();
|
||||
let down_block = down_raw_state.to_block_id();
|
||||
|
||||
if down_block == &Block::SANDSTONE
|
||||
|| down_block == &Block::STONE
|
||||
|| down_block == &Block::ANDESITE
|
||||
|| down_block == &Block::GRANITE
|
||||
|| down_block == &Block::DIORITE
|
||||
if down_block == Block::SANDSTONE
|
||||
|| down_block == Block::STONE
|
||||
|| down_block == Block::ANDESITE
|
||||
|| down_block == Block::GRANITE
|
||||
|| down_block == Block::DIORITE
|
||||
{
|
||||
for dir in BlockDirection::all() {
|
||||
let offset_pos = pos.offset(dir.to_offset());
|
||||
let dir_state = chunk.get_block_state(&offset_pos.0);
|
||||
|
||||
if !dir_state.to_state().is_air() && !Self::is_liquid(dir_state.to_block()) {
|
||||
if !dir_state.to_state().is_air() && !Self::is_liquid(dir_state.to_block_id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ impl StructurePieceBase for BuriedTreasurePiece {
|
||||
let down_offset_state = chunk.get_block_state(&down_offset_pos.0);
|
||||
|
||||
if (down_offset_state.to_state().is_air()
|
||||
|| Self::is_liquid(down_offset_state.to_block()))
|
||||
|| Self::is_liquid(down_offset_state.to_block_id()))
|
||||
&& dir != BlockDirection::Up
|
||||
{
|
||||
chunk.set_block_state(
|
||||
@ -105,11 +105,12 @@ impl StructurePieceBase for BuriedTreasurePiece {
|
||||
continue;
|
||||
}
|
||||
|
||||
let state1 = if state.to_state().is_air() || Self::is_liquid(state.to_block()) {
|
||||
Block::SAND.default_state
|
||||
} else {
|
||||
state.to_state()
|
||||
};
|
||||
let state1 =
|
||||
if state.to_state().is_air() || Self::is_liquid(state.to_block_id()) {
|
||||
Block::SAND.default_state
|
||||
} else {
|
||||
state.to_state()
|
||||
};
|
||||
chunk.set_block_state(offset_pos.0.x, offset_pos.0.y, offset_pos.0.z, state1);
|
||||
}
|
||||
|
||||
@ -132,7 +133,7 @@ impl StructurePieceBase for BuriedTreasurePiece {
|
||||
}
|
||||
|
||||
impl BuriedTreasurePiece {
|
||||
fn is_liquid(block: &Block) -> bool {
|
||||
block == &Block::WATER || block == &Block::LAVA
|
||||
fn is_liquid(block: u16) -> bool {
|
||||
block == Block::WATER || block == Block::LAVA
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +239,7 @@ impl SurfaceTerrainBuilder {
|
||||
let pos = Vector3::new(x, y, z);
|
||||
let block_state = chunk.get_block_state(&pos);
|
||||
if (block_state.to_state().is_air() && y < top_block && rand.next_f64() > 0.01)
|
||||
|| (block_state.to_block() == &WATER_BLOCK
|
||||
|| (block_state.to_block_id() == WATER_BLOCK
|
||||
&& y > bottom_block
|
||||
&& y < sea_level
|
||||
&& bottom_block != 0
|
||||
|
||||
@ -24,6 +24,8 @@ use pumpkin_util::math::{position::BlockPos, vector2::Vector2};
|
||||
use pumpkin_util::world_seed::Seed;
|
||||
use rand::{RngExt, SeedableRng, rngs::SmallRng};
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
// use std::time::Duration;
|
||||
use std::{
|
||||
@ -283,13 +285,24 @@ impl Level {
|
||||
};
|
||||
|
||||
log::info!("Joining {} synchronous threads...", handles.len());
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let join_task = tokio::task::spawn_blocking(move || {
|
||||
for handle in handles {
|
||||
// Attempt to join. If a thread is stuck, this block stays alive.
|
||||
let _ = handle.join();
|
||||
}
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
match timeout(Duration::from_secs(3), join_task).await {
|
||||
Ok(task_result) => {
|
||||
task_result.unwrap();
|
||||
log::info!("All threads joined successfully.");
|
||||
}
|
||||
Err(_) => {
|
||||
log::warn!(
|
||||
"Timed out waiting for synchronous threads to join. Proceeding anyway..."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("Awaiting remaining async tasks...");
|
||||
self.tasks.wait().await;
|
||||
|
||||
@ -116,7 +116,11 @@ pub fn bench_create_and_populate_noise(
|
||||
let mut surface_height_estimate_sampler =
|
||||
SurfaceHeightEstimateSampler::generate(&base_router.surface_estimator, &surface_config);
|
||||
|
||||
chunk.populate_noise(&mut noise_sampler, &mut surface_height_estimate_sampler);
|
||||
chunk.populate_noise(
|
||||
&mut noise_sampler,
|
||||
random_config,
|
||||
&mut surface_height_estimate_sampler,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn bench_create_and_populate_biome(
|
||||
@ -230,7 +234,11 @@ pub fn bench_create_and_populate_noise_with_surface(
|
||||
SurfaceHeightEstimateSampler::generate(&base_router.surface_estimator, &surface_config);
|
||||
|
||||
chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler);
|
||||
chunk.populate_noise(&mut noise_sampler, &mut surface_height_estimate_sampler);
|
||||
chunk.populate_noise(
|
||||
&mut noise_sampler,
|
||||
random_config,
|
||||
&mut surface_height_estimate_sampler,
|
||||
);
|
||||
chunk.build_surface(
|
||||
settings,
|
||||
random_config,
|
||||
|
||||
@ -864,12 +864,12 @@ impl World {
|
||||
let fluid = Fluid::from_state_id(block_state_id).unwrap_or(&Fluid::EMPTY);
|
||||
|
||||
if fluid.id == Fluid::EMPTY.id {
|
||||
let block = Block::from_state_id(block_state_id);
|
||||
let block = Block::get_raw_id_from_state_id(block_state_id);
|
||||
let block_state = BlockState::from_id(block_state_id);
|
||||
|
||||
let blocks_movement = block_state.is_solid()
|
||||
&& block != &Block::COBWEB
|
||||
&& block != &Block::BAMBOO_SAPLING;
|
||||
&& block != Block::COBWEB
|
||||
&& block != Block::BAMBOO_SAPLING;
|
||||
|
||||
if !blocks_movement {
|
||||
let down_pos = pos.down();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user