fix nether
This commit is contained in:
parent
01d3be963d
commit
ce652860e0
186
assets/dimension.json
Normal file
186
assets/dimension.json
Normal file
@ -0,0 +1,186 @@
|
||||
{
|
||||
"minecraft:overworld": {
|
||||
"has_skylight": true,
|
||||
"has_ceiling": false,
|
||||
"coordinate_scale": 1.0,
|
||||
"min_y": -64,
|
||||
"height": 384,
|
||||
"logical_height": 384,
|
||||
"infiniburn": "#minecraft:infiniburn_overworld",
|
||||
"ambient_light": 0.0,
|
||||
"monster_spawn_light_level": {
|
||||
"min_inclusive": 0,
|
||||
"max_inclusive": 7,
|
||||
"type": "minecraft:uniform"
|
||||
},
|
||||
"monster_spawn_block_light_limit": 0,
|
||||
"attributes": {
|
||||
"minecraft:audio/ambient_sounds": {
|
||||
"mood": {
|
||||
"sound": "minecraft:ambient.cave",
|
||||
"tick_delay": 6000,
|
||||
"block_search_extent": 8,
|
||||
"offset": 2.0
|
||||
}
|
||||
},
|
||||
"minecraft:audio/background_music": {
|
||||
"default": {
|
||||
"sound": "minecraft:music.game",
|
||||
"min_delay": 12000,
|
||||
"max_delay": 24000
|
||||
},
|
||||
"creative": {
|
||||
"sound": "minecraft:music.creative",
|
||||
"min_delay": 12000,
|
||||
"max_delay": 24000
|
||||
}
|
||||
},
|
||||
"minecraft:gameplay/bed_rule": {
|
||||
"can_sleep": "when_dark",
|
||||
"can_set_spawn": "always",
|
||||
"error_message": {
|
||||
"translate": "block.minecraft.bed.no_sleep"
|
||||
}
|
||||
},
|
||||
"minecraft:gameplay/nether_portal_spawns_piglin": true,
|
||||
"minecraft:gameplay/respawn_anchor_works": false,
|
||||
"minecraft:visual/cloud_color": "#ccffffff",
|
||||
"minecraft:visual/cloud_height": 192.33,
|
||||
"minecraft:visual/fog_color": "#c0d8ff",
|
||||
"minecraft:visual/sky_color": "#78a7ff"
|
||||
},
|
||||
"timelines": "#minecraft:in_overworld"
|
||||
},
|
||||
"minecraft:overworld_caves": {
|
||||
"has_skylight": true,
|
||||
"has_ceiling": true,
|
||||
"coordinate_scale": 1.0,
|
||||
"min_y": -64,
|
||||
"height": 384,
|
||||
"logical_height": 384,
|
||||
"infiniburn": "#minecraft:infiniburn_overworld",
|
||||
"ambient_light": 0.0,
|
||||
"monster_spawn_light_level": {
|
||||
"min_inclusive": 0,
|
||||
"max_inclusive": 7,
|
||||
"type": "minecraft:uniform"
|
||||
},
|
||||
"monster_spawn_block_light_limit": 0,
|
||||
"attributes": {
|
||||
"minecraft:audio/ambient_sounds": {
|
||||
"mood": {
|
||||
"sound": "minecraft:ambient.cave",
|
||||
"tick_delay": 6000,
|
||||
"block_search_extent": 8,
|
||||
"offset": 2.0
|
||||
}
|
||||
},
|
||||
"minecraft:audio/background_music": {
|
||||
"default": {
|
||||
"sound": "minecraft:music.game",
|
||||
"min_delay": 12000,
|
||||
"max_delay": 24000
|
||||
},
|
||||
"creative": {
|
||||
"sound": "minecraft:music.creative",
|
||||
"min_delay": 12000,
|
||||
"max_delay": 24000
|
||||
}
|
||||
},
|
||||
"minecraft:gameplay/bed_rule": {
|
||||
"can_sleep": "when_dark",
|
||||
"can_set_spawn": "always",
|
||||
"error_message": {
|
||||
"translate": "block.minecraft.bed.no_sleep"
|
||||
}
|
||||
},
|
||||
"minecraft:gameplay/nether_portal_spawns_piglin": true,
|
||||
"minecraft:gameplay/respawn_anchor_works": false,
|
||||
"minecraft:visual/cloud_color": "#ccffffff",
|
||||
"minecraft:visual/cloud_height": 192.33,
|
||||
"minecraft:visual/fog_color": "#c0d8ff",
|
||||
"minecraft:visual/sky_color": "#78a7ff"
|
||||
},
|
||||
"timelines": "#minecraft:in_overworld"
|
||||
},
|
||||
"minecraft:the_end": {
|
||||
"has_fixed_time": true,
|
||||
"has_skylight": true,
|
||||
"has_ceiling": false,
|
||||
"coordinate_scale": 1.0,
|
||||
"min_y": 0,
|
||||
"height": 256,
|
||||
"logical_height": 256,
|
||||
"infiniburn": "#minecraft:infiniburn_end",
|
||||
"ambient_light": 0.25,
|
||||
"monster_spawn_light_level": 15,
|
||||
"monster_spawn_block_light_limit": 0,
|
||||
"skybox": "end",
|
||||
"attributes": {
|
||||
"minecraft:audio/ambient_sounds": {
|
||||
"mood": {
|
||||
"sound": "minecraft:ambient.cave",
|
||||
"tick_delay": 6000,
|
||||
"block_search_extent": 8,
|
||||
"offset": 2.0
|
||||
}
|
||||
},
|
||||
"minecraft:audio/background_music": {
|
||||
"default": {
|
||||
"sound": "minecraft:music.end",
|
||||
"min_delay": 6000,
|
||||
"max_delay": 24000,
|
||||
"replace_current_music": true
|
||||
}
|
||||
},
|
||||
"minecraft:gameplay/bed_rule": {
|
||||
"can_sleep": "never",
|
||||
"can_set_spawn": "never",
|
||||
"explodes": true
|
||||
},
|
||||
"minecraft:gameplay/respawn_anchor_works": false,
|
||||
"minecraft:visual/fog_color": "#181318",
|
||||
"minecraft:visual/sky_color": "#000000",
|
||||
"minecraft:visual/sky_light_color": "#e580ff",
|
||||
"minecraft:visual/sky_light_factor": 0.0
|
||||
},
|
||||
"timelines": "#minecraft:in_end"
|
||||
},
|
||||
"minecraft:the_nether": {
|
||||
"has_fixed_time": true,
|
||||
"has_skylight": false,
|
||||
"has_ceiling": true,
|
||||
"coordinate_scale": 8.0,
|
||||
"min_y": 0,
|
||||
"height": 256,
|
||||
"logical_height": 128,
|
||||
"infiniburn": "#minecraft:infiniburn_nether",
|
||||
"ambient_light": 0.1,
|
||||
"monster_spawn_light_level": 7,
|
||||
"monster_spawn_block_light_limit": 15,
|
||||
"skybox": "none",
|
||||
"cardinal_light": "nether",
|
||||
"attributes": {
|
||||
"minecraft:gameplay/bed_rule": {
|
||||
"can_sleep": "never",
|
||||
"can_set_spawn": "never",
|
||||
"explodes": true
|
||||
},
|
||||
"minecraft:gameplay/can_start_raid": false,
|
||||
"minecraft:gameplay/fast_lava": true,
|
||||
"minecraft:gameplay/piglins_zombify": false,
|
||||
"minecraft:gameplay/respawn_anchor_works": true,
|
||||
"minecraft:gameplay/sky_light_level": 4.0,
|
||||
"minecraft:gameplay/snow_golem_melts": true,
|
||||
"minecraft:gameplay/water_evaporates": true,
|
||||
"minecraft:visual/default_dripstone_particle": {
|
||||
"type": "minecraft:dripping_dripstone_lava"
|
||||
},
|
||||
"minecraft:visual/fog_end_distance": 96.0,
|
||||
"minecraft:visual/fog_start_distance": 10.0,
|
||||
"minecraft:visual/sky_light_color": "#7a7aff",
|
||||
"minecraft:visual/sky_light_factor": 0.0
|
||||
},
|
||||
"timelines": "#minecraft:in_nether"
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@ mod chunk_status;
|
||||
mod composter_increase_chance;
|
||||
mod damage_type;
|
||||
mod data_component;
|
||||
mod dimension;
|
||||
mod effect;
|
||||
mod enchantments;
|
||||
mod entity_pose;
|
||||
@ -62,6 +63,7 @@ pub fn main() {
|
||||
(chunk_status::build, "chunk_status.rs"),
|
||||
(game_event::build, "game_event.rs"),
|
||||
(game_rules::build, "game_rules.rs"),
|
||||
(dimension::build, "dimension.rs"),
|
||||
(sound_category::build, "sound_category.rs"),
|
||||
(entity_pose::build, "entity_pose.rs"),
|
||||
(scoreboard_slot::build, "scoreboard_slot.rs"),
|
||||
|
||||
137
pumpkin-data/build/dimension.rs
Normal file
137
pumpkin-data/build/dimension.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use std::{collections::BTreeMap, fs};
|
||||
|
||||
use heck::ToShoutySnakeCase;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Dimension {
|
||||
pub has_skylight: bool,
|
||||
pub has_ceiling: bool,
|
||||
pub ambient_light: f32,
|
||||
pub coordinate_scale: f64,
|
||||
pub min_y: i32,
|
||||
pub height: i32,
|
||||
pub logical_height: i32,
|
||||
pub infiniburn: String,
|
||||
#[serde(rename = "fixed_time")]
|
||||
pub fixed_time: Option<i64>,
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Deserialize)]
|
||||
// #[serde(untagged)]
|
||||
// pub enum MonsterSpawnLightLevel {
|
||||
// Int(i32),
|
||||
// Tagged(MonsterSpawnLightLevelTagged),
|
||||
// }
|
||||
|
||||
// #[derive(Clone, PartialEq, Deserialize)]
|
||||
// pub struct MonsterSpawnLightLevelTagged {
|
||||
// min_inclusive: i32,
|
||||
// max_inclusive: i32,
|
||||
// r#type: String,
|
||||
// }
|
||||
|
||||
// impl From<i32> for MonsterSpawnLightLevel {
|
||||
// fn from(value: i32) -> Self {
|
||||
// Self::Int(value)
|
||||
// }
|
||||
// }
|
||||
|
||||
pub(crate) fn build() -> TokenStream {
|
||||
println!("cargo:rerun-if-changed=../assets/dimension.json");
|
||||
|
||||
let dimensions: BTreeMap<String, Dimension> = serde_json::from_str(
|
||||
&fs::read_to_string("../assets/dimension.json").expect("Missing dimension.json"),
|
||||
)
|
||||
.expect("Failed to parse dimension.json");
|
||||
|
||||
let mut variants = TokenStream::new();
|
||||
let mut name_to_type = TokenStream::new();
|
||||
|
||||
// Iterate with index to generate a unique numeric ID
|
||||
for (id, (name, dim)) in dimensions.into_iter().enumerate() {
|
||||
let id = id as u8; // Overworld=0, Nether=1, End=2 (usually)
|
||||
let format_name = format_ident!(
|
||||
"{}",
|
||||
name.strip_prefix("minecraft:")
|
||||
.unwrap_or(&name)
|
||||
.to_shouty_snake_case()
|
||||
);
|
||||
|
||||
let fixed_time = match dim.fixed_time {
|
||||
Some(t) => quote! { Some(#t) },
|
||||
None => quote! { None },
|
||||
};
|
||||
|
||||
let ambient_light = dim.ambient_light;
|
||||
let coordinate_scale = dim.coordinate_scale;
|
||||
let height = dim.height;
|
||||
let min_y = dim.min_y;
|
||||
let logical_height = dim.logical_height;
|
||||
let has_skylight = dim.has_skylight;
|
||||
let has_ceiling = dim.has_ceiling;
|
||||
let infiniburn = &dim.infiniburn;
|
||||
|
||||
let minecraft_name = if name.contains(':') {
|
||||
name.clone()
|
||||
} else {
|
||||
format!("minecraft:{}", name)
|
||||
};
|
||||
|
||||
variants.extend(quote! {
|
||||
pub const #format_name: Self = Self {
|
||||
id: #id,
|
||||
minecraft_name: #minecraft_name,
|
||||
fixed_time: #fixed_time,
|
||||
has_skylight: #has_skylight,
|
||||
has_ceiling: #has_ceiling,
|
||||
coordinate_scale: #coordinate_scale,
|
||||
min_y: #min_y,
|
||||
height: #height,
|
||||
logical_height: #logical_height,
|
||||
infiniburn: #infiniburn,
|
||||
ambient_light: #ambient_light,
|
||||
};
|
||||
});
|
||||
|
||||
name_to_type.extend(quote! {
|
||||
#minecraft_name => Some(&Self::#format_name),
|
||||
});
|
||||
}
|
||||
|
||||
quote! {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Dimension {
|
||||
pub id: u8,
|
||||
pub minecraft_name: &'static str,
|
||||
pub fixed_time: Option<i64>,
|
||||
pub has_skylight: bool,
|
||||
pub has_ceiling: bool,
|
||||
pub coordinate_scale: f64,
|
||||
pub min_y: i32,
|
||||
pub height: i32,
|
||||
pub logical_height: i32,
|
||||
pub infiniburn: &'static str,
|
||||
pub ambient_light: f32,
|
||||
}
|
||||
|
||||
impl Dimension {
|
||||
#variants
|
||||
|
||||
pub fn from_name(name: &str) -> Option<&'static Self> {
|
||||
match name {
|
||||
#name_to_type
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
impl PartialEq for Dimension {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
impl Eq for Dimension {}
|
||||
}
|
||||
}
|
||||
@ -84,6 +84,10 @@ mod entity_type;
|
||||
#[path = "generated/spawn_egg.rs"]
|
||||
mod spawn_egg;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[path = "generated/dimension.rs"]
|
||||
pub mod dimension;
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[path = "generated/enchantment.rs"]
|
||||
mod enchantment;
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Dimension {
|
||||
ambient_light: f32,
|
||||
bed_works: bool,
|
||||
coordinate_scale: f64,
|
||||
effects: DimensionEffects,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
fixed_time: Option<i64>,
|
||||
has_ceiling: bool,
|
||||
has_raids: bool,
|
||||
has_skylight: bool,
|
||||
height: i32,
|
||||
infiniburn: String,
|
||||
logical_height: i32,
|
||||
min_y: i32,
|
||||
monster_spawn_block_light_limit: i32,
|
||||
monster_spawn_light_level: MonsterSpawnLightLevel,
|
||||
natural: bool,
|
||||
piglin_safe: bool,
|
||||
respawn_anchor_works: bool,
|
||||
ultrawarm: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Default, Debug)]
|
||||
pub enum DimensionEffects {
|
||||
#[serde(rename = "minecraft:overworld")]
|
||||
#[default]
|
||||
Overworld,
|
||||
#[serde(rename = "minecraft:the_nether")]
|
||||
TheNether,
|
||||
#[serde(rename = "minecraft:the_end")]
|
||||
TheEnd,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum MonsterSpawnLightLevel {
|
||||
Int(i32),
|
||||
Tagged(MonsterSpawnLightLevelTagged),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct MonsterSpawnLightLevelTagged {
|
||||
min_inclusive: i32,
|
||||
max_inclusive: i32,
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
impl From<i32> for MonsterSpawnLightLevel {
|
||||
fn from(value: i32) -> Self {
|
||||
Self::Int(value)
|
||||
}
|
||||
}
|
||||
@ -46,35 +46,6 @@ impl SyncedRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum VanillaDimensionType {
|
||||
Overworld,
|
||||
OverworldCaves,
|
||||
TheEnd,
|
||||
TheNether,
|
||||
}
|
||||
|
||||
impl VanillaDimensionType {
|
||||
pub fn resource_location(&self) -> ResourceLocation {
|
||||
match self {
|
||||
Self::Overworld => ResourceLocation::vanilla("overworld"),
|
||||
Self::OverworldCaves => ResourceLocation::vanilla("overworld_caves"),
|
||||
Self::TheEnd => ResourceLocation::vanilla("the_end"),
|
||||
Self::TheNether => ResourceLocation::vanilla("the_nether"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_resource_location_string(resource_location: &str) -> Option<Self> {
|
||||
match resource_location {
|
||||
"minecraft:overworld" => Some(Self::Overworld),
|
||||
"minecraft:overworld_caves" => Some(Self::OverworldCaves),
|
||||
"minecraft:the_end" => Some(Self::TheEnd),
|
||||
"minecraft:the_nether" => Some(Self::TheNether),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
pub fn get_synced() -> Vec<Self> {
|
||||
let mut synced_registries = Vec::new();
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use pumpkin_data::chunk::Biome;
|
||||
use pumpkin_data::{chunk::Biome, dimension::Dimension};
|
||||
|
||||
use crate::{
|
||||
biome::BiomeSupplier,
|
||||
dimension::Dimension,
|
||||
generation::{
|
||||
biome_coords, noise::router::multi_noise_sampler::MultiNoiseSampler, section_coords,
|
||||
},
|
||||
|
||||
@ -2,11 +2,12 @@ use sha2::{Digest, Sha256};
|
||||
use std::cell::RefCell;
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use pumpkin_data::chunk::{Biome, BiomeTree, NETHER_BIOME_SOURCE, OVERWORLD_BIOME_SOURCE};
|
||||
|
||||
use crate::{
|
||||
dimension::Dimension, generation::noise::router::multi_noise_sampler::MultiNoiseSampler,
|
||||
use pumpkin_data::{
|
||||
chunk::{Biome, BiomeTree, NETHER_BIOME_SOURCE, OVERWORLD_BIOME_SOURCE},
|
||||
dimension::Dimension,
|
||||
};
|
||||
|
||||
use crate::generation::noise::router::multi_noise_sampler::MultiNoiseSampler;
|
||||
pub mod end;
|
||||
pub mod multi_noise;
|
||||
|
||||
@ -36,10 +37,10 @@ impl BiomeSupplier for MultiNoiseBiomeSupplier {
|
||||
noise: &mut MultiNoiseSampler<'_>,
|
||||
dimension: Dimension,
|
||||
) -> &'static Biome {
|
||||
let source: &'static BiomeTree = match dimension {
|
||||
Dimension::Overworld => &OVERWORLD_BIOME_SOURCE,
|
||||
Dimension::Nether => &NETHER_BIOME_SOURCE,
|
||||
Dimension::End => unreachable!(), // Use TheEndBiomeSupplier
|
||||
let source: &'static BiomeTree = if dimension == Dimension::OVERWORLD {
|
||||
&OVERWORLD_BIOME_SOURCE
|
||||
} else {
|
||||
&NETHER_BIOME_SOURCE
|
||||
};
|
||||
let point = noise.sample(x, y, z);
|
||||
let point_list = point.convert_to_list();
|
||||
@ -56,14 +57,15 @@ pub fn hash_seed(seed: u64) -> i64 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use pumpkin_data::{chunk::Biome, noise_router::OVERWORLD_BASE_NOISE_ROUTER};
|
||||
use pumpkin_data::{
|
||||
chunk::Biome, dimension::Dimension, noise_router::OVERWORLD_BASE_NOISE_ROUTER,
|
||||
};
|
||||
use pumpkin_util::read_data_from_file;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
GENERATION_SETTINGS, GeneratorSetting, GlobalRandomConfig, ProtoChunk,
|
||||
chunk::palette::BIOME_NETWORK_MAX_BITS,
|
||||
dimension::Dimension,
|
||||
generation::{
|
||||
noise::router::{
|
||||
multi_noise_sampler::{MultiNoiseSampler, MultiNoiseSamplerBuilderOptions},
|
||||
@ -84,7 +86,7 @@ mod test {
|
||||
let multi_noise_config = MultiNoiseSamplerBuilderOptions::new(1, 1, 1);
|
||||
let mut sampler =
|
||||
MultiNoiseSampler::generate(&noise_router.multi_noise, &multi_noise_config);
|
||||
let biome = MultiNoiseBiomeSupplier::biome(-24, 1, 8, &mut sampler, Dimension::Overworld);
|
||||
let biome = MultiNoiseBiomeSupplier::biome(-24, 1, 8, &mut sampler, Dimension::OVERWORLD);
|
||||
assert_eq!(biome, &Biome::DESERT)
|
||||
}
|
||||
|
||||
@ -121,7 +123,7 @@ mod test {
|
||||
let mut chunk = ProtoChunk::new(
|
||||
chunk_x,
|
||||
chunk_z,
|
||||
surface_settings,
|
||||
&Dimension::OVERWORLD,
|
||||
default_block,
|
||||
biome_mixer_seed,
|
||||
);
|
||||
@ -144,7 +146,7 @@ mod test {
|
||||
let mut multi_noise_sampler =
|
||||
MultiNoiseSampler::generate(&noise_router.multi_noise, &multi_noise_config);
|
||||
|
||||
chunk.populate_biomes(Dimension::Overworld, &mut multi_noise_sampler);
|
||||
chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler);
|
||||
|
||||
for (biome_x, biome_y, biome_z, biome_id) in data.data {
|
||||
let calculated_biome = chunk.get_biome(biome_x, biome_y, biome_z);
|
||||
|
||||
@ -30,13 +30,14 @@ impl NoiseValuePoint {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use pumpkin_data::{chunk::Biome, noise_router::OVERWORLD_BASE_NOISE_ROUTER};
|
||||
use pumpkin_data::{
|
||||
chunk::Biome, dimension::Dimension, noise_router::OVERWORLD_BASE_NOISE_ROUTER,
|
||||
};
|
||||
use pumpkin_util::read_data_from_file;
|
||||
|
||||
use crate::{
|
||||
GENERATION_SETTINGS, GeneratorSetting, GlobalRandomConfig, ProtoChunk,
|
||||
biome::{BiomeSupplier, MultiNoiseBiomeSupplier},
|
||||
dimension::Dimension,
|
||||
generation::{
|
||||
noise::router::{
|
||||
multi_noise_sampler::{MultiNoiseSampler, MultiNoiseSamplerBuilderOptions},
|
||||
@ -71,7 +72,7 @@ mod test {
|
||||
let _chunk = ProtoChunk::new(
|
||||
chunk_x,
|
||||
chunk_z,
|
||||
surface_config,
|
||||
&Dimension::OVERWORLD,
|
||||
surface_config.default_block.get_state(),
|
||||
biome_mixer_seed,
|
||||
);
|
||||
@ -121,7 +122,7 @@ mod test {
|
||||
|
||||
for (x, y, z, biome_id) in expected_data {
|
||||
let calculated_biome =
|
||||
MultiNoiseBiomeSupplier::biome(x, y, z, &mut sampler, Dimension::Overworld);
|
||||
MultiNoiseBiomeSupplier::biome(x, y, z, &mut sampler, Dimension::OVERWORLD);
|
||||
|
||||
assert_eq!(
|
||||
biome_id,
|
||||
|
||||
@ -9,7 +9,7 @@ TODO
|
||||
use crate::block::RawBlockState;
|
||||
use crate::chunk::io::LoadedData::Loaded;
|
||||
use crate::chunk::{ChunkData, ChunkHeightmapType, ChunkLight, ChunkSections, SubChunk};
|
||||
use crate::dimension::Dimension;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use std::default::Default;
|
||||
use std::pin::Pin;
|
||||
|
||||
@ -43,10 +43,9 @@ use std::sync::{Arc, Condvar, Mutex};
|
||||
|
||||
use crate::chunk::format::LightContainer;
|
||||
use crate::chunk::io::LoadedData;
|
||||
use crate::chunk::palette::{BiomePalette, BlockPalette};
|
||||
use crate::chunk_system::Chunk::Proto;
|
||||
use crate::chunk_system::StagedChunkEnum::{Biomes, Empty, Features, Full, Noise, Surface};
|
||||
use crate::generation::{biome_coords, section_coords};
|
||||
use crate::generation::biome_coords;
|
||||
use crossfire::AsyncRx;
|
||||
use pumpkin_data::chunk::ChunkStatus;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
@ -775,36 +774,45 @@ impl Chunk {
|
||||
Proto(chunk) => chunk,
|
||||
}
|
||||
}
|
||||
fn upgrade_to_level_chunk(&mut self, generation_settings: &GenerationSettings) {
|
||||
fn upgrade_to_level_chunk(&mut self, dimension: &Dimension) {
|
||||
let proto_chunk = self.get_proto_chunk_mut();
|
||||
let sub_chunks = generation_settings.shape.height as usize / BlockPalette::SIZE;
|
||||
let sections = (0..sub_chunks).map(|_| SubChunk::default()).collect();
|
||||
let mut sections = ChunkSections::new(sections, generation_settings.shape.min_y as i32);
|
||||
|
||||
for y in 0..biome_coords::from_block(generation_settings.shape.height) {
|
||||
let relative_y = y as usize;
|
||||
let section_index = relative_y / BiomePalette::SIZE;
|
||||
let relative_y = relative_y % BiomePalette::SIZE;
|
||||
let total_sections = dimension.height as usize / 16;
|
||||
let mut sections = ChunkSections::new(
|
||||
(0..total_sections).map(|_| SubChunk::default()).collect(),
|
||||
dimension.min_y,
|
||||
);
|
||||
|
||||
let proto_biome_height = biome_coords::from_block(proto_chunk.height());
|
||||
let biome_min_y = biome_coords::from_block(dimension.min_y);
|
||||
|
||||
for y_offset in 0..proto_biome_height {
|
||||
let section_index = y_offset as usize / 4;
|
||||
let relative_y = y_offset as usize % 4;
|
||||
|
||||
if let Some(section) = sections.sections.get_mut(section_index) {
|
||||
for z in 0..BiomePalette::SIZE {
|
||||
for x in 0..BiomePalette::SIZE {
|
||||
let absolute_y =
|
||||
biome_coords::from_block(generation_settings.shape.min_y as i32)
|
||||
+ y as i32;
|
||||
let biome = proto_chunk.get_biome(x as i32, absolute_y, z as i32);
|
||||
let absolute_biome_y = biome_min_y + y_offset as i32;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for y in 0..generation_settings.shape.height {
|
||||
let relative_y = y as usize;
|
||||
let section_index = section_coords::block_to_section(relative_y);
|
||||
let relative_y = relative_y % BlockPalette::SIZE;
|
||||
|
||||
let proto_block_height = proto_chunk.height();
|
||||
|
||||
for y_offset in 0..proto_block_height {
|
||||
let section_index = (y_offset as usize) / 16;
|
||||
let relative_y = (y_offset as usize) % 16;
|
||||
|
||||
if let Some(section) = sections.sections.get_mut(section_index) {
|
||||
for z in 0..BlockPalette::SIZE {
|
||||
for x in 0..BlockPalette::SIZE {
|
||||
let block = proto_chunk.get_block_state_raw(x as i32, y as i32, z as i32);
|
||||
for z in 0..16 {
|
||||
for x in 0..16 {
|
||||
let block =
|
||||
proto_chunk.get_block_state_raw(x as i32, y_offset as i32, z as i32);
|
||||
section.block_states.set(x, relative_y, z, block);
|
||||
}
|
||||
}
|
||||
@ -813,7 +821,15 @@ impl Chunk {
|
||||
let mut chunk = ChunkData {
|
||||
light_engine: ChunkLight {
|
||||
sky_light: (0..sections.sections.len())
|
||||
.map(|_| LightContainer::new_filled(15))
|
||||
.map(|_| {
|
||||
if dimension.has_skylight {
|
||||
// Overworld: Start with full sky light before occlusion
|
||||
LightContainer::new_filled(15)
|
||||
} else {
|
||||
// Nether/End: No sky light permitted
|
||||
LightContainer::new_empty(0)
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
block_light: (0..sections.sections.len())
|
||||
.map(|_| LightContainer::new_empty(0))
|
||||
@ -1141,7 +1157,7 @@ impl Cache {
|
||||
Full => {
|
||||
debug_assert_eq!(self.chunks[mid].get_proto_chunk_mut().stage, Features);
|
||||
self.chunks[mid].get_proto_chunk_mut().stage = Full;
|
||||
self.chunks[mid].upgrade_to_level_chunk(settings);
|
||||
self.chunks[mid].upgrade_to_level_chunk(&dimension);
|
||||
}
|
||||
StagedChunkEnum::None => {}
|
||||
}
|
||||
@ -1581,7 +1597,7 @@ impl GenerationSchedule {
|
||||
log::info!("io read thread start");
|
||||
use crate::biome::hash_seed;
|
||||
let biome_mixer_seed = hash_seed(level.world_gen.random_config.seed);
|
||||
let generation_setting = gen_settings_from_dimension(&level.world_gen.dimension);
|
||||
let dimension = &level.world_gen.dimension;
|
||||
let (t_send, mut t_recv) = tokio::sync::mpsc::channel(2);
|
||||
while let Ok(pos) = recv.recv().await {
|
||||
// debug!("io read thread receive chunk pos {pos:?}");
|
||||
@ -1610,7 +1626,7 @@ impl GenerationSchedule {
|
||||
let val =
|
||||
RecvChunk::IO(Chunk::Proto(Box::new(ProtoChunk::from_chunk_data(
|
||||
chunk.read().await.deref(),
|
||||
generation_setting,
|
||||
dimension,
|
||||
level.world_gen.default_block,
|
||||
biome_mixer_seed,
|
||||
))));
|
||||
@ -1631,7 +1647,7 @@ impl GenerationSchedule {
|
||||
RecvChunk::IO(Proto(Box::new(ProtoChunk::new(
|
||||
pos.x,
|
||||
pos.y,
|
||||
generation_setting,
|
||||
dimension,
|
||||
level.world_gen.default_block,
|
||||
biome_mixer_seed,
|
||||
)))),
|
||||
@ -1646,7 +1662,6 @@ impl GenerationSchedule {
|
||||
|
||||
async fn io_write_work(recv: AsyncRx<Vec<(ChunkPos, Chunk)>>, level: Arc<Level>, lock: IOLock) {
|
||||
log::info!("io write thread start",);
|
||||
let generation_setting = gen_settings_from_dimension(&level.world_gen.dimension);
|
||||
while let Ok(data) = recv.recv().await {
|
||||
// debug!("io write thread receive chunks size {}", data.len());
|
||||
let mut vec = Vec::with_capacity(data.len());
|
||||
@ -1655,7 +1670,7 @@ impl GenerationSchedule {
|
||||
Chunk::Level(chunk) => vec.push((pos, chunk)),
|
||||
Proto(chunk) => {
|
||||
let mut temp = Proto(chunk);
|
||||
temp.upgrade_to_level_chunk(generation_setting);
|
||||
temp.upgrade_to_level_chunk(&level.world_gen.dimension);
|
||||
let Chunk::Level(chunk) = temp else { panic!() };
|
||||
vec.push((pos, chunk));
|
||||
}
|
||||
|
||||
@ -1,31 +1,28 @@
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use pumpkin_config::world::LevelConfig;
|
||||
use serde::Deserialize;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
|
||||
use crate::{level::Level, world::BlockRegistryExt};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Deserialize, Debug)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Dimension {
|
||||
Overworld,
|
||||
Nether,
|
||||
End,
|
||||
}
|
||||
|
||||
impl Dimension {
|
||||
pub fn into_level(
|
||||
&self,
|
||||
level_config: &LevelConfig,
|
||||
mut base_directory: PathBuf,
|
||||
block_registry: Arc<dyn BlockRegistryExt>,
|
||||
seed: i64,
|
||||
) -> Arc<Level> {
|
||||
match self {
|
||||
Dimension::Overworld => {}
|
||||
Dimension::Nether => base_directory.push("DIM-1"),
|
||||
Dimension::End => base_directory.push("DIM1"),
|
||||
}
|
||||
Level::from_root_folder(level_config, base_directory, block_registry, seed, *self)
|
||||
}
|
||||
pub fn into_level(
|
||||
dimension: Dimension,
|
||||
level_config: &LevelConfig,
|
||||
mut base_directory: PathBuf,
|
||||
block_registry: Arc<dyn BlockRegistryExt>,
|
||||
seed: i64,
|
||||
) -> Arc<Level> {
|
||||
if dimension == Dimension::OVERWORLD {
|
||||
} else if dimension == Dimension::THE_NETHER {
|
||||
base_directory.push("DIM-1")
|
||||
} else if dimension == Dimension::THE_END {
|
||||
base_directory.push("DIM1")
|
||||
};
|
||||
Level::from_root_folder(
|
||||
level_config,
|
||||
base_directory,
|
||||
block_registry,
|
||||
seed,
|
||||
dimension,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use pumpkin_data::BlockState;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::noise_router::{
|
||||
END_BASE_NOISE_ROUTER, NETHER_BASE_NOISE_ROUTER, OVERWORLD_BASE_NOISE_ROUTER,
|
||||
};
|
||||
@ -6,7 +7,6 @@ use pumpkin_data::noise_router::{
|
||||
use super::{
|
||||
noise::router::proto_noise_router::ProtoNoiseRouters, settings::gen_settings_from_dimension,
|
||||
};
|
||||
use crate::dimension::Dimension;
|
||||
use crate::generation::proto_chunk::TerrainCache;
|
||||
use crate::generation::{GlobalRandomConfig, Seed};
|
||||
|
||||
@ -30,10 +30,14 @@ impl GeneratorInit for VanillaGenerator {
|
||||
|
||||
// TODO: The generation settings contains (part of?) the noise routers too; do we keep the separate or
|
||||
// use only the generation settings?
|
||||
let base = match dimension {
|
||||
Dimension::Overworld => OVERWORLD_BASE_NOISE_ROUTER,
|
||||
Dimension::Nether => NETHER_BASE_NOISE_ROUTER,
|
||||
Dimension::End => END_BASE_NOISE_ROUTER,
|
||||
let base = if dimension == Dimension::OVERWORLD {
|
||||
OVERWORLD_BASE_NOISE_ROUTER
|
||||
} else if dimension == Dimension::THE_NETHER {
|
||||
NETHER_BASE_NOISE_ROUTER
|
||||
} else if dimension == Dimension::THE_END {
|
||||
END_BASE_NOISE_ROUTER
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
let terrain_cache = TerrainCache::from_random(&random_config);
|
||||
let generation_settings = gen_settings_from_dimension(&dimension);
|
||||
|
||||
@ -23,6 +23,7 @@ mod surface;
|
||||
pub mod y_offset;
|
||||
|
||||
use generator::{GeneratorInit, VanillaGenerator};
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_util::{
|
||||
random::{
|
||||
RandomDeriver, RandomDeriverImpl, RandomImpl, legacy_rand::LegacyRand,
|
||||
@ -31,8 +32,6 @@ use pumpkin_util::{
|
||||
world_seed::Seed,
|
||||
};
|
||||
|
||||
use crate::dimension::Dimension;
|
||||
|
||||
pub fn get_world_gen(seed: Seed, dimension: Dimension) -> Box<VanillaGenerator> {
|
||||
// TODO decide which WorldGenerator to pick based on config.
|
||||
Box::new(VanillaGenerator::new(seed, dimension))
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::fluid::{Fluid, FluidState};
|
||||
use pumpkin_data::tag;
|
||||
use pumpkin_data::{
|
||||
@ -42,7 +43,6 @@ use crate::{
|
||||
biome::{BiomeSupplier, MultiNoiseBiomeSupplier, end::TheEndBiomeSupplier},
|
||||
block::RawBlockState,
|
||||
chunk::CHUNK_AREA,
|
||||
dimension::Dimension,
|
||||
generation::{biome, positions::chunk_pos},
|
||||
world::{BlockAccessor, BlockRegistryExt},
|
||||
};
|
||||
@ -126,7 +126,7 @@ pub struct ProtoChunk {
|
||||
biome_mixer_seed: i64,
|
||||
// These are local positions
|
||||
flat_block_map: Box<[BlockStateId]>,
|
||||
flat_biome_map: Box<[&'static Biome]>,
|
||||
pub flat_biome_map: Box<[&'static Biome]>,
|
||||
/// HEIGHTMAPS
|
||||
///
|
||||
/// Top block that is not air
|
||||
@ -168,12 +168,11 @@ impl ProtoChunk {
|
||||
pub fn new(
|
||||
x: i32,
|
||||
z: i32,
|
||||
settings: &GenerationSettings,
|
||||
dimension: &Dimension,
|
||||
default_block: &'static BlockState,
|
||||
biome_mixer_seed: i64,
|
||||
) -> Self {
|
||||
let generation_shape = &settings.shape;
|
||||
let height = generation_shape.height;
|
||||
let height = dimension.logical_height as u16;
|
||||
|
||||
let default_heightmap = vec![i16::MIN; CHUNK_AREA].into_boxed_slice();
|
||||
Self {
|
||||
@ -195,34 +194,40 @@ impl ProtoChunk {
|
||||
flat_motion_blocking_no_leaves_height_map: default_heightmap,
|
||||
structure_starts: HashMap::new(),
|
||||
height,
|
||||
bottom_y: generation_shape.min_y,
|
||||
bottom_y: dimension.min_y as i8,
|
||||
stage: StagedChunkEnum::Empty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_chunk_data(
|
||||
chunk_data: &ChunkData,
|
||||
settings: &GenerationSettings,
|
||||
dimension: &Dimension,
|
||||
default_block: &'static BlockState,
|
||||
biome_mixer_seed: i64,
|
||||
) -> Self {
|
||||
let mut proto_chunk = ProtoChunk::new(
|
||||
chunk_data.x,
|
||||
chunk_data.z,
|
||||
settings,
|
||||
dimension,
|
||||
default_block,
|
||||
biome_mixer_seed,
|
||||
);
|
||||
|
||||
for (section_y, section) in chunk_data.section.sections.iter().enumerate() {
|
||||
// 1. Calculate the base Y for this section
|
||||
let section_base_y = section_y as i32 * 16;
|
||||
|
||||
if section_base_y >= proto_chunk.height() as i32 {
|
||||
continue;
|
||||
}
|
||||
|
||||
for x in 0..16 {
|
||||
for y in 0..16 {
|
||||
for z in 0..16 {
|
||||
let block_state_id = section.block_states.get(x, y, z);
|
||||
let block_state = BlockState::from_id(block_state_id);
|
||||
|
||||
let absolute_y =
|
||||
(section_y << 4) as i32 + y as i32 + chunk_data.section.min_y;
|
||||
let absolute_y = section_base_y + y as i32 + chunk_data.section.min_y;
|
||||
|
||||
proto_chunk.set_block_state(
|
||||
&Vector3::new(x as i32, absolute_y, z as i32),
|
||||
@ -231,18 +236,23 @@ impl ProtoChunk {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for x in 0..4 {
|
||||
for y in 0..4 {
|
||||
for z in 0..4 {
|
||||
let biome_id = section.biomes.get(x, y, z);
|
||||
let biome = Biome::from_id(biome_id).unwrap();
|
||||
|
||||
let relative_y_block = (section_y as i32 * 16) + (y as i32 * 4);
|
||||
let relative_y_block = section_base_y + (y as i32 * 4);
|
||||
|
||||
let biome_y_idx = biome_coords::from_block(relative_y_block);
|
||||
|
||||
let index = proto_chunk.local_biome_pos_to_biome_index(
|
||||
x as i32,
|
||||
biome_coords::from_block(relative_y_block),
|
||||
biome_y_idx,
|
||||
z as i32,
|
||||
);
|
||||
|
||||
proto_chunk.flat_biome_map[index] = biome;
|
||||
}
|
||||
}
|
||||
@ -396,7 +406,7 @@ impl ProtoChunk {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn local_biome_pos_to_biome_index(&self, x: i32, y: i32, z: i32) -> usize {
|
||||
pub fn local_biome_pos_to_biome_index(&self, x: i32, y: i32, z: i32) -> usize {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
assert!((0..=3).contains(&x));
|
||||
@ -607,7 +617,7 @@ impl ProtoChunk {
|
||||
for x in 0..biomes_per_section {
|
||||
for y in 0..biomes_per_section {
|
||||
for z in 0..biomes_per_section {
|
||||
let biome = if dimension == Dimension::End {
|
||||
let biome = if dimension == Dimension::THE_END {
|
||||
TheEndBiomeSupplier::biome(
|
||||
start_biome_x + x,
|
||||
start_biome_y + y,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
use std::{collections::HashMap, sync::LazyLock};
|
||||
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_util::include_json_static;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{block::BlockStateCodec, dimension::Dimension};
|
||||
use crate::block::BlockStateCodec;
|
||||
|
||||
use super::{biome_coords::to_block, height_limit::HeightLimitView, surface::rule::MaterialRule};
|
||||
|
||||
@ -13,13 +14,14 @@ pub static GENERATION_SETTINGS: LazyLock<HashMap<GeneratorSetting, GenerationSet
|
||||
);
|
||||
|
||||
pub fn gen_settings_from_dimension(dimension: &Dimension) -> &GenerationSettings {
|
||||
match dimension {
|
||||
Dimension::Overworld => GENERATION_SETTINGS
|
||||
.get(&GeneratorSetting::Overworld)
|
||||
.unwrap(),
|
||||
Dimension::Nether => GENERATION_SETTINGS.get(&GeneratorSetting::Nether).unwrap(),
|
||||
Dimension::End => GENERATION_SETTINGS.get(&GeneratorSetting::End).unwrap(),
|
||||
}
|
||||
let setting = if dimension == &Dimension::OVERWORLD {
|
||||
GeneratorSetting::Overworld
|
||||
} else if dimension == &Dimension::THE_NETHER {
|
||||
GeneratorSetting::Nether
|
||||
} else {
|
||||
GeneratorSetting::End
|
||||
};
|
||||
GENERATION_SETTINGS.get(&setting).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Hash, PartialEq, Eq)]
|
||||
|
||||
@ -8,7 +8,6 @@ use crate::{
|
||||
format::{anvil::AnvilChunkFile, linear::LinearFile},
|
||||
io::{Dirtiable, FileIO, LoadedData, file_manager::ChunkFileManager},
|
||||
},
|
||||
dimension::Dimension,
|
||||
generation::get_world_gen,
|
||||
tick::{OrderedTick, ScheduledTick, TickPriority},
|
||||
world::BlockRegistryExt,
|
||||
@ -19,6 +18,7 @@ use log::trace;
|
||||
use num_traits::Zero;
|
||||
use pumpkin_config::{chunk::ChunkConfig, world::LevelConfig};
|
||||
use pumpkin_data::biome::Biome;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::{Block, block_properties::has_random_ticks, fluid::Fluid};
|
||||
use pumpkin_util::math::{position::BlockPos, vector2::Vector2};
|
||||
use pumpkin_util::world_seed::Seed;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use dimension::Dimension;
|
||||
use generation::settings::GenerationSettings;
|
||||
use pumpkin_data::BlockState;
|
||||
use pumpkin_data::{BlockState, dimension::Dimension};
|
||||
use pumpkin_util::math::vector2::Vector2;
|
||||
|
||||
pub mod biome;
|
||||
@ -67,7 +66,7 @@ pub fn bench_create_and_populate_noise(
|
||||
};
|
||||
|
||||
let biome_mixer_seed = hash_seed(random_config.seed);
|
||||
let mut chunk = ProtoChunk::new(0, 0, settings, default_block, biome_mixer_seed);
|
||||
let mut chunk = ProtoChunk::new(0, 0, &Dimension::OVERWORLD, default_block, biome_mixer_seed);
|
||||
|
||||
// Create noise sampler and other required components
|
||||
let generation_shape = &settings.shape;
|
||||
@ -128,7 +127,7 @@ pub fn bench_create_and_populate_biome(
|
||||
use crate::generation::{biome_coords, positions::chunk_pos};
|
||||
|
||||
let biome_mixer_seed = hash_seed(random_config.seed);
|
||||
let mut chunk = ProtoChunk::new(0, 0, settings, default_block, biome_mixer_seed);
|
||||
let mut chunk = ProtoChunk::new(0, 0, &Dimension::OVERWORLD, default_block, biome_mixer_seed);
|
||||
|
||||
// Create multi-noise sampler
|
||||
let generation_shape = &settings.shape;
|
||||
@ -150,7 +149,7 @@ pub fn bench_create_and_populate_biome(
|
||||
let mut multi_noise_sampler =
|
||||
MultiNoiseSampler::generate(&base_router.multi_noise, &multi_noise_config);
|
||||
|
||||
chunk.populate_biomes(Dimension::Overworld, &mut multi_noise_sampler);
|
||||
chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler);
|
||||
}
|
||||
|
||||
pub fn bench_create_and_populate_noise_with_surface(
|
||||
@ -176,7 +175,7 @@ pub fn bench_create_and_populate_noise_with_surface(
|
||||
};
|
||||
|
||||
let biome_mixer_seed = hash_seed(random_config.seed);
|
||||
let mut chunk = ProtoChunk::new(0, 0, settings, default_block, biome_mixer_seed);
|
||||
let mut chunk = ProtoChunk::new(0, 0, &Dimension::OVERWORLD, default_block, biome_mixer_seed);
|
||||
|
||||
// Create all required components
|
||||
let generation_shape = &settings.shape;
|
||||
@ -230,7 +229,7 @@ pub fn bench_create_and_populate_noise_with_surface(
|
||||
let mut surface_height_estimate_sampler =
|
||||
SurfaceHeightEstimateSampler::generate(&base_router.surface_estimator, &surface_config);
|
||||
|
||||
chunk.populate_biomes(Dimension::Overworld, &mut multi_noise_sampler);
|
||||
chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler);
|
||||
chunk.populate_noise(&mut noise_sampler, &mut surface_height_estimate_sampler);
|
||||
chunk.build_surface(
|
||||
settings,
|
||||
|
||||
@ -3,10 +3,10 @@ use std::sync::Arc;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::block_properties::BedPart;
|
||||
use pumpkin_data::block_properties::BlockProperties;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_values};
|
||||
use pumpkin_macros::pumpkin_block_from_tag;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::GameMode;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
@ -163,7 +163,7 @@ impl BlockBehaviour for BedBlock {
|
||||
};
|
||||
|
||||
// Explode if not in the overworld
|
||||
if args.world.dimension_type != VanillaDimensionType::Overworld {
|
||||
if args.world.dimension != Dimension::OVERWORLD {
|
||||
args.world
|
||||
.break_block(&bed_head_pos, None, BlockFlags::SKIP_DROPS)
|
||||
.await;
|
||||
@ -235,7 +235,7 @@ impl BlockBehaviour for BedBlock {
|
||||
if args
|
||||
.player
|
||||
.set_respawn_point(
|
||||
args.world.dimension_type,
|
||||
args.world.dimension,
|
||||
bed_head_pos,
|
||||
args.player.get_entity().yaw.load(),
|
||||
)
|
||||
|
||||
@ -4,8 +4,8 @@ use crate::block::BlockBehaviour;
|
||||
use crate::block::BlockFuture;
|
||||
use crate::block::OnEntityCollisionArgs;
|
||||
use crate::block::PlacedArgs;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_world::block::entities::end_portal::EndPortalBlockEntity;
|
||||
|
||||
#[pumpkin_block("minecraft:end_portal")]
|
||||
@ -14,13 +14,13 @@ pub struct EndPortalBlock;
|
||||
impl BlockBehaviour for EndPortalBlock {
|
||||
fn on_entity_collision<'a>(&'a self, args: OnEntityCollisionArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let world = if args.world.dimension_type == VanillaDimensionType::TheEnd {
|
||||
let world = if args.world.dimension == Dimension::THE_END {
|
||||
args.server
|
||||
.get_world_from_dimension(VanillaDimensionType::Overworld)
|
||||
.get_world_from_dimension(&Dimension::OVERWORLD)
|
||||
.await
|
||||
} else {
|
||||
args.server
|
||||
.get_world_from_dimension(VanillaDimensionType::TheEnd)
|
||||
.get_world_from_dimension(&Dimension::THE_END)
|
||||
.await
|
||||
};
|
||||
args.entity
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use pumpkin_data::block_properties::{BlockProperties, EnumVariants, HorizontalAxis};
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::fluid::Fluid;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_world::world::{BlockAccessor, BlockFlags};
|
||||
use rand::Rng;
|
||||
@ -172,10 +172,9 @@ impl BlockBehaviour for FireBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
let dimension = args.world.dimension_type;
|
||||
let dimension = args.world.dimension;
|
||||
// First lets check if we are in OverWorld or Nether, its not possible to place an Nether portal in other dimensions in Vanilla
|
||||
if (dimension == VanillaDimensionType::Overworld
|
||||
|| dimension == VanillaDimensionType::TheNether)
|
||||
if (dimension == Dimension::OVERWORLD || dimension == Dimension::THE_NETHER)
|
||||
&& let Some(portal) =
|
||||
NetherPortal::get_new_portal(args.world, args.position, HorizontalAxis::X).await
|
||||
{
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::tag::Taggable;
|
||||
use pumpkin_data::world::WorldEvent;
|
||||
use pumpkin_data::{Block, BlockDirection, tag};
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::random::RandomGenerator;
|
||||
use pumpkin_util::random::xoroshiro128::Xoroshiro;
|
||||
@ -84,10 +84,8 @@ impl FireBlockBase {
|
||||
block_pos: &BlockPos,
|
||||
direction: BlockDirection,
|
||||
) -> bool {
|
||||
let dimension = world.dimension_type;
|
||||
if dimension != VanillaDimensionType::Overworld
|
||||
&& dimension != VanillaDimensionType::TheNether
|
||||
{
|
||||
let dimension = world.dimension;
|
||||
if dimension != Dimension::OVERWORLD && dimension != Dimension::THE_NETHER {
|
||||
return false;
|
||||
}
|
||||
let mut found = false;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
use crate::block::registry::BlockActionResult;
|
||||
use crate::block::{BlockBehaviour, BlockFuture, RandomTickArgs, UseWithItemArgs};
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::flower_pot_transformations::get_potted_item;
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_values};
|
||||
use pumpkin_macros::pumpkin_block_from_tag;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
#[pumpkin_block_from_tag("minecraft:flower_pots")]
|
||||
@ -49,14 +49,8 @@ impl BlockBehaviour for FlowerPotBlock {
|
||||
|
||||
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
if (args
|
||||
.world
|
||||
.dimension_type
|
||||
.eq(&VanillaDimensionType::Overworld)
|
||||
|| args
|
||||
.world
|
||||
.dimension_type
|
||||
.eq(&VanillaDimensionType::OverworldCaves))
|
||||
if (args.world.dimension.eq(&Dimension::OVERWORLD)
|
||||
|| args.world.dimension.eq(&Dimension::OVERWORLD_CAVES))
|
||||
&& args.block.eq(&Block::POTTED_CLOSED_EYEBLOSSOM)
|
||||
&& args.world.level_time.lock().await.time_of_day % 24000 > 14500
|
||||
{
|
||||
|
||||
@ -8,9 +8,9 @@ use crate::world::World;
|
||||
use crate::world::portal::nether::NetherPortal;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::block_properties::{Axis, BlockProperties, NetherPortalLikeProperties};
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::GameMode;
|
||||
use pumpkin_world::BlockStateId;
|
||||
|
||||
@ -62,13 +62,13 @@ impl BlockBehaviour for NetherPortalBlock {
|
||||
|
||||
fn on_entity_collision<'a>(&'a self, args: OnEntityCollisionArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let target_world = if args.world.dimension_type == VanillaDimensionType::TheNether {
|
||||
let target_world = if args.world.dimension == Dimension::THE_NETHER {
|
||||
args.server
|
||||
.get_world_from_dimension(VanillaDimensionType::Overworld)
|
||||
.get_world_from_dimension(&Dimension::OVERWORLD)
|
||||
.await
|
||||
} else {
|
||||
args.server
|
||||
.get_world_from_dimension(VanillaDimensionType::TheNether)
|
||||
.get_world_from_dimension(&Dimension::THE_NETHER)
|
||||
.await
|
||||
};
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::tag::{RegistryKey, get_tag_values};
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_world::BlockStateId;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
@ -48,14 +48,8 @@ impl BlockBehaviour for FlowerBlock {
|
||||
fn random_tick<'a>(&'a self, args: RandomTickArgs<'a>) -> BlockFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
//TODO add trail particule
|
||||
if (args
|
||||
.world
|
||||
.dimension_type
|
||||
.eq(&VanillaDimensionType::Overworld)
|
||||
|| args
|
||||
.world
|
||||
.dimension_type
|
||||
.eq(&VanillaDimensionType::OverworldCaves))
|
||||
if (args.world.dimension.eq(&Dimension::OVERWORLD)
|
||||
|| args.world.dimension.eq(&Dimension::OVERWORLD_CAVES))
|
||||
&& args.block.eq(&Block::CLOSED_EYEBLOSSOM)
|
||||
&& args.world.level_time.lock().await.time_of_day % 24000 > 14500
|
||||
{
|
||||
|
||||
@ -2,11 +2,11 @@ use std::sync::Arc;
|
||||
|
||||
use pumpkin_data::{
|
||||
Block, BlockDirection,
|
||||
dimension::Dimension,
|
||||
fluid::{Falling, Fluid, FluidProperties, Level},
|
||||
world::WorldEvent,
|
||||
};
|
||||
use pumpkin_macros::pumpkin_block;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::{BlockStateId, tick::TickPriority, world::BlockFlags};
|
||||
|
||||
@ -141,7 +141,7 @@ impl FluidBehaviour for FlowingLava {
|
||||
impl FlowingFluid for FlowingLava {
|
||||
fn get_level_decrease_per_block(&self, world: &World) -> i32 {
|
||||
// ultrawarm logic
|
||||
if world.dimension_type == VanillaDimensionType::TheNether {
|
||||
if world.dimension == Dimension::THE_NETHER {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
@ -150,7 +150,7 @@ impl FlowingFluid for FlowingLava {
|
||||
|
||||
fn get_max_flow_distance(&self, world: &World) -> i32 {
|
||||
// ultrawarm logic
|
||||
if world.dimension_type == VanillaDimensionType::TheNether {
|
||||
if world.dimension == Dimension::THE_NETHER {
|
||||
4
|
||||
} else {
|
||||
2
|
||||
|
||||
@ -10,7 +10,7 @@ use crate::command::{
|
||||
tree::{CommandTree, builder::argument},
|
||||
};
|
||||
use crate::server::Server;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_util::{math::position::BlockPos, text::TextComponent};
|
||||
|
||||
const NAMES: [&str; 1] = ["setworldspawn"];
|
||||
@ -106,18 +106,14 @@ async fn setworldspawn(
|
||||
"Failed to get world.",
|
||||
)));
|
||||
};
|
||||
|
||||
match world.dimension_type {
|
||||
VanillaDimensionType::Overworld | VanillaDimensionType::OverworldCaves => {}
|
||||
_ => {
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.setworldspawn.failure.not_overworld",
|
||||
[],
|
||||
))
|
||||
.await;
|
||||
return Ok(());
|
||||
}
|
||||
if world.dimension != Dimension::OVERWORLD && world.dimension != Dimension::OVERWORLD_CAVES {
|
||||
sender
|
||||
.send_message(TextComponent::translate(
|
||||
"commands.setworldspawn.failure.not_overworld",
|
||||
[],
|
||||
))
|
||||
.await;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut level_info_guard = server.level_info.write().await;
|
||||
|
||||
@ -7,6 +7,7 @@ use living::LivingEntity;
|
||||
use player::Player;
|
||||
use pumpkin_data::BlockState;
|
||||
use pumpkin_data::block_properties::{EnumVariants, Integer0To15};
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::fluid::Fluid;
|
||||
use pumpkin_data::{Block, BlockDirection};
|
||||
use pumpkin_data::{
|
||||
@ -25,7 +26,6 @@ use pumpkin_protocol::{
|
||||
},
|
||||
ser::serializer::Serializer,
|
||||
};
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::math::vector3::Axis;
|
||||
use pumpkin_util::math::{
|
||||
boundingbox::{BoundingBox, EntityDimensions},
|
||||
@ -993,7 +993,7 @@ impl Entity {
|
||||
.await;
|
||||
}
|
||||
|
||||
let lava_speed = if self.world.dimension_type == VanillaDimensionType::TheNether {
|
||||
let lava_speed = if self.world.dimension == Dimension::THE_NETHER {
|
||||
0.007
|
||||
} else {
|
||||
0.002_333_333
|
||||
@ -1305,21 +1305,9 @@ impl Entity {
|
||||
self.portal_cooldown
|
||||
.store(self.default_portal_cooldown(), Ordering::Relaxed);
|
||||
let pos = self.pos.load();
|
||||
// TODO: this is bad
|
||||
let scale_factor_new = if portal_manager.portal_world.dimension_type
|
||||
== VanillaDimensionType::TheNether
|
||||
{
|
||||
8.0
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
// TODO: this is bad
|
||||
let scale_factor_current =
|
||||
if self.world.dimension_type == VanillaDimensionType::TheNether {
|
||||
8.0
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
let scale_factor_new = portal_manager.portal_world.dimension.coordinate_scale;
|
||||
let scale_factor_current = self.world.dimension.coordinate_scale;
|
||||
|
||||
let scale_factor = scale_factor_current / scale_factor_new;
|
||||
// TODO
|
||||
let pos = BlockPos::floored(pos.x * scale_factor, pos.y, pos.z * scale_factor);
|
||||
@ -1762,7 +1750,7 @@ impl Entity {
|
||||
}
|
||||
|
||||
pub async fn check_out_of_world(&self, dyn_self: &dyn EntityBase) {
|
||||
if self.pos.load().y < f64::from(self.world.generation_settings().shape.min_y) - 64.0 {
|
||||
if self.pos.load().y < f64::from(self.world.dimension.min_y) - 64.0 {
|
||||
// Tick out of world damage
|
||||
dyn_self
|
||||
.damage(dyn_self, 4.0, DamageType::OUT_OF_WORLD)
|
||||
|
||||
@ -10,6 +10,7 @@ use std::time::{Duration, Instant};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use crossbeam::channel::Receiver;
|
||||
use log::warn;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_inventory::player::ender_chest_inventory::EnderChestInventory;
|
||||
use pumpkin_protocol::bedrock::client::level_chunk::CLevelChunk;
|
||||
use pumpkin_protocol::bedrock::client::set_time::CSetTime;
|
||||
@ -56,7 +57,6 @@ use pumpkin_protocol::java::client::play::{
|
||||
CUpdateTime, GameEvent, MetaDataType, Metadata, PlayerAction, PlayerInfoFlags, PreviousMessage,
|
||||
};
|
||||
use pumpkin_protocol::java::server::play::SClickSlot;
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::math::{
|
||||
boundingbox::BoundingBox, experience, position::BlockPos, vector2::Vector2, vector3::Vector3,
|
||||
};
|
||||
@ -661,7 +661,7 @@ impl Player {
|
||||
|
||||
pub async fn set_respawn_point(
|
||||
&self,
|
||||
dimension: VanillaDimensionType,
|
||||
dimension: Dimension,
|
||||
block_pos: BlockPos,
|
||||
yaw: f32,
|
||||
) -> bool {
|
||||
@ -690,12 +690,12 @@ impl Player {
|
||||
|
||||
let block = self.world().get_block(&respawn_point.position).await;
|
||||
|
||||
if respawn_point.dimension == VanillaDimensionType::Overworld
|
||||
if respawn_point.dimension == Dimension::OVERWORLD
|
||||
&& block.has_tag(&tag::Block::MINECRAFT_BEDS)
|
||||
{
|
||||
// TODO: calculate respawn position
|
||||
Some((respawn_point.position.to_f64(), respawn_point.yaw))
|
||||
} else if respawn_point.dimension == VanillaDimensionType::TheNether
|
||||
} else if respawn_point.dimension == Dimension::THE_NETHER
|
||||
&& block == &Block::RESPAWN_ANCHOR
|
||||
{
|
||||
// TODO: calculate respawn position
|
||||
@ -1292,7 +1292,7 @@ impl Player {
|
||||
self.chunk_manager.lock().await.change_world(¤t_world.level, &new_world.level);
|
||||
|
||||
let last_pos = self.living_entity.entity.last_pos.load();
|
||||
let death_dimension = self.world().dimension_type.resource_location();
|
||||
let death_dimension = ResourceLocation::from(self.world().dimension.minecraft_name);
|
||||
let death_location = BlockPos(Vector3::new(
|
||||
last_pos.x.round() as i32,
|
||||
last_pos.y.round() as i32,
|
||||
@ -1300,8 +1300,8 @@ impl Player {
|
||||
));
|
||||
self.client
|
||||
.send_packet_now(&CRespawn::new(
|
||||
(new_world.dimension_type as u8).into(),
|
||||
new_world.dimension_type.resource_location(),
|
||||
(new_world.dimension.id).into(),
|
||||
ResourceLocation::from(new_world.dimension.minecraft_name),
|
||||
biome::hash_seed(new_world.level.seed.0), // seed
|
||||
self.gamemode.load() as u8,
|
||||
self.gamemode.load() as i8,
|
||||
@ -2117,7 +2117,7 @@ impl NBTStorage for Player {
|
||||
|
||||
nbt.put_string(
|
||||
"Dimension",
|
||||
self.world().dimension_type.resource_location().to_string(),
|
||||
ResourceLocation::from(self.world().dimension.minecraft_name).to_string(),
|
||||
);
|
||||
})
|
||||
}
|
||||
@ -2531,7 +2531,7 @@ impl Abilities {
|
||||
/// Represents the player's respawn point.
|
||||
#[derive(Copy, Debug, Clone, PartialEq)]
|
||||
pub struct RespawnPoint {
|
||||
pub dimension: VanillaDimensionType,
|
||||
pub dimension: Dimension,
|
||||
pub position: BlockPos,
|
||||
pub yaw: f32,
|
||||
pub force: bool,
|
||||
|
||||
@ -6,11 +6,11 @@ use crate::{
|
||||
};
|
||||
use pumpkin_data::{
|
||||
Block,
|
||||
dimension::Dimension,
|
||||
fluid::Fluid,
|
||||
item::Item,
|
||||
sound::{Sound, SoundCategory},
|
||||
};
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::{
|
||||
GameMode,
|
||||
math::{position::BlockPos, vector3::Vector3},
|
||||
@ -236,9 +236,7 @@ impl ItemBehaviour for FilledBucketItem {
|
||||
return;
|
||||
};
|
||||
|
||||
if item.id != Item::LAVA_BUCKET.id
|
||||
&& world.dimension_type == VanillaDimensionType::TheNether
|
||||
{
|
||||
if item.id != Item::LAVA_BUCKET.id && world.dimension == Dimension::THE_NETHER {
|
||||
world
|
||||
.play_sound_raw(
|
||||
Sound::BlockFireExtinguish as u16,
|
||||
|
||||
@ -13,17 +13,18 @@ use crate::{command::dispatcher::CommandDispatcher, entity::player::Player, worl
|
||||
use connection_cache::{CachedBranding, CachedStatus};
|
||||
use key_store::KeyStore;
|
||||
use pumpkin_config::{AdvancedConfiguration, BasicConfiguration};
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_world::dimension::into_level;
|
||||
|
||||
use crate::command::CommandSender;
|
||||
use pumpkin_macros::send_cancellable;
|
||||
use pumpkin_protocol::java::client::login::CEncryptionRequest;
|
||||
use pumpkin_protocol::java::client::play::CChangeDifficulty;
|
||||
use pumpkin_protocol::{ClientPacket, java::client::config::CPluginMessage};
|
||||
use pumpkin_registry::{Registry, VanillaDimensionType};
|
||||
use pumpkin_registry::Registry;
|
||||
use pumpkin_util::Difficulty;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_util::text::TextComponent;
|
||||
use pumpkin_world::dimension::Dimension;
|
||||
use pumpkin_world::lock::LevelLocker;
|
||||
use pumpkin_world::lock::anvil::AnvilLevelLocker;
|
||||
use pumpkin_world::world_info::anvil::{
|
||||
@ -72,7 +73,7 @@ pub struct Server {
|
||||
/// Manages multiple worlds within the server.
|
||||
pub worlds: RwLock<Vec<Arc<World>>>,
|
||||
/// All the dimensions that exist on the server.
|
||||
pub dimensions: Vec<VanillaDimensionType>,
|
||||
pub dimensions: Vec<Dimension>,
|
||||
/// Caches game registries for efficient access.
|
||||
pub cached_registry: Vec<Registry>,
|
||||
/// Assigns unique IDs to containers.
|
||||
@ -182,10 +183,9 @@ impl Server {
|
||||
container_id: 0.into(),
|
||||
worlds: RwLock::new(vec![]),
|
||||
dimensions: vec![
|
||||
VanillaDimensionType::Overworld,
|
||||
VanillaDimensionType::OverworldCaves,
|
||||
VanillaDimensionType::TheNether,
|
||||
VanillaDimensionType::TheEnd,
|
||||
Dimension::OVERWORLD,
|
||||
Dimension::THE_NETHER,
|
||||
Dimension::THE_END,
|
||||
],
|
||||
command_dispatcher,
|
||||
block_registry: block_registry.clone(),
|
||||
@ -215,35 +215,43 @@ impl Server {
|
||||
|
||||
log::info!("Loading Overworld: {seed}");
|
||||
let overworld = World::load(
|
||||
Dimension::Overworld.into_level(
|
||||
into_level(
|
||||
Dimension::OVERWORLD,
|
||||
level_config,
|
||||
world_path.clone(),
|
||||
block_registry.clone(),
|
||||
seed,
|
||||
),
|
||||
level_info.clone(),
|
||||
VanillaDimensionType::Overworld,
|
||||
Dimension::OVERWORLD,
|
||||
block_registry.clone(),
|
||||
weak.clone(),
|
||||
);
|
||||
log::info!("Loading Nether: {seed}");
|
||||
let nether = World::load(
|
||||
Dimension::Nether.into_level(
|
||||
into_level(
|
||||
Dimension::THE_NETHER,
|
||||
level_config,
|
||||
world_path.clone(),
|
||||
block_registry.clone(),
|
||||
seed,
|
||||
),
|
||||
level_info.clone(),
|
||||
VanillaDimensionType::TheNether,
|
||||
Dimension::THE_NETHER,
|
||||
block_registry.clone(),
|
||||
weak.clone(),
|
||||
);
|
||||
log::info!("Loading End: {seed}");
|
||||
let end = World::load(
|
||||
Dimension::End.into_level(level_config, world_path, block_registry.clone(), seed),
|
||||
into_level(
|
||||
Dimension::THE_END,
|
||||
level_config,
|
||||
world_path,
|
||||
block_registry.clone(),
|
||||
seed,
|
||||
),
|
||||
level_info,
|
||||
VanillaDimensionType::TheEnd,
|
||||
Dimension::THE_END,
|
||||
block_registry,
|
||||
weak,
|
||||
);
|
||||
@ -266,14 +274,15 @@ impl Server {
|
||||
self.tasks.spawn(task)
|
||||
}
|
||||
|
||||
pub async fn get_world_from_dimension(&self, dimension: VanillaDimensionType) -> Arc<World> {
|
||||
pub async fn get_world_from_dimension(&self, dimension: &Dimension) -> Arc<World> {
|
||||
// TODO: this is really bad
|
||||
let world_guard = self.worlds.read().await;
|
||||
match dimension {
|
||||
VanillaDimensionType::Overworld => world_guard.first(),
|
||||
VanillaDimensionType::OverworldCaves => todo!(),
|
||||
VanillaDimensionType::TheEnd => world_guard.get(2),
|
||||
VanillaDimensionType::TheNether => world_guard.get(1),
|
||||
if dimension == &Dimension::OVERWORLD {
|
||||
world_guard.first()
|
||||
} else if dimension == &Dimension::THE_NETHER {
|
||||
world_guard.get(1)
|
||||
} else {
|
||||
world_guard.get(2)
|
||||
}
|
||||
.cloned()
|
||||
.unwrap()
|
||||
@ -315,9 +324,7 @@ impl Server {
|
||||
|
||||
let (world, nbt) = if let Ok(Some(data)) = self.player_data_storage.load_data(&profile.id) {
|
||||
if let Some(dimension_key) = data.get_string("Dimension") {
|
||||
if let Some(dimension) =
|
||||
VanillaDimensionType::from_resource_location_string(dimension_key)
|
||||
{
|
||||
if let Some(dimension) = Dimension::from_name(dimension_key) {
|
||||
let world = self.get_world_from_dimension(dimension).await;
|
||||
(world, Some(data))
|
||||
} else {
|
||||
|
||||
@ -39,6 +39,7 @@ use crossbeam::queue::SegQueue;
|
||||
use explosion::Explosion;
|
||||
use pumpkin_config::BasicConfiguration;
|
||||
use pumpkin_data::data_component_impl::EquipmentSlot;
|
||||
use pumpkin_data::dimension::Dimension;
|
||||
use pumpkin_data::entity::MobCategory;
|
||||
use pumpkin_data::fluid::{Falling, FluidProperties, FluidState};
|
||||
use pumpkin_data::{
|
||||
@ -94,7 +95,6 @@ use pumpkin_protocol::{
|
||||
CWorldEvent,
|
||||
},
|
||||
};
|
||||
use pumpkin_registry::VanillaDimensionType;
|
||||
use pumpkin_util::resource_location::ResourceLocation;
|
||||
use pumpkin_util::text::{TextComponent, color::NamedColor};
|
||||
use pumpkin_util::{
|
||||
@ -108,9 +108,8 @@ use pumpkin_util::{
|
||||
use pumpkin_world::chunk::palette::BlockPalette;
|
||||
use pumpkin_world::world::{GetBlockError, WorldFuture};
|
||||
use pumpkin_world::{
|
||||
BlockStateId, CURRENT_BEDROCK_MC_VERSION, GENERATION_SETTINGS, GeneratorSetting, biome,
|
||||
block::entities::BlockEntity, chunk::io::Dirtiable, inventory::Inventory, item::ItemStack,
|
||||
world::SimpleWorld,
|
||||
BlockStateId, CURRENT_BEDROCK_MC_VERSION, biome, block::entities::BlockEntity,
|
||||
chunk::io::Dirtiable, inventory::Inventory, item::ItemStack, world::SimpleWorld,
|
||||
};
|
||||
use pumpkin_world::{chunk::ChunkData, world::BlockAccessor};
|
||||
use pumpkin_world::{level::Level, tick::TickPriority};
|
||||
@ -132,7 +131,7 @@ pub mod weather;
|
||||
use crate::world::natural_spawner::{SpawnState, spawn_for_chunk};
|
||||
use pumpkin_data::effect::StatusEffect;
|
||||
use pumpkin_world::chunk::ChunkHeightmapType::MotionBlocking;
|
||||
use pumpkin_world::generation::settings::GenerationSettings;
|
||||
use pumpkin_world::generation::settings::gen_settings_from_dimension;
|
||||
use uuid::Uuid;
|
||||
use weather::Weather;
|
||||
|
||||
@ -177,7 +176,7 @@ pub struct World {
|
||||
/// The world's time, including counting ticks for weather, time cycles, and statistics.
|
||||
pub level_time: Mutex<LevelTime>,
|
||||
/// The type of dimension the world is in.
|
||||
pub dimension_type: VanillaDimensionType,
|
||||
pub dimension: Dimension,
|
||||
pub sea_level: i32,
|
||||
pub min_y: i32,
|
||||
/// The world's weather, including rain and thunder levels.
|
||||
@ -197,33 +196,21 @@ impl World {
|
||||
pub fn load(
|
||||
level: Arc<Level>,
|
||||
level_info: Arc<RwLock<LevelData>>,
|
||||
dimension_type: VanillaDimensionType,
|
||||
dimension: Dimension,
|
||||
block_registry: Arc<BlockRegistry>,
|
||||
server: Weak<Server>,
|
||||
) -> Self {
|
||||
// TODO
|
||||
let generation_settings = match dimension_type {
|
||||
VanillaDimensionType::Overworld => GENERATION_SETTINGS
|
||||
.get(&GeneratorSetting::Overworld)
|
||||
.unwrap(),
|
||||
VanillaDimensionType::OverworldCaves => todo!(),
|
||||
VanillaDimensionType::TheEnd => {
|
||||
GENERATION_SETTINGS.get(&GeneratorSetting::End).unwrap()
|
||||
}
|
||||
VanillaDimensionType::TheNether => {
|
||||
GENERATION_SETTINGS.get(&GeneratorSetting::Nether).unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
let generation_settings = gen_settings_from_dimension(&dimension);
|
||||
Self {
|
||||
level,
|
||||
level_info,
|
||||
players: Arc::new(RwLock::new(HashMap::new())),
|
||||
entities: Arc::new(RwLock::new(HashMap::new())),
|
||||
scoreboard: Mutex::new(Scoreboard::default()),
|
||||
worldborder: Mutex::new(Worldborder::new(0.0, 0.0, 30_000_000.0, 0, 0, 0)),
|
||||
worldborder: Mutex::new(Worldborder::new(0.0, 0.0, 5.999_996_8E7, 0, 5, 300)),
|
||||
level_time: Mutex::new(LevelTime::new()),
|
||||
dimension_type,
|
||||
dimension,
|
||||
weather: Mutex::new(Weather::new()),
|
||||
block_registry,
|
||||
sea_level: generation_settings.sea_level,
|
||||
@ -1154,29 +1141,9 @@ impl World {
|
||||
spawn_for_chunk(self, chunk_pos, chunk, spawn_state, spawn_list).await;
|
||||
}
|
||||
|
||||
pub fn generation_settings(&self) -> &GenerationSettings {
|
||||
// TODO: this is bad
|
||||
match self.dimension_type {
|
||||
VanillaDimensionType::Overworld => GENERATION_SETTINGS
|
||||
.get(&GeneratorSetting::Overworld)
|
||||
.unwrap(),
|
||||
VanillaDimensionType::OverworldCaves => todo!(),
|
||||
VanillaDimensionType::TheEnd => {
|
||||
GENERATION_SETTINGS.get(&GeneratorSetting::End).unwrap()
|
||||
}
|
||||
VanillaDimensionType::TheNether => {
|
||||
GENERATION_SETTINGS.get(&GeneratorSetting::Nether).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the y position of the first non air block from the top down
|
||||
pub async fn get_top_block(&self, position: Vector2<i32>) -> i32 {
|
||||
let generation_settings = self.generation_settings();
|
||||
for y in (i32::from(generation_settings.shape.min_y)
|
||||
..i32::from(generation_settings.shape.max_y()))
|
||||
.rev()
|
||||
{
|
||||
for y in (self.dimension.min_y..self.dimension.height).rev() {
|
||||
let pos = BlockPos::new(position.x, y, position.y);
|
||||
let block = self.get_block_state(&pos).await;
|
||||
if block.is_air() {
|
||||
@ -1184,7 +1151,7 @@ impl World {
|
||||
}
|
||||
return y;
|
||||
}
|
||||
i32::from(generation_settings.shape.min_y)
|
||||
self.dimension.min_y
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_lines)]
|
||||
@ -1379,7 +1346,7 @@ impl World {
|
||||
let dimensions: Vec<ResourceLocation> = server
|
||||
.dimensions
|
||||
.iter()
|
||||
.map(VanillaDimensionType::resource_location)
|
||||
.map(|d| ResourceLocation::from(d.minecraft_name))
|
||||
.collect();
|
||||
|
||||
// This code follows the vanilla packet order
|
||||
@ -1404,8 +1371,8 @@ impl World {
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
(self.dimension_type as u8).into(),
|
||||
self.dimension_type.resource_location(),
|
||||
(self.dimension.id).into(),
|
||||
ResourceLocation::from(self.dimension.minecraft_name),
|
||||
biome::hash_seed(self.level.seed.0), // seed
|
||||
gamemode as u8,
|
||||
player
|
||||
@ -1805,7 +1772,7 @@ impl World {
|
||||
|
||||
pub async fn respawn_player(&self, player: &Arc<Player>, alive: bool) {
|
||||
let last_pos = player.living_entity.entity.last_pos.load();
|
||||
let death_dimension = player.world().dimension_type.resource_location();
|
||||
let death_dimension = ResourceLocation::from(player.world().dimension.minecraft_name);
|
||||
let death_location = BlockPos(Vector3::new(
|
||||
last_pos.x.round() as i32,
|
||||
last_pos.y.round() as i32,
|
||||
@ -1819,8 +1786,8 @@ impl World {
|
||||
player
|
||||
.client
|
||||
.enqueue_packet(&CRespawn::new(
|
||||
(self.dimension_type as u8).into(),
|
||||
self.dimension_type.resource_location(),
|
||||
(self.dimension.id).into(),
|
||||
ResourceLocation::from(self.dimension.minecraft_name),
|
||||
biome::hash_seed(self.level.seed.0), // seed
|
||||
player.gamemode.load() as u8,
|
||||
player.gamemode.load() as i8,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user