bones_framework/networking/
random.rs1use crate::prelude::*;
4#[cfg(feature = "scripting")]
5use crate::{
6 prelude::bindings::EcsRef,
7 scripting::lua::{
8 bindings::SchemaLuaEcsRefMetatable,
9 piccolo::{self as lua, Callback},
10 },
11};
12use core::ops::RangeBounds;
13use std::collections::VecDeque;
14use turborand::prelude::*;
15
16#[derive(Clone, HasSchema)]
20#[type_data(SchemaLuaEcsRefMetatable(lua_metatable))]
21pub struct RngGenerator {
22 internal_generator: AtomicRng,
23}
24
25impl Default for RngGenerator {
26 fn default() -> Self {
28 Self {
29 internal_generator: AtomicRng::with_seed(7),
30 }
31 }
32}
33
34impl RngGenerator {
35 pub fn new(seed: u64) -> Self {
37 Self {
38 internal_generator: AtomicRng::with_seed(seed),
39 }
40 }
41
42 pub fn gen_u8(&mut self) -> u8 {
44 self.internal_generator.gen_u8()
45 }
46
47 pub fn gen_u8_range<R: RangeBounds<u8>>(&mut self, range: R) -> u8 {
49 self.internal_generator.u8(range)
50 }
51
52 pub fn gen_i8(&mut self) -> i8 {
54 self.internal_generator.gen_i8()
55 }
56
57 pub fn gen_i8_range<R: RangeBounds<i8>>(&mut self, range: R) -> i8 {
59 self.internal_generator.i8(range)
60 }
61
62 pub fn gen_u16(&mut self) -> u16 {
64 self.internal_generator.gen_u16()
65 }
66
67 pub fn gen_u16_range<R: RangeBounds<u16>>(&mut self, range: R) -> u16 {
69 self.internal_generator.u16(range)
70 }
71
72 pub fn gen_i16(&mut self) -> i16 {
74 self.internal_generator.gen_i16()
75 }
76
77 pub fn gen_i16_range<R: RangeBounds<i16>>(&mut self, range: R) -> i16 {
79 self.internal_generator.i16(range)
80 }
81
82 pub fn gen_u32(&mut self) -> u32 {
84 self.internal_generator.gen_u32()
85 }
86
87 pub fn gen_u32_range<R: RangeBounds<u32>>(&mut self, range: R) -> u32 {
89 self.internal_generator.u32(range)
90 }
91
92 pub fn gen_i32(&mut self) -> i32 {
94 self.internal_generator.gen_i32()
95 }
96
97 pub fn gen_i32_range<R: RangeBounds<i32>>(&mut self, range: R) -> i32 {
99 self.internal_generator.i32(range)
100 }
101
102 pub fn gen_u64(&mut self) -> u64 {
104 self.internal_generator.gen_u64()
105 }
106
107 pub fn gen_u64_range<R: RangeBounds<u64>>(&mut self, range: R) -> u64 {
109 self.internal_generator.u64(range)
110 }
111
112 pub fn gen_i64(&mut self) -> i64 {
114 self.internal_generator.gen_i64()
115 }
116
117 pub fn gen_i64_range<R: RangeBounds<i64>>(&mut self, range: R) -> i64 {
119 self.internal_generator.i64(range)
120 }
121
122 pub fn gen_usize(&mut self) -> usize {
124 self.internal_generator.gen_usize()
125 }
126
127 pub fn gen_usize_range<R: RangeBounds<usize>>(&mut self, range: R) -> usize {
129 self.internal_generator.usize(range)
130 }
131
132 pub fn gen_isize(&mut self) -> isize {
134 self.internal_generator.gen_isize()
135 }
136
137 pub fn gen_isize_range<R: RangeBounds<isize>>(&mut self, range: R) -> isize {
139 self.internal_generator.isize(range)
140 }
141
142 pub fn gen_f32(&mut self) -> f32 {
144 self.internal_generator.f32()
145 }
146
147 pub fn gen_f32_range<R: RangeBounds<f32>>(&mut self, range: R) -> f32 {
149 let start = match range.start_bound() {
150 std::ops::Bound::Included(&n) => n,
151 std::ops::Bound::Excluded(&n) => n,
152 std::ops::Bound::Unbounded => 0.0,
153 };
154 let end = match range.end_bound() {
155 std::ops::Bound::Included(&n) => n,
156 std::ops::Bound::Excluded(&n) => n,
157 std::ops::Bound::Unbounded => 1.0,
158 };
159 loop {
160 let n = self.gen_f32();
161 if n >= start && n <= end {
162 return n;
163 }
164 }
165 }
166
167 pub fn gen_f64(&mut self) -> f64 {
169 self.internal_generator.f64()
170 }
171
172 pub fn gen_f64_range<R: RangeBounds<f64>>(&mut self, range: R) -> f64 {
174 let start = match range.start_bound() {
175 std::ops::Bound::Included(&n) => n,
176 std::ops::Bound::Excluded(&n) => n,
177 std::ops::Bound::Unbounded => 0.0,
178 };
179 let end = match range.end_bound() {
180 std::ops::Bound::Included(&n) => n,
181 std::ops::Bound::Excluded(&n) => n,
182 std::ops::Bound::Unbounded => 1.0,
183 };
184 loop {
185 let n = self.gen_f64();
186 if n >= start && n <= end {
187 return n;
188 }
189 }
190 }
191
192 pub fn gen_bool(&mut self) -> bool {
194 self.internal_generator.bool()
195 }
196
197 pub fn gen_vec2(&mut self) -> Vec2 {
199 Vec2::new(self.gen_f32(), self.gen_f32())
200 }
201
202 pub fn gen_vec2_range<R1: RangeBounds<f32>, R2: RangeBounds<f32>>(
204 &mut self,
205 x_range: R1,
206 y_range: R2,
207 ) -> Vec2 {
208 Vec2::new(self.gen_f32_range(x_range), self.gen_f32_range(y_range))
209 }
210
211 pub fn gen_vec3(&mut self) -> Vec3 {
213 Vec3::new(self.gen_f32(), self.gen_f32(), self.gen_f32())
214 }
215
216 pub fn gen_vec3_range<R1: RangeBounds<f32>, R2: RangeBounds<f32>, R3: RangeBounds<f32>>(
218 &mut self,
219 x_range: R1,
220 y_range: R2,
221 z_range: R3,
222 ) -> Vec3 {
223 Vec3::new(
224 self.gen_f32_range(x_range),
225 self.gen_f32_range(y_range),
226 self.gen_f32_range(z_range),
227 )
228 }
229
230 pub fn shuffle_vec<T>(&mut self, vec: &mut [T]) {
232 self.internal_generator.shuffle(vec);
233 }
234
235 pub fn shuffle_svec<T: HasSchema>(&mut self, svec: &mut SVec<T>) {
237 for i in (1..svec.len()).rev() {
238 let j = self.gen_usize_range(0..=i);
239 svec.swap(i, j);
240 }
241 }
242
243 pub fn shuffle_vecdeque<T>(&mut self, deque: &mut VecDeque<T>) {
245 let len = deque.len();
246 for i in (1..len).rev() {
247 let j = self.gen_usize_range(0..=i);
248 deque.swap(i, j);
249 }
250 }
251
252 pub fn gen_alphabetic(&mut self) -> char {
254 self.internal_generator.alphabetic()
255 }
256
257 pub fn gen_alphanumeric(&mut self) -> char {
259 self.internal_generator.alphanumeric()
260 }
261
262 pub fn gen_lowercase(&mut self) -> char {
264 self.internal_generator.lowercase()
265 }
266
267 pub fn gen_uppercase(&mut self) -> char {
269 self.internal_generator.uppercase()
270 }
271
272 pub fn gen_digit(&mut self, radix: u8) -> char {
278 self.internal_generator.digit(radix)
279 }
280
281 pub fn gen_char<R: RangeBounds<char>>(&mut self, bounds: R) -> char {
286 self.internal_generator.char(bounds)
287 }
288
289 pub fn gen_random_ascii_char(&mut self) -> char {
291 self.gen_u8_range(33..=126) as char
292 }
293
294 pub fn gen_random_ascii_string(&mut self, length: u64) -> String {
296 (0..length).map(|_| self.gen_random_ascii_char()).collect()
297 }
298
299 pub fn gen_chance(&mut self, success_rate: f64) -> bool {
302 let clamped_rate = success_rate.clamp(0.0, 1.0);
303 self.internal_generator.chance(clamped_rate)
304 }
305
306 pub fn gen_sample<'a, T>(&mut self, list: &'a [T]) -> Option<&'a T> {
308 self.internal_generator.sample(list)
309 }
310
311 pub fn gen_sample_iter<T: Iterator>(&mut self, list: T) -> Option<T::Item> {
313 self.internal_generator.sample_iter(list)
314 }
315
316 pub fn gen_sample_mut<'a, T>(&mut self, list: &'a mut [T]) -> Option<&'a mut T> {
318 self.internal_generator.sample_mut(list)
319 }
320
321 pub fn gen_sample_multiple<'a, T>(&mut self, list: &'a [T], amount: usize) -> Vec<&'a T> {
323 self.internal_generator.sample_multiple(list, amount)
324 }
325
326 pub fn gen_sample_multiple_mut<'a, T>(
328 &mut self,
329 list: &'a mut [T],
330 amount: usize,
331 ) -> Vec<&'a mut T> {
332 self.internal_generator.sample_multiple_mut(list, amount)
333 }
334
335 pub fn gen_sample_multiple_iter<T: Iterator>(
337 &mut self,
338 list: T,
339 amount: usize,
340 ) -> Vec<T::Item> {
341 self.internal_generator.sample_multiple_iter(list, amount)
342 }
343
344 pub fn gen_weighted_sample<'a, T, F>(
346 &mut self,
347 list: &'a [T],
348 weight_sampler: F,
349 ) -> Option<&'a T>
350 where
351 F: Fn((&T, usize)) -> f64,
352 {
353 self.internal_generator
354 .weighted_sample(list, weight_sampler)
355 }
356
357 pub fn gen_weighted_sample_mut<'a, T, F>(
359 &mut self,
360 list: &'a mut [T],
361 weight_sampler: F,
362 ) -> Option<&'a mut T>
363 where
364 F: Fn((&T, usize)) -> f64,
365 {
366 self.internal_generator
367 .weighted_sample_mut(list, weight_sampler)
368 }
369}
370
371#[cfg(feature = "scripting")]
372fn lua_metatable(ctx: lua::Context) -> lua::Table {
373 let metatable = lua::Table::new(&ctx);
374
375 let f32_fn = ctx.registry().stash(
376 &ctx,
377 Callback::from_fn(&ctx, |ctx, _fuel, mut stack| {
378 let this: &EcsRef = stack.consume(ctx)?;
379 let mut b = this.borrow_mut();
380 let rng_generator = b.schema_ref_mut()?.cast_into_mut::<RngGenerator>();
381 let n = rng_generator.internal_generator.f32();
382 stack.replace(ctx, n);
383 Ok(lua::CallbackReturn::Return)
384 }),
385 );
386 metatable
387 .set(
388 ctx,
389 "__index",
390 Callback::from_fn(&ctx, move |ctx, _fuel, mut stack| {
391 let (_this, key): (lua::Value, lua::String) = stack.consume(ctx)?;
392
393 #[allow(clippy::single_match)]
394 match key.as_bytes() {
395 b"f32" => {
396 stack.push_front(ctx.registry().fetch(&f32_fn).into());
397 }
398 _ => (),
399 }
400 Ok(lua::CallbackReturn::Return)
401 }),
402 )
403 .unwrap();
404
405 metatable
406}