Propagate the RNG to the action context. This lets random work.

This commit is contained in:
David Wendt 2019-09-01 21:03:50 -06:00 committed by Mike Welsh
parent 26c928b68f
commit 359d3e4780
4 changed files with 35 additions and 14 deletions

View File

@ -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<Value<'gc>>,
rng: SmallRng,
constant_pool: Vec<String>,
locals: HashMap<String, Value<'gc>>,
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(())
}

View File

@ -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> {

View File

@ -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()
};

View File

@ -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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: Navig
view_matrix: Matrix,
inverse_view_matrix: Matrix,
rng: SmallRng,
gc_arena: GcArena,
background_color: Color,
@ -88,6 +91,8 @@ impl<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
}
}
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
&mut self.renderer,
&mut self.audio,
&mut self.navigator,
&mut self.rng,
&mut self.is_mouse_down,
);
@ -224,6 +230,7 @@ impl<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
}
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
&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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
}
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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<Audio: AudioBackend, Renderer: RenderBackend, Navigator: NavigatorBackend>
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>,
}