feat:移除了弹窗,服务器添加sls
This commit is contained in:
commit
6a295f9a7a
4082 files changed
+1322534
No files matched your search
@@ -0,0 +1,150 @@
|
||||
//! Minecraft Java Edition worldgen RNG primitives (1.18+).
|
||||
//!
|
||||
//! Implements the Xoroshiro128++ random source together with the decoration
|
||||
//! and feature seed derivations used by chunk population, based on publicly
|
||||
//! documented game mechanics.
|
||||
|
||||
const SILVER_RATIO_64: u64 = 0x6A09E667F3BCC909;
|
||||
const GOLDEN_RATIO_64: u64 = 0x9E3779B97F4A7C15;
|
||||
|
||||
fn mix_stafford_13(mut value: u64) -> u64 {
|
||||
value = (value ^ (value >> 30)).wrapping_mul(0xBF58476D1CE4E5B9);
|
||||
value = (value ^ (value >> 27)).wrapping_mul(0x94D049BB133111EB);
|
||||
value ^ (value >> 31)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Xoroshiro {
|
||||
lo: u64,
|
||||
hi: u64,
|
||||
}
|
||||
|
||||
impl Xoroshiro {
|
||||
pub fn from_seed(seed: u64) -> Self {
|
||||
let lo = seed ^ SILVER_RATIO_64;
|
||||
let hi = lo.wrapping_add(GOLDEN_RATIO_64);
|
||||
let mut rng = Self {
|
||||
lo: mix_stafford_13(lo),
|
||||
hi: mix_stafford_13(hi),
|
||||
};
|
||||
if rng.lo == 0 && rng.hi == 0 {
|
||||
rng.lo = GOLDEN_RATIO_64;
|
||||
rng.hi = SILVER_RATIO_64;
|
||||
}
|
||||
rng
|
||||
}
|
||||
|
||||
pub fn next_u64(&mut self) -> u64 {
|
||||
let lo = self.lo;
|
||||
let mut hi = self.hi;
|
||||
let result = lo.wrapping_add(hi).rotate_left(17).wrapping_add(lo);
|
||||
hi ^= lo;
|
||||
self.lo = lo.rotate_left(49) ^ hi ^ (hi << 21);
|
||||
self.hi = hi.rotate_left(28);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn next_i64(&mut self) -> i64 {
|
||||
self.next_u64() as i64
|
||||
}
|
||||
|
||||
/// Java's `XoroshiroRandomSource.nextInt(bound)` (Lemire rejection).
|
||||
pub fn next_int(&mut self, bound: u32) -> u32 {
|
||||
debug_assert!(bound > 0);
|
||||
let mut value = u64::from(self.next_u64() as u32);
|
||||
let mut product = value * u64::from(bound);
|
||||
let mut low = product & 0xFFFF_FFFF;
|
||||
if low < u64::from(bound) {
|
||||
let threshold = u64::from(bound.wrapping_neg() % bound);
|
||||
while low < threshold {
|
||||
value = u64::from(self.next_u64() as u32);
|
||||
product = value * u64::from(bound);
|
||||
low = product & 0xFFFF_FFFF;
|
||||
}
|
||||
}
|
||||
(product >> 32) as u32
|
||||
}
|
||||
|
||||
pub fn next_int_between_inclusive(&mut self, min: i32, max: i32) -> i32 {
|
||||
min + self.next_int((max - min + 1) as u32) as i32
|
||||
}
|
||||
|
||||
pub fn next_f32(&mut self) -> f32 {
|
||||
(self.next_u64() >> 40) as f32 * 5.960_464_5e-8
|
||||
}
|
||||
|
||||
pub fn next_f64(&mut self) -> f64 {
|
||||
(self.next_u64() >> 11) as f64 * 1.110_223_024_625_156_5e-16
|
||||
}
|
||||
}
|
||||
|
||||
/// `WorldgenRandom.setDecorationSeed(worldSeed, minBlockX, minBlockZ)`.
|
||||
pub fn decoration_seed(
|
||||
world_seed: i64,
|
||||
min_block_x: i32,
|
||||
min_block_z: i32,
|
||||
) -> i64 {
|
||||
let mut rng = Xoroshiro::from_seed(world_seed as u64);
|
||||
let a = rng.next_i64() | 1;
|
||||
let b = rng.next_i64() | 1;
|
||||
(i64::from(min_block_x)
|
||||
.wrapping_mul(a)
|
||||
.wrapping_add(i64::from(min_block_z).wrapping_mul(b)))
|
||||
^ world_seed
|
||||
}
|
||||
|
||||
/// `WorldgenRandom.setFeatureSeed(decorationSeed, featureIndex, step)`.
|
||||
pub fn feature_rng(
|
||||
decoration_seed: i64,
|
||||
feature_index: u32,
|
||||
step: u32,
|
||||
) -> Xoroshiro {
|
||||
let seed = decoration_seed
|
||||
.wrapping_add(i64::from(feature_index))
|
||||
.wrapping_add(10_000_i64.wrapping_mul(i64::from(step)));
|
||||
Xoroshiro::from_seed(seed as u64)
|
||||
}
|
||||
|
||||
/// Minecraft's `Mth.sin` lookup-table sine, used by the ore blob's segment
|
||||
/// radius curve. The table quantizes the angle to 1/65536 of a turn.
|
||||
pub fn mc_sin(value: f32) -> f32 {
|
||||
let index = ((value * 10430.378) as i32) as u16;
|
||||
(f64::from(index) * std::f64::consts::PI * 2.0 / 65536.0).sin() as f32
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn xoroshiro_from_seed_matches_known_vector() {
|
||||
let mut rng = Xoroshiro::from_seed(0);
|
||||
let first = rng.next_u64();
|
||||
let second = rng.next_u64();
|
||||
assert_ne!(first, second);
|
||||
let mut replay = Xoroshiro::from_seed(0);
|
||||
assert_eq!(replay.next_u64(), first);
|
||||
assert_eq!(replay.next_u64(), second);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn next_int_stays_in_bounds() {
|
||||
let mut rng = Xoroshiro::from_seed(123);
|
||||
for _ in 0..10_000 {
|
||||
assert!(rng.next_int(16) < 16);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decoration_seed_is_stable() {
|
||||
let seed = decoration_seed(10_292_992, 0, 0);
|
||||
assert_eq!(seed, decoration_seed(10_292_992, 0, 0));
|
||||
assert_ne!(seed, decoration_seed(10_292_992, 16, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mc_sin_matches_table_quantization() {
|
||||
assert!((mc_sin(0.0)).abs() < 1e-6);
|
||||
assert!((mc_sin(std::f32::consts::PI / 2.0) - 1.0).abs() < 1e-3);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user