# HG changeset patch # User koda # Date 1320972023 -3600 # Node ID 5a0416e5a6de2b7a3cd687415a767dd61bf0df8a # Parent 238a6dc0e7ad8bfdd82e7adf489ee1ceb26ded71 further engine interaction refactoring diff -r 238a6dc0e7ad -r 5a0416e5a6de project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h Fri Nov 11 01:18:19 2011 +0100 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.h Fri Nov 11 01:40:23 2011 +0100 @@ -32,17 +32,21 @@ id delegate; NSOutputStream *stream; - TCPsocket csd; // Client socket descriptor + TCPsocket csd; + NSInteger enginePort; } @property (nonatomic,assign) id delegate; @property (nonatomic,retain) NSOutputStream *stream; @property (assign) TCPsocket csd; +@property (assign) NSInteger enginePort; -(id) init; --(NSInteger) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary; ++(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary; ++(NSInteger) activeEnginePort; + -(void) engineProtocol:(id) object; -(void) gameHasEndedWithStats:(NSArray *)stats; diff -r 238a6dc0e7ad -r 5a0416e5a6de project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m --- a/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Fri Nov 11 01:18:19 2011 +0100 +++ b/project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m Fri Nov 11 01:40:23 2011 +0100 @@ -25,8 +25,10 @@ #define BUFFER_SIZE 255 // like in original frontend +static NSInteger activeEnginePort; + @implementation EngineProtocolNetwork -@synthesize delegate, stream, csd; +@synthesize delegate, stream, csd, enginePort; -(id) init { if (self = [super init]) { @@ -34,7 +36,9 @@ self.csd = NULL; self.stream = nil; + self.enginePort = [HWUtils randomPort]; } + activeEnginePort = self.enginePort; return self; } @@ -53,21 +57,20 @@ #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]; ++(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary { + EngineProtocolNetwork *proto = [[EngineProtocolNetwork alloc] init]; + proto.stream = (onSaveFile) ? [[NSOutputStream alloc] initToFileAtPath:onSaveFile append:YES] : nil; + [proto.stream open]; - NSInteger ipcPort = [HWUtils randomPort]; - NSDictionary *config = [[NSDictionary alloc] initWithObjectsAndKeys: - [NSNumber numberWithInt:ipcPort],@"port", - dictionary,@"config", nil]; + // +detachNewThreadSelector retain/release self automatically [NSThread detachNewThreadSelector:@selector(engineProtocol:) - toTarget:self - withObject:config]; - [config release]; + toTarget:proto + withObject:dictionary]; + [proto release]; +} - return ipcPort; ++(NSInteger) activeEnginePort { + return activeEnginePort; } #pragma mark - @@ -228,8 +231,7 @@ // this is launched as thread and handles all IPC with engine -(void) engineProtocol:(id) object { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSDictionary *gameConfig = [(NSDictionary *)object objectForKey:@"config"]; - NSInteger port = [[(NSDictionary *)object objectForKey:@"port"] intValue]; + NSDictionary *gameConfig = (NSDictionary *)object; NSMutableArray *statsArray = nil; TCPsocket sd; IPaddress ip; @@ -247,18 +249,18 @@ } // Resolving the host using NULL make network interface to listen - if (SDLNet_ResolveHost(&ip, NULL, port) < 0 && !clientQuit) { + if (SDLNet_ResolveHost(&ip, NULL, self.enginePort) < 0 && !clientQuit) { DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError()); clientQuit = YES; } // Open a connection with the IP provided (listen on the host's port) if (!(sd = SDLNet_TCP_Open(&ip)) && !clientQuit) { - DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port); + DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), self.enginePort); clientQuit = YES; } - DLog(@"Waiting for a client on port %d", port); + DLog(@"Waiting for a client on port %d", self.enginePort); while (csd == NULL) csd = SDLNet_TCP_Accept(sd); SDLNet_TCP_Close(sd); @@ -413,8 +415,6 @@ SDLNet_Quit(); [pool release]; - - [self performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:YES]; // Invoking this method should be avoided as it does not give your thread a chance // to clean up any resources it allocated during its execution. //[NSThread exit]; diff -r 238a6dc0e7ad -r 5a0416e5a6de project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h Fri Nov 11 01:18:19 2011 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.h Fri Nov 11 01:40:23 2011 +0100 @@ -23,11 +23,9 @@ @interface GameInterfaceBridge : NSObject { - NSInteger ipcPort; UIView *blackView; } -@property (assign) NSInteger ipcPort; @property (nonatomic,retain) UIView *blackView; +(void) startLocalGame:(NSDictionary *)withOptions; diff -r 238a6dc0e7ad -r 5a0416e5a6de project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m --- a/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Fri Nov 11 01:18:19 2011 +0100 +++ b/project_files/HedgewarsMobile/Classes/GameInterfaceBridge.m Fri Nov 11 01:40:23 2011 +0100 @@ -27,7 +27,7 @@ #import "ObjcExports.h" @implementation GameInterfaceBridge -@synthesize ipcPort, blackView; +@synthesize blackView; #pragma mark - #pragma mark Instance methods for engine interaction @@ -35,10 +35,7 @@ -(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]; + [EngineProtocolNetwork spawnThread:pathOrNil withOptions:optionsOrNil]; // add a black view hiding the background CGRect theFrame = [[UIScreen mainScreen] bounds]; @@ -90,8 +87,9 @@ -(void) engineLaunch:(NSString *)pathOrNil { const char *gameArgs[11]; CGFloat width, height; + NSInteger enginePort = [EngineProtocolNetwork activeEnginePort]; CGFloat screenScale = [[UIScreen mainScreen] safeScale]; - NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",self.ipcPort]; + NSString *ipcString = [[NSString alloc] initWithFormat:@"%d",enginePort]; NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt",[[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]]; NSUserDefaults *settings = [NSUserDefaults standardUserDefaults]; @@ -158,10 +156,14 @@ #pragma mark - #pragma mark Class methods for setting up the engine from outsite -// set up variables for a local game ++(void) startGame:(TGameType) type atPath:(NSString *)path withOptions:(NSDictionary *)config { + [HWUtils setGameType:type]; + GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init]; + [bridge earlyEngineLaunch:path withOptions:config]; + [bridge release]; +} + +(void) startLocalGame:(NSDictionary *)withOptions { - [HWUtils setGameType:gtLocal]; - NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init]; [outputFormatter setDateFormat:@"yyyy-MM-dd '@' HH.mm"]; NSString *savePath = [[NSString alloc] initWithFormat:@"%@%@.hws",SAVES_DIRECTORY(),[outputFormatter stringFromDate:[NSDate date]]]; @@ -171,30 +173,20 @@ if ([[NSFileManager defaultManager] fileExistsAtPath:savePath]) [[NSFileManager defaultManager] removeItemAtPath:savePath error:nil]; - GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init]; - [bridge earlyEngineLaunch:savePath withOptions:withOptions]; - [bridge release]; + [self startGame:gtLocal atPath:savePath withOptions:withOptions]; [savePath release]; } -// set up variables for a save game +(void) startSaveGame:(NSString *)atPath { - [HWUtils setGameType:gtSave]; - GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init]; - [bridge earlyEngineLaunch:atPath withOptions:nil]; - [bridge release]; + [self startGame:gtSave atPath:atPath withOptions:nil]; } +(void) startMissionGame:(NSString *)withScript { - [HWUtils setGameType:gtMission]; - NSString *missionPath = [[NSString alloc] initWithFormat:@"escript Missions/Training/%@.lua",withScript]; NSDictionary *missionLine = [[NSDictionary alloc] initWithObjectsAndKeys:missionPath,@"mission_command",nil]; [missionPath release]; - GameInterfaceBridge *bridge = [[GameInterfaceBridge alloc] init]; - [bridge earlyEngineLaunch:nil withOptions:missionLine]; - [bridge release]; + [self startGame:gtMission atPath:nil withOptions:missionLine]; [missionLine release]; } diff -r 238a6dc0e7ad -r 5a0416e5a6de project_files/HedgewarsMobile/Classes/HWUtils.m --- a/project_files/HedgewarsMobile/Classes/HWUtils.m Fri Nov 11 01:18:19 2011 +0100 +++ b/project_files/HedgewarsMobile/Classes/HWUtils.m Fri Nov 11 01:40:23 2011 +0100 @@ -25,6 +25,7 @@ #import #import #import "hwconsts.h" +#import "EngineProtocolNetwork.h" static NSString *cachedModel = nil; static NSArray *cachedColors = nil; @@ -96,7 +97,11 @@ +(NSInteger) randomPort { srandom(time(NULL)); NSInteger res = (random() % 64511) + 1024; - return (res == NETGAME_DEFAULT_PORT) ? [HWUtils randomPort] : res; + // recall self until you get a free port + if (res == NETGAME_DEFAULT_PORT || res == [EngineProtocolNetwork activeEnginePort]) + return [self randomPort]; + else + return res; } +(BOOL) isNetworkReachable { diff -r 238a6dc0e7ad -r 5a0416e5a6de project_files/HedgewarsMobile/Classes/RestoreViewController.m --- a/project_files/HedgewarsMobile/Classes/RestoreViewController.m Fri Nov 11 01:18:19 2011 +0100 +++ b/project_files/HedgewarsMobile/Classes/RestoreViewController.m Fri Nov 11 01:40:23 2011 +0100 @@ -36,14 +36,13 @@ if (theButton.tag != 0) { [AudioManagerController playClickSound]; - [self.parentViewController dismissModalViewControllerAnimated:NO]; [[NSNotificationCenter defaultCenter] postNotificationName:@"launchRestoredGame" object:nil]; } else { [AudioManagerController playBackSound]; [defaults setObject:@"" forKey:@"savedGamePath"]; [defaults synchronize]; - [self.parentViewController dismissModalViewControllerAnimated:YES]; } + [self.parentViewController dismissModalViewControllerAnimated:YES]; } -(void) viewDidLoad {