Modifying the domain memory of a loaded SWF to control behavior - actionscript-3

I have several flash games that cannot be paused from within the games. I would like to write a wrapper swf that allows me to pause them. It is not feasible to recompile the games, so no functionality can be added to them.
What I would probably need to do is control when the loaded swf gets ENTER_FRAME events and redirect calls to flash.utils.getTimer to a function defined in the wrapper. Can this be done by modifying the domainMemory ByteArray of the loaded ApplicationDomain object?

domainMemory is definitely doesn't help you, it's just the API to access to the fast memory.
What you can try to do is to decompile the game swf and find the dispatcher of main EnterFrame event (and after loading game swf you have to find this dispatcher through the display list for example if it doesn't turned out to be the stage or root), that is used as the game tick dispatcher, than you will be able to intercept the default EnterFrame event for this dispatcher. For interception just add your own listener with the higher priority:
//pause the game
dispatcher.addEventListener(Event.ENTER_FRAME, onGameEnterFrame, false, 1);
//resume the game
dispatcher.removeEventListener(Event.ENTER_FRAME, onGameEnterFrame);
protected function onGameEnterFrame(event:Event):void
{
event.stopImmediatePropagation();
}

Related

as3 symbol variables not initialized yet

I'm initializing symbols in my timeline, and trying to access the variables within those symbols, but they return 0 or undefined even though I set the variables in the symbol's timeline. For some reason the variables haven't been set yet, though the main timeline can see that they exist. How do I make the program wait until the variables have been set?
Best practice to work with classes, not coding in timeline and frames of MovieClip.
I assume you have MovieClip from designer and you want inject some logic to the specific frame. There are many options.
Events
You can trigger event in the specific frame, and you work in normal way (with classes and class members).
//Frame code
import flash.events.Event;
this.dispatchEvent(new Event("IntroDidFinish", true, true));
stop();
//Somewhere in class
myContainer.addEventListener("IntroDidFinish", onIntroFinish, false, 0, true);
function onIntroFinish(e: Event):void{
//Do your stuff
}
Events help you decouple logic from the design(predefined complex MovieClip, etc.)
Waiting for initialisation
As MovieClip reaches some frame, you should wait extra time for initialisation. Thats why 99.9% of AS3 developers don't like MovieClip as holder for any critical data or logic. It means if you call myMovieClip.goToAndStop(8); you can't get myMovieClip.someValue declared in 8 frame after goTo operation. If you still want to go with such approach, easiest solution for you will be Event.ENTER_FRAME, after goTo subscribe for ENTER_FRAME event, for only one update, and do your work ;)

Should I remove listener for SOUND_COMPLETE event?

My application needs to notify UI that sound playback is finished. To accomplish that is attaches listener to the SOUND_COMPLETE event of a SoundChannel object.
Should I remove my SOUND_COMPLETE event listener after event processing is done?
private function playbackCompleteHandler(event:Event):void {
// Notify UI that playback is done etc
channel.removeEventListener(Event.SOUND_COMPLETE, playbackCompleteHandler);
}
Everyone says that we should always remove event listeners so that GC could properly collect objects ('channel' object in this case). But it seems that Adobe doesn't do that in the official documentation [1][2]
[1] http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/SoundChannel.html
[2] http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d21.html
Dispatcher holds listeners, so, if your dispatcher is long-living(like Application), you should use weak listeners:
channel.removeEventListener(Event.SOUND_COMPLETE, playbackCompleteHandler,false,0, true)
last true allows your objects to be freed.
If you don't need your temporary objects to process dispatcher's events after you loose all references to temporary objects and until they are collected, you shall remove listeners
Otherwise(when dispatchers are short-living), there is no need to care about listeners: if you are listening to something temporary, it will die without any problems.
It seems that your case is the last one, so it's better not to pollute code with meaningless lines.
You're question states my answer for this
Everyone says that we should always remove event listeners so that GC
could properly collect objects
If you are no longer keeping an instance of the Sound object around; then remove the event listener. If you will still be using the Sound object; then there is no need to remove the listener.

as3 air unloadAndStop() event listener or timer

my air application plays an external swf over and over until time to play the next external swf. in order to avoid memory leaks i am using unloadAndStop(). i am using two timers. the first unloadAndStops the swf. the second waits two seconds then loads it back up again.
this approach (coupled with the use of weak references) seems to keep the memory in check. however, i'd rather not use timers but event listeners. is there an event listener for when unloadAndStop completes to then load the swf again.
here is what i had in mind:
var TIMER_INTERVAL:int = int(duration);
var t:Timer = new Timer(TIMER_INTERVAL);
t.addEventListener(TimerEvent.TIMER,updateTimer,false,0,true);
t.start();
private function updateTimer(e:TimerEvent):void
{
swfLoader.unloadAndStop(true);
swfLoader.addEventListener(Event.UNLOAD,onSWFUnloadComplete,false,0,true);
}
private function updateTimer(e:TimerEvent):void
{
var swfSource2:String = File.applicationStorageDirectory.nativePath.toString();
swfLoader.load(swfSource2+'\\'+name_xml);
}
unloadAndStop is not an asynchronous method, so an unload event wouldn't really be relevant. What is likely happening behind the scenes is that it takes 1 full frame to fully dispose of the movies objects/listeners and that's why you're having issues loading it again in the same block of code.
If you wait just one frame before loading it again, you should have the results you expect.
Now, of course the best solution is go into the source file of your loaded swf and fix the memory leaks.

AS3: Handle BulkLoader.COMPLETE event on AS3 Preloader

I am trying to use BulkLoader (https://github.com/arthur-debert/BulkLoader) to preload all assets of my AS3/Flex application. Right now it is working and I am able to access the contents everywhere on my Main module (where my BulkLoader instance lives).
My problem: I need to handle the BulkLoader.COMPLETE event from my preloader (pre.as living next to Main.mxml on src/), to allow the user to exit the preloader and enter the application ONLY after BulkLoader.COMPLETE was fired.
Thanks!
Why not pass the reference to the BulkLoader instance?
Somethinglike this:
preloader.setLoader(_bulkLoaderInstance or name)
or
var preloader:Preloader = new Preloder(_bulkLoaderInstance or name)
BTW, the LoaderMax from Greensock is better (fewer bugs, more reliable events, nicer API).

AS3 Wrapper Accessing AS1 Variables

Okay, so I have a Flash CS3 (+ AS3) program which is loading another flash program (called "pacman_main.swf" in this example). I've determined this is a rather old SWF, as it is made in Flash 5 and AS1 (yippee!).
I want the parent SWF (a.k.a. the wrapper) to be able to access the variables, specifically the score, of the child SWFG (a.k.a. "pacman_main.swf"). This is so I can submit the score to a 3rd party PHP/mySQL db blah blah.
function checkScore() {
// Get the score and submit it
}
submitScore.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(event:MouseEvent):void {
checkScore();
}
var loader:Loader = new Loader();
loader.load(new URLRequest("pacman_main.swf"));
addChildAt(loader, 0);
I know the variable name of the score, using the Debug > List Variables after building the wrapper. The score is a variable listed as "Variable _level0.instance5.instance6.score = 180" after getting 18 pac-dots in the game. How would I access that in my "checkScore" function?
Thanks!
The latest flash players have two virtual machines packaged in them, the AVM2 for as3, and AVM1 for as2/as1. Because of this, when you load an as1/as2 swf into flash it is of the type AVM1Movie, which will be run by the AVM1. Unfortunately, the AVM2 has little access to the objects running on AVM1, in fact, "no interoperability (such as calling methods or using parameters) between the AVM1Movie object and AVM2 objects is allowed".
Do you have access to the as1 source code? If you do I suggest firing off events every time the score changes, you can listen for these events in your wrapper class and not have to worry about accessing the score variable directly.
You can read more about AVM1Movie here