alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates common src random.rs
const MULTIPLIER: i64 = 0x5_DEEC_E66D;
const ADDEND: i64 = 0xB;
const MASK: i64 = (1 << 48) - 1;
/// Port of `java.util.Random`, producing identical sequences for identical seeds.
#[derive(Clone, Debug)]
pub struct JavaRandom {
seed: i64,
next_gaussian: Option<f64>,
}
impl Default for JavaRandom {
fn default() -> Self {
Self::new(0)
}
}
impl JavaRandom {
pub fn new(seed: i64) -> Self {
Self {
seed: (seed ^ MULTIPLIER) & MASK,
next_gaussian: None,
}
}
pub fn set_seed(&mut self, seed: i64) {
*self = Self::new(seed);
}
fn next(&mut self, bits: u32) -> i32 {
self.seed = self.seed.wrapping_mul(MULTIPLIER).wrapping_add(ADDEND) & MASK;
(self.seed >> (48 - bits)) as i32
}
/// Uniform in `0..bound`. Panics if `bound <= 0`, like Java's `IllegalArgumentException`.
pub fn next_int(&mut self, bound: i32) -> i32 {
assert!(bound > 0, "bound must be positive");
if bound & -bound == bound {
return ((i64::from(bound) * i64::from(self.next(31))) >> 31) as i32;
}
loop {
let bits = self.next(31);
let value = bits % bound;
if bits.wrapping_sub(value).wrapping_add(bound - 1) >= 0 {
return value;
}
}
}
pub fn next_i32(&mut self) -> i32 {
self.next(32)
}
pub fn next_long(&mut self) -> i64 {
let high = i64::from(self.next(32)) << 32;
high.wrapping_add(i64::from(self.next(32)))
}
pub fn next_bool(&mut self) -> bool {
self.next(1) != 0
}
pub fn next_float(&mut self) -> f32 {
self.next(24) as f32 / (1 << 24) as f32
}
pub fn next_double(&mut self) -> f64 {
let high = i64::from(self.next(26)) << 27;
(high + i64::from(self.next(27))) as f64 * (1.0 / (1_i64 << 53) as f64)
}
/// `nextGaussian`: the polar method, which yields values in pairs.
pub fn next_gaussian(&mut self) -> f64 {
if let Some(value) = self.next_gaussian.take() {
return value;
}
loop {
let v1 = 2.0 * self.next_double() - 1.0;
let v2 = 2.0 * self.next_double() - 1.0;
let s = v1 * v1 + v2 * v2;
if s < 1.0 && s != 0.0 {
let multiplier = (-2.0 * s.ln() / s).sqrt();
self.next_gaussian = Some(v2 * multiplier);
return v1 * multiplier;
}
}
}
}