From 359d3e4780f277418bdf061dd5fc78bbda6e715f Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sun, 1 Sep 2019 21:03:50 -0600 Subject: [PATCH] Propagate the RNG to the action context. This lets random work. --- core/src/avm1.rs | 7 +++---- core/src/avm1/globals.rs | 8 ++++++-- core/src/avm1/globals/math.rs | 7 +++++-- core/src/player.rs | 27 +++++++++++++++++++++------ 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 1a84d786e..6a268b462 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -21,6 +21,7 @@ pub struct ActionContext<'a, 'gc, 'gc_context> { pub root: DisplayNode<'gc>, pub start_clip: DisplayNode<'gc>, pub active_clip: DisplayNode<'gc>, + pub rng: &'a mut SmallRng, pub audio: &'a mut dyn crate::backend::audio::AudioBackend, pub navigator: &'a mut dyn crate::backend::navigator::NavigatorBackend } @@ -28,7 +29,6 @@ pub struct ActionContext<'a, 'gc, 'gc_context> { pub struct Avm1<'gc> { swf_version: u8, stack: Vec>, - rng: SmallRng, constant_pool: Vec, locals: HashMap>, globals: GcCell<'gc, Object<'gc>>, @@ -50,7 +50,6 @@ impl<'gc> Avm1<'gc> { Self { swf_version, stack: vec![], - rng: SmallRng::from_seed([0u8; 16]), // TODO(Herschel): Get a proper seed on all platforms. constant_pool: vec![], locals: HashMap::new(), globals: GcCell::allocate(gc_context, create_globals(gc_context)), @@ -912,9 +911,9 @@ impl<'gc> Avm1<'gc> { Ok(()) } - fn action_random_number(&mut self, _context: &mut ActionContext) -> Result<(), Error> { + fn action_random_number(&mut self, context: &mut ActionContext) -> Result<(), Error> { let max = self.pop()?.as_f64()? as u32; - let val = self.rng.gen_range(0, max); + let val = context.rng.gen_range(0, max); self.push(Value::Number(val.into())); Ok(()) } diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index f155e848d..06f4f47d7 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -1,5 +1,6 @@ use crate::avm1::{Object, Value, ActionContext}; use gc_arena::{MutationContext, GcCell}; +use rand::Rng; mod math; @@ -27,11 +28,14 @@ pub fn getURL<'a, 'gc>( } pub fn random<'gc>( - _action_context: &mut ActionContext<'_, 'gc, '_>, + action_context: &mut ActionContext<'_, 'gc, '_>, _this: GcCell<'gc, Object<'gc>>, args: &[Value<'gc>], ) -> Value<'gc> { - Value::Number(4.0) //chosen by fair dice roll. guaranteed to be random. + match args.get(0) { + Some(Value::Number(max)) => Value::Number(action_context.rng.gen_range(0.0f64, max).floor()), + _ => Value::Undefined //TODO: Shouldn't this be an error condition? + } } pub fn create_globals<'gc>(gc_context: MutationContext<'gc, '_>) -> Object<'gc> { diff --git a/core/src/avm1/globals/math.rs b/core/src/avm1/globals/math.rs index 71601b64b..cb46fcd07 100644 --- a/core/src/avm1/globals/math.rs +++ b/core/src/avm1/globals/math.rs @@ -1,6 +1,7 @@ use crate::avm1::{ActionContext, Object, Value}; use gc_arena::{GcCell, MutationContext}; use std::f64::NAN; +use rand::Rng; macro_rules! wrap_std { ( $object: ident, $gc_context: ident, $($name:expr => $std:path),* ) => {{ @@ -36,11 +37,11 @@ fn atan2<'gc>( } pub fn random<'gc>( - _action_context: &mut ActionContext<'_, 'gc, '_>, + action_context: &mut ActionContext<'_, 'gc, '_>, _this: GcCell<'gc, Object<'gc>>, _args: &[Value<'gc>], ) -> Value<'gc> { - Value::Number(0.4) //chosen by fair dice roll. guaranteed to be random. + Value::Number(action_context.rng.gen_range(0.0f64, 1.0f64)) } pub fn create<'gc>(gc_context: MutationContext<'gc, '_>) -> GcCell<'gc, Object<'gc>> { @@ -87,6 +88,7 @@ mod tests { use crate::display_object::DisplayObject; use crate::movie_clip::MovieClip; use gc_arena::rootless_arena; + use rand::{rngs::SmallRng, SeedableRng}; macro_rules! test_std { ( $test: ident, $name: expr, $($args: expr => $out: expr),* ) => { @@ -119,6 +121,7 @@ mod tests { root, start_clip: root, active_clip: root, + rng: &mut SmallRng::from_seed([0u8; 16]), audio: &mut NullAudioBackend::new(), navigator: &mut NullNavigatorBackend::new() }; diff --git a/core/src/player.rs b/core/src/player.rs index fd729b84a..02624e321 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -5,6 +5,7 @@ use crate::library::Library; use crate::movie_clip::MovieClip; use crate::prelude::*; use crate::transform::TransformStack; +use rand::{rngs::SmallRng, SeedableRng}; use gc_arena::{make_arena, ArenaParameters, Collect, GcCell, MutationContext}; use log::info; use std::sync::Arc; @@ -33,6 +34,8 @@ pub struct Player view_matrix: Default::default(), inverse_view_matrix: Default::default(), + rng: SmallRng::from_seed([0u8; 16]), // TODO(Herschel): Get a proper seed on all platforms. + gc_arena: GcArena::new(ArenaParameters::default(), |gc_context| GcRoot { library: GcCell::allocate(gc_context, Library::new()), root: GcCell::allocate( @@ -205,7 +210,7 @@ impl } } - let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator, is_mouse_down) = ( + let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator, rng, is_mouse_down) = ( self.global_time, &mut self.swf_data, self.swf_version, @@ -213,6 +218,7 @@ impl &mut self.renderer, &mut self.audio, &mut self.navigator, + &mut self.rng, &mut self.is_mouse_down, ); @@ -224,6 +230,7 @@ impl library: gc_root.library.write(gc_context), background_color, avm: gc_root.avm.write(gc_context), + rng, renderer, audio, navigator, @@ -269,14 +276,15 @@ impl return false; } - let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator) = ( + let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator, rng) = ( self.global_time, &mut self.swf_data, self.swf_version, &mut self.background_color, &mut self.renderer, &mut self.audio, - &mut self.navigator + &mut self.navigator, + &mut self.rng ); let mouse_pos = &self.mouse_pos; @@ -295,6 +303,7 @@ impl library: gc_root.library.write(gc_context), background_color, avm: gc_root.avm.write(gc_context), + rng, renderer, audio, navigator, @@ -330,7 +339,7 @@ impl } fn preload(&mut self) { - let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator) = ( + let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator, rng) = ( self.global_time, &mut self.swf_data, self.swf_version, @@ -338,6 +347,7 @@ impl &mut self.renderer, &mut self.audio, &mut self.navigator, + &mut self.rng ); self.gc_arena.mutate(|gc_context, gc_root| { @@ -348,6 +358,7 @@ impl library: gc_root.library.write(gc_context), background_color, avm: gc_root.avm.write(gc_context), + rng, renderer, audio, navigator, @@ -376,14 +387,15 @@ impl } pub fn run_frame(&mut self) { - let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator) = ( + let (global_time, swf_data, swf_version, background_color, renderer, audio, navigator, rng) = ( self.global_time, &mut self.swf_data, self.swf_version, &mut self.background_color, &mut self.renderer, &mut self.audio, - &mut self.navigator + &mut self.navigator, + &mut self.rng ); self.gc_arena.mutate(|gc_context, gc_root| { @@ -394,6 +406,7 @@ impl library: gc_root.library.write(gc_context), background_color, avm: gc_root.avm.write(gc_context), + rng, renderer, audio, navigator, @@ -478,6 +491,7 @@ impl root, start_clip: root, active_clip: root, + rng: update_context.rng, audio: update_context.audio, navigator: update_context.navigator, }; @@ -548,6 +562,7 @@ pub struct UpdateContext<'a, 'gc, 'gc_context> { pub renderer: &'a mut dyn RenderBackend, pub audio: &'a mut dyn AudioBackend, pub navigator: &'a mut dyn NavigatorBackend, + pub rng: &'a mut SmallRng, pub actions: Vec<(DisplayNode<'gc>, crate::tag_utils::SwfSlice)>, pub active_clip: DisplayNode<'gc>, }