fix: nether/end
This commit is contained in:
parent
38a924e6ce
commit
8634d8740f
@ -159,7 +159,7 @@ pub fn get_region_seed(world_seed: u64, region_x: i32, region_z: i32, salt: u32)
|
||||
/// A seed value to be used with a legacy random generator.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn seed_slime_chunk(x: i32, z: i32, seed: u64, salt: u64) -> u64 {
|
||||
pub const fn seed_slime_chunk(x: i32, z: i32, seed: u64, salt: u64) -> u64 {
|
||||
(seed
|
||||
.wrapping_add((x.wrapping_mul(x).wrapping_mul(4_987_142)) as i64 as u64)
|
||||
.wrapping_add((x.wrapping_mul(5_947_611)) as i64 as u64)
|
||||
|
||||
@ -280,6 +280,46 @@ impl TextComponentBase {
|
||||
text
|
||||
}
|
||||
|
||||
/// Converts this component by resolving all translations.
|
||||
///
|
||||
/// # Returns
|
||||
/// A new component with all translations resolved.
|
||||
fn translate_hover_event(style: &mut Style) {
|
||||
if let Some(ref hover) = style.hover_event {
|
||||
style.hover_event = match hover {
|
||||
HoverEvent::ShowText { value } => {
|
||||
let mut hover_components = vec![];
|
||||
for hover_component in value {
|
||||
hover_components.push(hover_component.to_owned().to_translated());
|
||||
}
|
||||
Some(HoverEvent::ShowText {
|
||||
value: hover_components,
|
||||
})
|
||||
}
|
||||
HoverEvent::ShowEntity { name, id, uuid } => name.as_ref().map_or_else(
|
||||
|| {
|
||||
Some(HoverEvent::ShowEntity {
|
||||
name: None,
|
||||
id: id.clone(),
|
||||
uuid: uuid.clone(),
|
||||
})
|
||||
},
|
||||
|name| {
|
||||
Some(HoverEvent::ShowEntity {
|
||||
name: Some(name.iter().map(|x| x.to_owned().to_translated()).collect()),
|
||||
id: id.clone(),
|
||||
uuid: uuid.clone(),
|
||||
})
|
||||
},
|
||||
),
|
||||
HoverEvent::ShowItem { id, count } => Some(HoverEvent::ShowItem {
|
||||
id: id.clone(),
|
||||
count: count.to_owned(),
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this component by resolving all translations.
|
||||
///
|
||||
/// # Returns
|
||||
@ -354,52 +394,16 @@ impl TextComponentBase {
|
||||
_ => self, // If not a translation, return as is
|
||||
};
|
||||
// Ensure that the extra components are translated
|
||||
let mut extra = vec![];
|
||||
for extra_component in component.extra {
|
||||
let translated = extra_component.to_translated();
|
||||
extra.push(translated);
|
||||
}
|
||||
let extra = component
|
||||
.extra
|
||||
.into_iter()
|
||||
.map(Self::to_translated)
|
||||
.collect();
|
||||
|
||||
// If the hover event is present, it will also be translated
|
||||
let style = match component.style.hover_event {
|
||||
None => component.style,
|
||||
Some(ref hover) => {
|
||||
let mut style = component.style.clone();
|
||||
style.hover_event = match hover {
|
||||
HoverEvent::ShowText { value } => {
|
||||
let mut hover_components = vec![];
|
||||
for hover_component in value {
|
||||
hover_components.push(hover_component.to_owned().to_translated());
|
||||
}
|
||||
Some(HoverEvent::ShowText {
|
||||
value: hover_components,
|
||||
})
|
||||
}
|
||||
HoverEvent::ShowEntity { name, id, uuid } => name.as_ref().map_or_else(
|
||||
|| {
|
||||
Some(HoverEvent::ShowEntity {
|
||||
name: None,
|
||||
id: id.clone(),
|
||||
uuid: uuid.clone(),
|
||||
})
|
||||
},
|
||||
|name| {
|
||||
Some(HoverEvent::ShowEntity {
|
||||
name: Some(
|
||||
name.iter().map(|x| x.to_owned().to_translated()).collect(),
|
||||
),
|
||||
id: id.clone(),
|
||||
uuid: uuid.clone(),
|
||||
})
|
||||
},
|
||||
),
|
||||
HoverEvent::ShowItem { id, count } => Some(HoverEvent::ShowItem {
|
||||
id: id.clone(),
|
||||
count: count.to_owned(),
|
||||
}),
|
||||
};
|
||||
style
|
||||
}
|
||||
};
|
||||
let mut style = component.style;
|
||||
Self::translate_hover_event(&mut style);
|
||||
|
||||
Self {
|
||||
content: component.content,
|
||||
style,
|
||||
|
||||
@ -13,10 +13,10 @@ pub fn into_level(
|
||||
seed: i64,
|
||||
gen_pool: Option<Arc<rayon::ThreadPool>>,
|
||||
) -> Arc<Level> {
|
||||
if dimension == Dimension::OVERWORLD {
|
||||
} else if dimension == Dimension::THE_NETHER {
|
||||
if dimension.minecraft_name == Dimension::OVERWORLD.minecraft_name {
|
||||
} else if dimension.minecraft_name == Dimension::THE_NETHER.minecraft_name {
|
||||
base_directory.push("DIM-1");
|
||||
} else if dimension == Dimension::THE_END {
|
||||
} else if dimension.minecraft_name == Dimension::THE_END.minecraft_name {
|
||||
base_directory.push("DIM1");
|
||||
}
|
||||
Level::from_root_folder(level_config, base_directory, seed, dimension, gen_pool)
|
||||
|
||||
@ -9,7 +9,7 @@ use pumpkin_util::{
|
||||
math::{block_box::BlockBox, position::BlockPos, vector3::Vector3},
|
||||
random::{RandomGenerator, RandomImpl, get_carver_seed, xoroshiro128::Xoroshiro},
|
||||
};
|
||||
use tracing::debug;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::generation::structure::structures::stronghold::StrongholdPieceType;
|
||||
pub use crate::world::WorldPortalExt;
|
||||
@ -411,7 +411,7 @@ impl StructurePiece {
|
||||
let block_pos = self.offset_pos(x, y, z);
|
||||
|
||||
if !box_limit.contains_pos(&block_pos) {
|
||||
debug!("Structure out of bounds");
|
||||
trace!("Structure out of bounds");
|
||||
return Block::AIR.default_state;
|
||||
}
|
||||
|
||||
@ -431,7 +431,7 @@ impl StructurePiece {
|
||||
|
||||
// Bounds and logic checks
|
||||
if !box_limit.contains_pos(&block_pos) {
|
||||
debug!("Structure out of bounds");
|
||||
trace!("Structure out of bounds");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -14,14 +14,23 @@ 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 == Dimension::THE_END {
|
||||
args.server.get_world_from_dimension(&Dimension::OVERWORLD)
|
||||
} else {
|
||||
args.server.get_world_from_dimension(&Dimension::THE_END)
|
||||
};
|
||||
let target_world =
|
||||
if args.world.dimension.minecraft_name == Dimension::THE_END.minecraft_name {
|
||||
args.server.get_world_from_dimension(&Dimension::OVERWORLD)
|
||||
} else {
|
||||
args.server.get_world_from_dimension(&Dimension::THE_END)
|
||||
};
|
||||
if Arc::ptr_eq(&target_world, args.world) {
|
||||
return;
|
||||
}
|
||||
tracing::info!(
|
||||
"End portal collision at {:?}, targeting world {:?}",
|
||||
args.position,
|
||||
target_world.dimension.minecraft_name
|
||||
);
|
||||
args.entity
|
||||
.get_entity()
|
||||
.try_use_portal(0, world, *args.position)
|
||||
.try_use_portal(0, target_world, *args.position)
|
||||
.await;
|
||||
})
|
||||
}
|
||||
|
||||
@ -70,12 +70,22 @@ 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 == Dimension::THE_NETHER {
|
||||
args.server.get_world_from_dimension(&Dimension::OVERWORLD)
|
||||
} else {
|
||||
args.server.get_world_from_dimension(&Dimension::THE_NETHER)
|
||||
};
|
||||
let target_world =
|
||||
if args.world.dimension.minecraft_name == Dimension::THE_NETHER.minecraft_name {
|
||||
args.server.get_world_from_dimension(&Dimension::OVERWORLD)
|
||||
} else {
|
||||
args.server.get_world_from_dimension(&Dimension::THE_NETHER)
|
||||
};
|
||||
|
||||
if Arc::ptr_eq(&target_world, args.world) {
|
||||
return;
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"Nether portal collision at {:?}, targeting world {:?}",
|
||||
args.position,
|
||||
target_world.dimension.minecraft_name
|
||||
);
|
||||
let portal_delay = Self::get_portal_time(args.world, args.entity);
|
||||
|
||||
args.entity
|
||||
|
||||
@ -44,23 +44,8 @@ impl MoveControlTrait for MoveControl {
|
||||
let mob_entity = mob.get_mob_entity();
|
||||
let living_entity = &mob_entity.living_entity;
|
||||
let entity = &living_entity.entity;
|
||||
|
||||
if self.operation == Operation::Strafe {
|
||||
let movement_speed = living_entity.get_attribute_value(&Attributes::MOVEMENT_SPEED);
|
||||
let speed_modified = (self.speed_modifier * movement_speed) as f32;
|
||||
let xa = self.strafe_forwards;
|
||||
let za = self.strafe_right;
|
||||
let mut dist = xa.hypot(za);
|
||||
if dist < 1.0 {
|
||||
dist = 1.0;
|
||||
}
|
||||
|
||||
let dist_norm = speed_modified / dist;
|
||||
let _xa_norm = xa * dist_norm;
|
||||
let _za_norm = za * dist_norm;
|
||||
|
||||
// TODO: is_walkable check
|
||||
|
||||
living_entity.movement_input.store(Vector3::new(
|
||||
self.strafe_right as f64,
|
||||
0.0,
|
||||
@ -121,11 +106,13 @@ impl MoveControlTrait for MoveControl {
|
||||
}
|
||||
|
||||
impl MoveControl {
|
||||
#[must_use]
|
||||
pub fn has_wanted(&self) -> bool {
|
||||
self.operation == Operation::MoveTo
|
||||
}
|
||||
|
||||
pub fn get_speed_modifier(&self) -> f64 {
|
||||
#[must_use]
|
||||
pub const fn get_speed_modifier(&self) -> f64 {
|
||||
self.speed_modifier
|
||||
}
|
||||
|
||||
@ -139,7 +126,7 @@ impl MoveControl {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn strafe(&mut self, forwards: f32, right: f32) {
|
||||
pub const fn strafe(&mut self, forwards: f32, right: f32) {
|
||||
self.operation = Operation::Strafe;
|
||||
self.strafe_forwards = forwards;
|
||||
self.strafe_right = right;
|
||||
|
||||
@ -42,7 +42,7 @@ impl TrackTargetGoal {
|
||||
Self::new(check_visibility, false)
|
||||
}
|
||||
|
||||
pub fn set_unseen_memory_ticks(mut self, ticks: i32) -> Self {
|
||||
pub const fn set_unseen_memory_ticks(mut self, ticks: i32) -> Self {
|
||||
self.max_time_without_visibility = ticks;
|
||||
self
|
||||
}
|
||||
|
||||
@ -224,7 +224,7 @@ impl MobEntity {
|
||||
let dimension = &world.dimension;
|
||||
let block_light_limit = dimension.monster_spawn_block_light_limit;
|
||||
|
||||
let block_light = world.get_block_light_level(pos).unwrap();
|
||||
let block_light = world.get_block_light_level(pos).unwrap_or(0);
|
||||
if block_light_limit < 15 && block_light > block_light_limit {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -187,13 +187,12 @@ impl SlimeEntity {
|
||||
false
|
||||
}
|
||||
|
||||
fn get_spawn_chance(moon_phase: i64) -> f32 {
|
||||
const fn get_spawn_chance(moon_phase: i64) -> f32 {
|
||||
match moon_phase {
|
||||
0 => 1.0,
|
||||
1 | 7 => 0.75,
|
||||
2 | 6 => 0.5,
|
||||
3 | 5 => 0.25,
|
||||
4 => 0.0,
|
||||
_ => 0.0,
|
||||
}
|
||||
}
|
||||
@ -206,11 +205,11 @@ impl SlimeEntity {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_jump_delay(&self) -> i32 {
|
||||
fn get_jump_delay() -> i32 {
|
||||
rand::random_range(10..30)
|
||||
}
|
||||
|
||||
fn rot_lerp(&self, start: f32, end: f32, max_step: f32) -> f32 {
|
||||
fn rot_lerp(start: f32, end: f32, max_step: f32) -> f32 {
|
||||
let mut diff = (end - start).rem_euclid(360.0);
|
||||
if diff > 180.0 {
|
||||
diff -= 360.0;
|
||||
@ -363,7 +362,7 @@ impl Mob for SlimeEntity {
|
||||
pos.z + zd as f64,
|
||||
);
|
||||
let new_entity = Entity::new(world.clone(), new_pos, &EntityType::SLIME);
|
||||
let slime = SlimeEntity::new(new_entity);
|
||||
let slime = Self::new(new_entity);
|
||||
slime.set_size(half_size, true);
|
||||
slime
|
||||
.entity
|
||||
@ -383,7 +382,8 @@ pub struct SlimeMoveControl {
|
||||
}
|
||||
|
||||
impl SlimeMoveControl {
|
||||
pub fn new(slime: Weak<SlimeEntity>) -> Self {
|
||||
#[must_use]
|
||||
pub const fn new(slime: Weak<SlimeEntity>) -> Self {
|
||||
Self { slime }
|
||||
}
|
||||
}
|
||||
@ -400,7 +400,7 @@ impl MoveControlTrait for SlimeMoveControl {
|
||||
let entity = &living_entity.entity;
|
||||
|
||||
let current_yaw = entity.yaw.load();
|
||||
let new_yaw = slime.rot_lerp(current_yaw, slime.target_yaw.load(), 90.0);
|
||||
let new_yaw = SlimeEntity::rot_lerp(current_yaw, slime.target_yaw.load(), 90.0);
|
||||
entity.yaw.store(new_yaw);
|
||||
entity.head_yaw.store(new_yaw);
|
||||
entity.body_yaw.store(new_yaw);
|
||||
@ -415,7 +415,7 @@ impl MoveControlTrait for SlimeMoveControl {
|
||||
let current_delay = slime.jump_delay.load(Ordering::Relaxed);
|
||||
if current_delay <= 0 {
|
||||
// Start jump
|
||||
let mut next_delay = slime.get_jump_delay();
|
||||
let mut next_delay = SlimeEntity::get_jump_delay();
|
||||
if slime.is_aggressive.load(Ordering::Relaxed) {
|
||||
next_delay /= 3;
|
||||
}
|
||||
@ -455,7 +455,7 @@ pub struct SlimeFloatGoal {
|
||||
}
|
||||
|
||||
impl SlimeFloatGoal {
|
||||
pub fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
pub const fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
Self { slime }
|
||||
}
|
||||
}
|
||||
@ -497,7 +497,7 @@ pub struct SlimeAttackGoal {
|
||||
}
|
||||
|
||||
impl SlimeAttackGoal {
|
||||
pub fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
pub const fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
Self {
|
||||
slime,
|
||||
grow_tired_timer: 0,
|
||||
@ -558,7 +558,7 @@ pub struct SlimeRandomDirectionGoal {
|
||||
}
|
||||
|
||||
impl SlimeRandomDirectionGoal {
|
||||
pub fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
pub const fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
Self {
|
||||
slime,
|
||||
chosen_degrees: 0.0,
|
||||
@ -618,7 +618,7 @@ pub struct SlimeKeepOnJumpingGoal {
|
||||
}
|
||||
|
||||
impl SlimeKeepOnJumpingGoal {
|
||||
pub fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
pub const fn new(slime: Arc<SlimeEntity>) -> Self {
|
||||
Self { slime }
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,6 +221,24 @@ impl Server {
|
||||
}
|
||||
});
|
||||
|
||||
let dimensions = {
|
||||
let mut dimensions = vec![Dimension::OVERWORLD];
|
||||
if basic_config.allow_nether {
|
||||
dimensions.push(Dimension::THE_NETHER);
|
||||
}
|
||||
if basic_config.allow_end {
|
||||
dimensions.push(Dimension::THE_END);
|
||||
}
|
||||
dimensions
|
||||
};
|
||||
info!(
|
||||
"Enabled dimensions: {:?}",
|
||||
dimensions
|
||||
.iter()
|
||||
.map(|d| d.minecraft_name)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let server = Self {
|
||||
basic_config,
|
||||
advanced_config,
|
||||
@ -234,11 +252,7 @@ impl Server {
|
||||
recipe_manager: Arc::new(recipe::RecipeManager::new()),
|
||||
map_id: level_info.load().map_id.into(),
|
||||
worlds: ArcSwap::from_pointee(vec![]),
|
||||
dimensions: vec![
|
||||
Dimension::OVERWORLD,
|
||||
Dimension::THE_NETHER,
|
||||
Dimension::THE_END,
|
||||
],
|
||||
dimensions,
|
||||
command_dispatcher,
|
||||
block_registry: block_registry.clone(),
|
||||
item_registry: super::item::items::default_registry(),
|
||||
@ -305,18 +319,19 @@ impl Server {
|
||||
};
|
||||
|
||||
info!("Starting parallel world load...");
|
||||
let (overworld, nether, end, keys) = tokio::join!(
|
||||
world_loader(Dimension::OVERWORLD),
|
||||
world_loader(Dimension::THE_NETHER),
|
||||
world_loader(Dimension::THE_END),
|
||||
mojang_keys_task
|
||||
);
|
||||
let mut world_futures = Vec::new();
|
||||
for dim in &server.dimensions {
|
||||
world_futures.push(world_loader(dim.clone()));
|
||||
}
|
||||
|
||||
let (worlds_results, keys) =
|
||||
tokio::join!(futures::future::join_all(world_futures), mojang_keys_task);
|
||||
|
||||
let mut worlds_vec = Vec::new();
|
||||
for world_result in worlds_results {
|
||||
worlds_vec.push(world_result.expect("World loading panicked"));
|
||||
}
|
||||
|
||||
let worlds_vec = vec![
|
||||
overworld.expect("Overworld panicked"),
|
||||
nether.expect("Nether panicked"),
|
||||
end.expect("End panicked"),
|
||||
];
|
||||
server.worlds.store(Arc::new(worlds_vec));
|
||||
if let Ok(k) = keys {
|
||||
server.mojang_public_keys.store(Arc::new(k));
|
||||
@ -354,18 +369,18 @@ impl Server {
|
||||
}
|
||||
|
||||
pub fn get_world_from_dimension(&self, dimension: &Dimension) -> Arc<World> {
|
||||
// TODO: this is really bad
|
||||
let world_guard = self.worlds.load();
|
||||
|
||||
if dimension == &Dimension::OVERWORLD {
|
||||
world_guard.first()
|
||||
} else if dimension == &Dimension::THE_NETHER {
|
||||
world_guard.get(1)
|
||||
} else {
|
||||
world_guard.get(2)
|
||||
}
|
||||
.cloned()
|
||||
.unwrap()
|
||||
self.worlds
|
||||
.load()
|
||||
.iter()
|
||||
.find(|w| w.dimension.minecraft_name == dimension.minecraft_name)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
self.worlds
|
||||
.load()
|
||||
.first()
|
||||
.expect("Default world should exist")
|
||||
.clone()
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn create_world(self: &Arc<Self>, name: String, dimension: Dimension) -> Arc<World> {
|
||||
|
||||
@ -232,6 +232,45 @@ impl PartialEq for World {
|
||||
impl Eq for World {}
|
||||
|
||||
impl World {
|
||||
pub async fn get_block_state_id_async(&self, position: &BlockPos) -> BlockStateId {
|
||||
if !self.is_in_build_limit(*position) {
|
||||
return Block::AIR.default_state.id;
|
||||
}
|
||||
|
||||
let (chunk_coordinate, relative) = position.chunk_and_chunk_relative_position();
|
||||
self.level
|
||||
.get_or_fetch_chunk(chunk_coordinate, |chunk| {
|
||||
chunk
|
||||
.section
|
||||
.get_block_absolute_y(relative.x as usize, relative.y, relative.z as usize)
|
||||
.unwrap_or(Block::AIR.default_state.id)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_block_state_async(&self, position: &BlockPos) -> &'static BlockState {
|
||||
let id = self.get_block_state_id_async(position).await;
|
||||
BlockState::from_id(id)
|
||||
}
|
||||
|
||||
pub async fn get_heightmap_height_async(
|
||||
&self,
|
||||
height_map: ChunkHeightmapType,
|
||||
x: i32,
|
||||
z: i32,
|
||||
) -> i32 {
|
||||
let chunk_pos = Vector2::new(x >> 4, z >> 4);
|
||||
self.level
|
||||
.get_or_fetch_chunk(chunk_pos, |chunk| {
|
||||
chunk
|
||||
.heightmap
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get(height_map, x, z, self.min_y)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn load(
|
||||
level: Arc<Level>,
|
||||
@ -245,8 +284,8 @@ impl World {
|
||||
|
||||
// Load portal POI from disk (PoiStorage::new automatically loads from disk if files exist)
|
||||
let portal_poi = portal::PortalPoiStorage::new(&level.level_folder.root_folder);
|
||||
let dragon_fight =
|
||||
(dimension == Dimension::THE_END).then(|| Mutex::new(dragon_fight::DragonFight::new()));
|
||||
let dragon_fight = (dimension.minecraft_name == Dimension::THE_END.minecraft_name)
|
||||
.then(|| Mutex::new(dragon_fight::DragonFight::new()));
|
||||
Self {
|
||||
uuid: Uuid::new_v4(),
|
||||
level,
|
||||
|
||||
@ -12,7 +12,7 @@ use pumpkin_world::{chunk::ChunkHeightmapType, world::BlockFlags};
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
const SEARCH_RADIUS_NETHER: i32 = 16;
|
||||
const SEARCH_RADIUS_NETHER: i32 = 128;
|
||||
const SEARCH_RADIUS_OVERWORLD: i32 = 128;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -467,6 +467,11 @@ impl NetherPortal {
|
||||
world: &Arc<World>,
|
||||
target_pos: BlockPos,
|
||||
) -> Option<PortalSearchResult> {
|
||||
tracing::debug!(
|
||||
"Searching for portal in {:?} around {:?}",
|
||||
world.dimension.minecraft_name,
|
||||
target_pos
|
||||
);
|
||||
let min_y = world.min_y;
|
||||
let max_y = min_y + world.dimension.height - 1;
|
||||
let worldborder = world.worldborder.lock().await;
|
||||
@ -545,6 +550,11 @@ impl NetherPortal {
|
||||
target_pos: BlockPos,
|
||||
axis: HorizontalAxis,
|
||||
) -> Option<(BlockPos, HorizontalAxis, bool)> {
|
||||
tracing::debug!(
|
||||
"Finding safe location for portal in {:?} around {:?}",
|
||||
world.dimension.minecraft_name,
|
||||
target_pos
|
||||
);
|
||||
let min_y = world.min_y;
|
||||
let max_y = min_y + world.dimension.height - 1;
|
||||
let worldborder = world.worldborder.lock().await;
|
||||
@ -564,8 +574,8 @@ impl NetherPortal {
|
||||
let mut ideal_pos: Option<(BlockPos, HorizontalAxis, f64)> = None;
|
||||
let mut acceptable_pos: Option<(BlockPos, HorizontalAxis, f64)> = None;
|
||||
|
||||
for offset_x in -16..=16 {
|
||||
for offset_z in -16..=16 {
|
||||
for offset_x in -32..=32 {
|
||||
for offset_z in -32..=32 {
|
||||
let check_x = target_pos.0.x + offset_x;
|
||||
let check_z = target_pos.0.z + offset_z;
|
||||
|
||||
@ -579,23 +589,25 @@ impl NetherPortal {
|
||||
continue;
|
||||
}
|
||||
|
||||
let heightmap_y = world.get_heightmap_height(
|
||||
ChunkHeightmapType::MotionBlocking,
|
||||
check_x,
|
||||
check_z,
|
||||
);
|
||||
let heightmap_y = world
|
||||
.get_heightmap_height_async(
|
||||
ChunkHeightmapType::MotionBlocking,
|
||||
check_x,
|
||||
check_z,
|
||||
)
|
||||
.await;
|
||||
let start_y = heightmap_y.min(top_y_limit);
|
||||
|
||||
let mut y = start_y;
|
||||
while y >= min_y {
|
||||
let pos = BlockPos(Vector3::new(check_x, y, check_z));
|
||||
let state = world.get_block_state(&pos);
|
||||
let state = world.get_block_state_async(&pos).await;
|
||||
|
||||
if Self::is_valid_portal_air(state) {
|
||||
let mut bottom_y = y;
|
||||
while bottom_y > min_y {
|
||||
let below = BlockPos(Vector3::new(check_x, bottom_y - 1, check_z));
|
||||
let below_state = world.get_block_state(&below);
|
||||
let below_state = world.get_block_state_async(&below).await;
|
||||
if !Self::is_valid_portal_air(below_state) {
|
||||
break;
|
||||
}
|
||||
@ -607,18 +619,23 @@ impl NetherPortal {
|
||||
let floor_pos = BlockPos(Vector3::new(check_x, bottom_y, check_z));
|
||||
|
||||
for check_axis in [HorizontalAxis::X, HorizontalAxis::Z] {
|
||||
if Self::is_valid_portal_pos(world, floor_pos, check_axis, 0) {
|
||||
if Self::is_valid_portal_pos_async(world, floor_pos, check_axis, 0)
|
||||
.await
|
||||
{
|
||||
let dist = f64::from(target_pos.0.squared_distance_to(
|
||||
floor_pos.0.x,
|
||||
floor_pos.0.y,
|
||||
floor_pos.0.z,
|
||||
));
|
||||
|
||||
let is_ideal =
|
||||
Self::is_valid_portal_pos(world, floor_pos, check_axis, -1)
|
||||
&& Self::is_valid_portal_pos(
|
||||
world, floor_pos, check_axis, 1,
|
||||
);
|
||||
let is_ideal = Self::is_valid_portal_pos_async(
|
||||
world, floor_pos, check_axis, -1,
|
||||
)
|
||||
.await
|
||||
&& Self::is_valid_portal_pos_async(
|
||||
world, floor_pos, check_axis, 1,
|
||||
)
|
||||
.await;
|
||||
|
||||
if is_ideal {
|
||||
if ideal_pos.is_none()
|
||||
@ -669,7 +686,7 @@ impl NetherPortal {
|
||||
state.replaceable() && !state.is_liquid()
|
||||
}
|
||||
|
||||
fn is_valid_portal_pos(
|
||||
async fn is_valid_portal_pos_async(
|
||||
world: &Arc<World>,
|
||||
floor_pos: BlockPos,
|
||||
axis: HorizontalAxis,
|
||||
@ -693,7 +710,7 @@ impl NetherPortal {
|
||||
.offset_dir(perpendicular.to_offset(), perpendicular_offset)
|
||||
.offset_dir(BlockDirection::Up.to_offset(), height);
|
||||
|
||||
let state = world.get_block_state(&pos);
|
||||
let state = world.get_block_state_async(&pos).await;
|
||||
|
||||
if height < 0 {
|
||||
if !state.is_solid_block() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user