Pumpkin/pumpkin-world/src/biome/position_finder.rs
Alexander Medvedev ac021d5d47 chore: more work
- fixed nether again, not the dead lock or whatever it is but the server crash
- further replace Notify with CancellationToken
- fixed chunk loading on inital spawn
- more stronghold work
2026-01-21 23:08:56 +01:00

78 lines
2.3 KiB
Rust

use pumpkin_data::chunk::ParameterRange;
use pumpkin_util::math::vector2::Vector2;
pub struct FittestPositionFinderResult {
pub location: Vector2<i32>,
pub fitness: i64,
}
pub struct FittestPositionFinder;
impl FittestPositionFinder {
pub fn find_best_spawn_position(
target_noises: &[[ParameterRange; 7]],
sampler: &dyn Fn(i32, i32) -> [i64; 7],
) -> Vector2<i32> {
let mut best_result = Self::calculate_fitness(target_noises, sampler, 0, 0);
Self::find_fittest(target_noises, sampler, &mut best_result, 2048.0, 512.0);
Self::find_fittest(target_noises, sampler, &mut best_result, 512.0, 32.0);
best_result.location
}
fn find_fittest(
noises: &[[ParameterRange; 7]],
sampler: &dyn Fn(i32, i32) -> [i64; 7],
best_result: &mut FittestPositionFinderResult,
max_distance: f32,
step: f32,
) {
let mut angle = 0.0f32;
let mut distance = step;
let center = best_result.location;
while distance <= max_distance {
let x = center.x + (angle.sin() * distance) as i32;
let z = center.y + (angle.cos() * distance) as i32;
let result = Self::calculate_fitness(noises, sampler, x, z);
if result.fitness < best_result.fitness {
*best_result = result;
}
angle += step / distance;
if angle > std::f32::consts::TAU {
angle = 0.0;
distance += step;
}
}
}
fn calculate_fitness(
noises: &[[ParameterRange; 7]],
sampler: &dyn Fn(i32, i32) -> [i64; 7],
x: i32,
z: i32,
) -> FittestPositionFinderResult {
let sampled_noise = sampler(x, z);
let mut min_squared_dist = i64::MAX;
for noise_ranges in noises {
let mut current_dist = 0i64;
for i in 0..7 {
current_dist += noise_ranges[i].calc_distance(sampled_noise[i]);
}
min_squared_dist = min_squared_dist.min(current_dist);
}
let origin_dist_sq = (x as i64 * x as i64) + (z as i64 * z as i64);
let fitness = min_squared_dist * (2048 * 2048) + origin_dist_sq;
FittestPositionFinderResult {
location: Vector2::new(x, z),
fitness,
}
}
}