1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
mod math;

use crate::simplex_noise::SimplexNoise;
use crate::voronoi::get_fuzzy_positions;
use java_random::{Random, END_LCG};
mod voronoi;
mod simplex_noise;



#[derive(Copy, Clone)]
pub struct EndGen {
    seed: u64,
    x: i32,
    z: i32,
    noise: SimplexNoise,
}

pub enum EndBiomes {
    TheEnd,
    EndHighlands,
    EndMidlands,
    SmallEndIslands,
    EndBarrens,
}

impl EndGen {
    pub fn new(seed: u64, x: i32, z: i32) -> Self {
        let seed: u64 = Random::with_seed_and_lcg(seed, END_LCG).next_state().get_raw_seed();
        let noise: SimplexNoise = SimplexNoise::init(Random::with_raw_seed(seed));
        EndGen { seed, x, z, noise }
    }

    pub fn get_final_biome(&mut self, x: i32, z: i32) -> EndBiomes {
        let (xx, _, zz): (i32, i32, i32) = get_fuzzy_positions(self.seed as i64, x, 0, z);
        return self.get_biome(xx, zz);
    }
    pub fn get_biome(&mut self, x: i32, z: i32) -> EndBiomes {
        let chunk_x: i32 = x >> 2;
        let chunk_z: i32 = z >> 2;
        if chunk_x as i64 * chunk_x as i64 + chunk_z as i64 * chunk_z as i64 <= 4096i64 {
            return EndBiomes::TheEnd;
        }
        let height: f32 = Self::get_height(self.noise, chunk_x * 2 + 1, chunk_z * 2 + 1);
        if height > 40.0f32 {
            return EndBiomes::EndHighlands;
        }
        if height >= 0.0f32 {
            return EndBiomes::EndMidlands;
        }
        if height < -20.0f32 {
            return EndBiomes::SmallEndIslands;
        }
        return EndBiomes::EndBarrens;
    }
    pub fn get_height(noise: SimplexNoise, x: i32, z: i32) -> f32 {
        let scaled_x: i32 = x / 2;
        let scaled_z: i32 = z / 2;
        let odd_x: i32 = x % 2;
        let odd_z: i32 = z % 2;
        let mut height: f32 = math::clamp(100.0f32 - math::sqrt((x * x + z * z) as f32) * 8.0f32, -100.0f32, 80.0f32);
        for rx in -12..=12 {
            for rz in -12..=12 {
                let shifted_x: i64 = (scaled_x + rx) as i64;
                let shifted_z: i64 = (scaled_z + rz) as i64;
                if shifted_x * shifted_x + shifted_z * shifted_z <= 4096i64 || !(noise.get_value_2d(shifted_x as f64, shifted_z as f64) < -0.8999999761581421) {
                    continue;
                }
                let elevation: f32 = (math::abs(shifted_x as f32) * 3439.0f32 + math::abs(shifted_z as f32) * 147.0f32) % 13.0f32 + 9.0f32;
                let smooth_x: f32 = (odd_x - rx * 2) as f32;
                let smooth_z: f32 = (odd_z - rz * 2) as f32;
                height = math::max(height, math::clamp(100.0f32 - math::sqrt(smooth_x * smooth_x + smooth_z * smooth_z) * elevation, -100.0f32, 80.0f32));
            }
        }
        return height;
    }
    pub fn set_seed(&mut self, seed: u64) {
        let mut random: Random = Random::with_seed_and_lcg(seed, END_LCG);
        self.seed = random.next_state().get_raw_seed()
    }

    pub fn set_position(&mut self, x: i32, z: i32) {
        self.x = x;
        self.z = z;
    }
    pub fn set_x(&mut self, x: i32) {
        self.x = x;
    }
    pub fn set_z(&mut self, z: i32) {
        self.z = z;
    }
}