engine interaction class refactoring, round 4 or 5, can't remember: this time use the class methods to create an instance object and operates on that, reducing the number of arguments between methods and simplifying memory management
authorkoda
Sun, 06 Nov 2011 17:43:57 +0100
changeset 6301 1259736c0134
parent 6300 db8fd3ff693c
child 6302 db8bdbb34e03
engine interaction class refactoring, round 4 or 5, can't remember: this time use the class methods to create an instance object and operates on that, reducing the number of arguments between methods and simplifying memory management
project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m
project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h
project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m
--- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m	Sun Nov 06 16:41:14 2011 +0100
+++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m	Sun Nov 06 17:43:57 2011 +0100
@@ -54,6 +54,7 @@
 #pragma mark -
 #pragma mark Spawner functions
 -(NSInteger) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary {
+    [self retain];
     self.stream = (onSaveFile) ? [[NSOutputStream alloc] initToFileAtPath:onSaveFile append:YES] : nil;
     [self.stream open];
 
--- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h	Sun Nov 06 16:41:14 2011 +0100
+++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h	Sun Nov 06 17:43:57 2011 +0100
@@ -23,8 +23,12 @@
 
 
 @interface GameInterfaceBridge : NSObject {
+    NSInteger ipcPort;
+    UIView *blackView;
+}
 
-}
+@property (assign) NSInteger ipcPort;
+@property (nonatomic,retain) UIView *blackView;
 
 +(void) startLocalGame:(NSDictionary *)withOptions;
 +(void) startSaveGame:(NSString *)atPath;
--- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m	Sun Nov 06 16:41:14 2011 +0100
+++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m	Sun Nov 06 17:43:57 2011 +0100
@@ -27,14 +27,72 @@
 #import "ObjcExports.h"
 
 @implementation GameInterfaceBridge
+@synthesize ipcPort, blackView;
+
+#pragma mark -
+#pragma mark Instance methods for engine interaction
+// prepares the controllers for hosting a game
+-(void) earlyEngineLaunch:(NSString *)pathOrNil withOptions:(NSDictionary *)optionsOrNil {
+    [self retain];
+    [AudioManagerController stopBackgroundMusic];
+
+    EngineProtocolNetwork *proto = [[EngineProtocolNetwork alloc] init];
+    self.ipcPort = [proto spawnThread:pathOrNil withOptions:optionsOrNil];
+    [proto release];
+
+    // add a black view hiding the background
+    CGRect theFrame = [[UIScreen mainScreen] bounds];
+    UIWindow *thisWindow = [[HedgewarsAppDelegate sharedAppDelegate] uiwindow];
+    self.blackView = [[UIView alloc] initWithFrame:theFrame];
+    self.blackView.opaque = YES;
+    self.blackView.backgroundColor = [UIColor blackColor];
+    self.blackView.alpha = 0;
+    [UIView beginAnimations:@"fade out" context:NULL];
+    [UIView setAnimationDuration:1];
+    self.blackView.alpha = 1;
+    [UIView commitAnimations];
+    [thisWindow addSubview:self.blackView];
+    [self.blackView release];
+
+    // keep track of uncompleted games
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    [userDefaults setObject:pathOrNil forKey:@"savedGamePath"];
+    [userDefaults synchronize];
+
+    // let's launch the engine using this -perfomSelector so that the runloop can deal with queued messages first
+    [self performSelector:@selector(engineLaunch:) withObject:pathOrNil afterDelay:0.1f];
+}
+
+// cleans up everything
+-(void) lateEngineLaunch {
+    // remove completed games notification
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    [userDefaults setObject:@"" forKey:@"savedGamePath"];
+    [userDefaults synchronize];
+
+    // remove the cover view with a transition
+    self.blackView.alpha = 1;
+    [UIView beginAnimations:@"fade in" context:NULL];
+    [UIView setAnimationDuration:1];
+    self.blackView.alpha = 0;
+    [UIView commitAnimations];
+    [self.blackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
+
+    // the overlay is not needed any more and can be removed
+    [[OverlayViewController mainOverlay] removeOverlay];
+
+    // restart music and we're done
+    [AudioManagerController playBackgroundMusic];
+    [self release];
+}
 
 // main routine for calling the actual game engine
-+(void) engineLaunchOn:(NSInteger) ipcPort withArgument:(NSString *)path {
+-(void) engineLaunch:(NSString *)pathOrNil {
     const char *gameArgs[11];
     CGFloat width, height;
     CGFloat screenScale = [[UIScreen mainScreen] safeScale];
-    NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",ipcPort];
-    NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
+    NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",self.ipcPort];
+    NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]];
     NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
 
     if (IS_DUALHEAD()) {
@@ -83,7 +141,7 @@
     gameArgs[ 7] = [[[settings objectForKey:@"music"] stringValue] UTF8String];                 //isMusicEnabled
     gameArgs[ 8] = [[[settings objectForKey:@"alternate"] stringValue] UTF8String];             //cAltDamage
     gameArgs[ 9] = [rotation UTF8String];                                                       //rotateQt
-    gameArgs[10] = ([HWUtils gameType] == gtSave) ? [path UTF8String] : NULL;                   //recordFileName
+    gameArgs[10] = ([HWUtils gameType] == gtSave) ? [pathOrNil UTF8String] : NULL;              //recordFileName
 
     [verticalSize release];
     [horizontalSize release];
@@ -95,61 +153,11 @@
 
     // this is the pascal function that starts the game
     Game(gameArgs);
+    [self lateEngineLaunch];
 }
 
-// prepares the controllers for hosting a game
-+(void) prepareEngineOn:(NSString *)pathOrNil withOptions:(NSDictionary *)optionsOrNil {
-    EngineProtocolNetwork *proto = [[EngineProtocolNetwork alloc] init];
-    NSInteger ipcPort = [proto spawnThread:pathOrNil withOptions:optionsOrNil];
-
-    CGRect theFrame = [[UIScreen mainScreen] bounds];
-    UIWindow *thisWindow = [[HedgewarsAppDelegate sharedAppDelegate] uiwindow];
-    // we add a black view hiding the background
-    UIView *blackView = [[UIView alloc] initWithFrame:theFrame];
-    [thisWindow addSubview:blackView];
-    blackView.opaque = YES;
-    blackView.backgroundColor = [UIColor blackColor];
-    blackView.alpha = 0;
-
-    // when dual screen we apply a little transition
-    if (IS_DUALHEAD()) {
-        [UIView beginAnimations:@"fade out" context:NULL];
-        [UIView setAnimationDuration:1];
-        blackView.alpha = 1;
-        [UIView commitAnimations];
-    } else
-        blackView.alpha = 1;
-
-    // keep track of uncompleted games
-    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
-    [userDefaults setObject:pathOrNil forKey:@"savedGamePath"];
-    [userDefaults synchronize];
-
-    [AudioManagerController pauseBackgroundMusic];
-
-    // SYSTEMS ARE GO!!
-    [self engineLaunchOn:ipcPort withArgument:pathOrNil];
-    
-    // remove completed games notification
-    [userDefaults setObject:@"" forKey:@"savedGamePath"];
-    [userDefaults synchronize];
-
-    // now we can remove the cover with a transition
-    blackView.frame = theFrame;
-    blackView.alpha = 1;
-    [UIView beginAnimations:@"fade in" context:NULL];
-    [UIView setAnimationDuration:1];
-    blackView.alpha = 0;
-    [UIView commitAnimations];
-    [blackView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1];
-    [blackView release];
-
-    // the overlay is not needed any more and can be removed
-    [[OverlayViewController mainOverlay] removeOverlay];
-
-    [AudioManagerController playBackgroundMusic];
-}
-
+#pragma mark -
+#pragma mark Class methods for setting up the engine from outsite
 // set up variables for a local game
 +(void) startLocalGame:(NSDictionary *)withOptions {
     [HWUtils setGameType:gtLocal];
@@ -159,18 +167,22 @@
     NSString *savePath = [[NSString alloc] initWithFormat:@"%@%@.hws",SAVES_DIRECTORY(),[outputFormatter stringFromDate:[NSDate date]]];
     [outputFormatter release];
 
-    // in the rare case in which a savefile with the same name exists the older one must be removed (or it gets corrupted)
+    // in the rare case in which a savefile with the same name exists the older one must be removed (otherwise it gets corrupted)
     if ([[NSFileManager defaultManager] fileExistsAtPath:savePath])
         [[NSFileManager defaultManager] removeItemAtPath:savePath error:nil];
 
-    [GameInterfaceBridge prepareEngineOn:savePath withOptions:withOptions];
+    GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init];
+    [bridge earlyEngineLaunch:savePath withOptions:withOptions];
+    [bridge release];
     [savePath release];
 }
 
 // set up variables for a save game
 +(void) startSaveGame:(NSString *)atPath {
     [HWUtils setGameType:gtSave];
-    [GameInterfaceBridge prepareEngineOn:atPath withOptions:nil];
+    GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init];
+    [bridge earlyEngineLaunch:atPath withOptions:nil];
+    [bridge release];
 }
 
 +(void) startMissionGame:(NSString *)withScript {
@@ -180,7 +192,9 @@
     NSDictionary *missionLine = [[NSDictionary alloc] initWithObjectsAndKeys:missionPath,@"mission_command",nil];
     [missionPath release];
 
-    [GameInterfaceBridge prepareEngineOn:nil withOptions:missionLine];
+    GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init];
+    [bridge earlyEngineLaunch:nil withOptions:missionLine];
+    [bridge release];
     [missionLine release];
 }