mc_core/rand/
java.rs

1use std::sync::atomic::{AtomicI64, Ordering};
2use std::time::{UNIX_EPOCH, SystemTime};
3use std::num::Wrapping;
4use uuid::Uuid;
5
6
7const MULTIPLIER: Wrapping<i64> = Wrapping(0x5DEECE66D);
8const ADDEND: Wrapping<i64> = Wrapping(0xB);
9const MASK: Wrapping<i64> = Wrapping((1 << 48) - 1);
10
11const FLOAT_DIV: f32 = (1u32 << 24) as f32;
12const DOUBLE_DIV: f64 = (1u64 << 53) as f64;
13
14
15#[inline]
16pub fn initial_scramble(seed: i64) -> Wrapping<i64> {
17    (Wrapping(seed) ^ MULTIPLIER) & MASK
18}
19
20
21/// Generate a new seed in the same way as `java.f.Random` (same constants).
22pub fn gen_seed() -> i64 {
23    static SEED: AtomicI64 = AtomicI64::new(8682522807148012);
24    let mut current = SEED.load(Ordering::Relaxed);
25    loop {
26        let next = current.wrapping_mul(181783497276652981);
27        match SEED.compare_exchange_weak(current, next, Ordering::Relaxed, Ordering::Relaxed) {
28            Ok(_) => {
29                // This is a bit different from Java implementation because the nano time
30                // as an integer value is not available in Rust, even with Instant.
31                // So we're using duration since unix epoch of the system time, maybe not
32                // as safe as the Java implementation.
33                return match SystemTime::now().duration_since(UNIX_EPOCH) {
34                    Ok(d) => next ^ (d.as_nanos() as i64),
35                    Err(_) => next
36                };
37            }
38            Err(old) => current = old
39        }
40    }
41}
42
43#[derive(Debug, Clone)]
44pub struct JavaRandom {
45    seed: Wrapping<i64>
46}
47
48impl JavaRandom {
49
50    #[inline]
51    pub fn new(seed: i64) -> JavaRandom {
52        JavaRandom { seed: initial_scramble(seed) }
53    }
54
55    #[inline]
56    pub fn new_seeded() -> JavaRandom {
57        Self::new(gen_seed())
58    }
59
60    #[inline]
61    pub fn new_blank() -> JavaRandom {
62        JavaRandom { seed: Wrapping(0) }
63    }
64
65    #[inline]
66    pub fn set_seed(&mut self, seed: i64) {
67        self.seed = initial_scramble(seed);
68    }
69
70    #[inline]
71    pub fn get_seed(&self) -> i64 {
72        self.seed.0
73    }
74
75    pub fn next_blank(&mut self) {
76        self.seed = (self.seed * MULTIPLIER + ADDEND) & MASK;
77    }
78
79    #[inline]
80    fn next(&mut self, bits: u8) -> i32 {
81        self.next_blank();
82        (self.seed.0 as u64 >> (48 - bits)) as i32
83    }
84
85    #[inline]
86    pub fn next_int(&mut self) -> i32 {
87        self.next(32)
88    }
89
90    pub fn next_int_bounded(&mut self, bound: i32) -> i32 {
91
92        if (bound & -bound) == bound {
93            (((bound as i64).wrapping_mul(self.next(31) as i64)) >> 31) as i32
94        } else {
95
96            let mut bits;
97            let mut val;
98
99            loop {
100                bits = self.next(31);
101                val = bits.rem_euclid(bound);
102                if bits - val + (bound - 1) >= 0 {
103                    break;
104                }
105            }
106
107            val
108
109        }
110
111    }
112
113    pub fn next_long(&mut self) -> i64 {
114        ((self.next(32) as i64) << 32).wrapping_add(self.next(32) as i64)
115    }
116
117    pub fn next_float(&mut self) -> f32 {
118        self.next(24) as f32 / FLOAT_DIV
119    }
120
121    pub fn next_double(&mut self) -> f64 {
122        let high = (self.next(26) as i64) << 27;
123        let low = self.next(27) as i64;
124        (high.wrapping_add(low) as f64) / DOUBLE_DIV
125    }
126
127    pub fn next_insecure_uuid(&mut self) -> Uuid {
128        let most = (self.next_long() & -61441) | 16384;
129        let least = (self.next_long() & 4611686018427387903) | i64::MIN;
130        Uuid::from_u128((most as u128) << 64 | (least as u128))
131    }
132
133}