project_files/HedgewarsMobile/Classes/EngineProtocolNetwork.m
branch0.9.17
changeset 6366 1a49a8fcca56
parent 6353 d8f62c805619
child 6365 c992df555afb
equal deleted inserted replaced
6360:eca20f8990e2 6366:1a49a8fcca56
    26 #define BUFFER_SIZE 255     // like in original frontend
    26 #define BUFFER_SIZE 255     // like in original frontend
    27 
    27 
    28 static NSInteger activeEnginePort;
    28 static NSInteger activeEnginePort;
    29 
    29 
    30 @implementation EngineProtocolNetwork
    30 @implementation EngineProtocolNetwork
    31 @synthesize delegate, stream, csd, enginePort;
    31 @synthesize statsArray, stream, csd, enginePort;
    32 
    32 
    33 -(id) init {
    33 -(id) init {
    34     if (self = [super init]) {
    34     if (self = [super init]) {
    35         self.delegate = nil;
    35         self.statsArray = nil;
    36 
       
    37         self.csd = NULL;
    36         self.csd = NULL;
    38         self.stream = nil;
    37         self.stream = nil;
    39         self.enginePort = [HWUtils randomPort];
    38         self.enginePort = [HWUtils randomPort];
    40     }
    39     }
    41     activeEnginePort = self.enginePort;
    40     activeEnginePort = self.enginePort;
    42     return self;
    41     return self;
    43 }
    42 }
    44 
    43 
    45 -(void) gameHasEndedWithStats:(NSArray *)stats {
       
    46     if (self.delegate != nil && [self.delegate respondsToSelector:@selector(gameHasEndedWithStats:)])
       
    47         [self.delegate gameHasEndedWithStats:stats];
       
    48     else
       
    49         DLog(@"Error! delegate == nil");
       
    50 }
       
    51 
       
    52 -(void) dealloc {
    44 -(void) dealloc {
    53     self.delegate = nil;
    45     releaseAndNil(statsArray);
    54     releaseAndNil(stream);
    46     releaseAndNil(stream);
    55     [super dealloc];
    47     [super dealloc];
    56 }
    48 }
    57 
    49 
    58 #pragma mark -
    50 #pragma mark -
    59 #pragma mark Spawner functions
    51 #pragma mark Spawner functions
    60 +(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary {
    52 -(void) spawnThread:(NSString *)onSaveFile withOptions:(NSDictionary *)dictionary {
    61     id proto = [[self alloc] init];
    53     self.stream = (onSaveFile) ? [[NSOutputStream alloc] initToFileAtPath:onSaveFile append:YES] : nil;
    62     [proto setStream: (onSaveFile) ? [[NSOutputStream alloc] initToFileAtPath:onSaveFile append:YES] : nil];
    54     [self.stream open];
    63     [[proto stream] open];
       
    64 
    55 
    65     // +detachNewThreadSelector retain/release self automatically
    56     // +detachNewThreadSelector retain/release self automatically
    66     [NSThread detachNewThreadSelector:@selector(engineProtocol:)
    57     [NSThread detachNewThreadSelector:@selector(engineProtocol:)
    67                              toTarget:proto
    58                              toTarget:self
    68                            withObject:dictionary];
    59                            withObject:dictionary];
    69     [proto release];
       
    70 }
    60 }
    71 
    61 
    72 +(NSInteger) activeEnginePort {
    62 +(NSInteger) activeEnginePort {
    73     return activeEnginePort;
    63     return activeEnginePort;
    74 }
    64 }
   230 
   220 
   231 // this is launched as thread and handles all IPC with engine
   221 // this is launched as thread and handles all IPC with engine
   232 -(void) engineProtocol:(id) object {
   222 -(void) engineProtocol:(id) object {
   233     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   223     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   234     NSDictionary *gameConfig = (NSDictionary *)object;
   224     NSDictionary *gameConfig = (NSDictionary *)object;
   235     NSMutableArray *statsArray = nil;
   225     NSMutableArray *tempStats = nil;
   236     TCPsocket sd;
   226     TCPsocket sd;
   237     IPaddress ip;
   227     IPaddress ip;
   238     int eProto;
   228     int eProto;
   239     BOOL clientQuit;
   229     BOOL clientQuit;
   240     char const buffer[BUFFER_SIZE];
   230     char const buffer[BUFFER_SIZE];
   345                     DLog(@"ERROR - wrong protocol number: %d (expecting %d)", netProto, eProto);
   335                     DLog(@"ERROR - wrong protocol number: %d (expecting %d)", netProto, eProto);
   346                     clientQuit = YES;
   336                     clientQuit = YES;
   347                 }
   337                 }
   348                 break;
   338                 break;
   349             case 'i':
   339             case 'i':
   350                 if (statsArray == nil) {
   340                 if (tempStats == nil) {
   351                     statsArray = [[NSMutableArray alloc] initWithCapacity:10 - 2];
   341                     tempStats = [[NSMutableArray alloc] initWithCapacity:10 - 2];
   352                     NSMutableArray *ranking = [[NSMutableArray alloc] initWithCapacity:4];
   342                     NSMutableArray *ranking = [[NSMutableArray alloc] initWithCapacity:4];
   353                     [statsArray insertObject:ranking atIndex:0];
   343                     [tempStats insertObject:ranking atIndex:0];
   354                     [ranking release];
   344                     [ranking release];
   355                 }
   345                 }
   356                 NSString *tempStr = [NSString stringWithUTF8String:&buffer[2]];
   346                 NSString *tempStr = [NSString stringWithUTF8String:&buffer[2]];
   357                 NSArray *info = [tempStr componentsSeparatedByString:@" "];
   347                 NSArray *info = [tempStr componentsSeparatedByString:@" "];
   358                 NSString *arg = [info objectAtIndex:0];
   348                 NSString *arg = [info objectAtIndex:0];
   359                 int index = [arg length] + 3;
   349                 int index = [arg length] + 3;
   360                 switch (buffer[1]) {
   350                 switch (buffer[1]) {
   361                     case 'r':           // winning team
   351                     case 'r':           // winning team
   362                         [statsArray insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1];
   352                         [tempStats insertObject:[NSString stringWithUTF8String:&buffer[2]] atIndex:1];
   363                         break;
   353                         break;
   364                     case 'D':           // best shot
   354                     case 'D':           // best shot
   365                         [statsArray addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]];
   355                         [tempStats addObject:[NSString stringWithFormat:@"The best shot award won by %s (with %@ points)", &buffer[index], arg]];
   366                         break;
   356                         break;
   367                     case 'k':           // best hedgehog
   357                     case 'k':           // best hedgehog
   368                         [statsArray addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kills in a turn", &buffer[index], arg]];
   358                         [tempStats addObject:[NSString stringWithFormat:@"The best killer is %s with %@ kills in a turn", &buffer[index], arg]];
   369                         break;
   359                         break;
   370                     case 'K':           // number of hogs killed
   360                     case 'K':           // number of hogs killed
   371                         [statsArray addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]];
   361                         [tempStats addObject:[NSString stringWithFormat:@"%@ hedgehog(s) were killed during this round", arg]];
   372                         break;
   362                         break;
   373                     case 'H':           // team health/graph
   363                     case 'H':           // team health/graph
   374                         break;
   364                         break;
   375                     case 'T':           // local team stats
   365                     case 'T':           // local team stats
   376                         // still WIP in statsPage.cpp
   366                         // still WIP in statsPage.cpp
   377                         break;
   367                         break;
   378                     case 'P':           // teams ranking
   368                     case 'P':           // teams ranking
   379                         [[statsArray objectAtIndex:0] addObject:tempStr];
   369                         [[tempStats objectAtIndex:0] addObject:tempStr];
   380                         break;
   370                         break;
   381                     case 's':           // self damage
   371                     case 's':           // self damage
   382                         [statsArray addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]];
   372                         [tempStats addObject:[NSString stringWithFormat:@"%s thought it's good to shoot his own hedgehogs with %@ points", &buffer[index], arg]];
   383                         break;
   373                         break;
   384                     case 'S':           // friendly fire
   374                     case 'S':           // friendly fire
   385                         [statsArray addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]];
   375                         [tempStats addObject:[NSString stringWithFormat:@"%s killed %@ of his own hedgehogs", &buffer[index], arg]];
   386                         break;
   376                         break;
   387                     case 'B':           // turn skipped
   377                     case 'B':           // turn skipped
   388                         [statsArray addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]];
   378                         [tempStats addObject:[NSString stringWithFormat:@"%s was scared and skipped turn %@ times", &buffer[index], arg]];
   389                         break;
   379                         break;
   390                     default:
   380                     default:
   391                         DLog(@"Unhandled stat message, see statsPage.cpp");
   381                         DLog(@"Unhandled stat message, see statsPage.cpp");
   392                         break;
   382                         break;
   393                 }
   383                 }
   394                 break;
   384                 break;
   395             case 'q':
   385             case 'q':
   396                 // game ended, can remove the savefile and present the statistics of the match
   386                 // game ended and match finished, statsArray is full of delicious statistics
   397                 [HWUtils setGameStatus:gsEnded];
   387                 [HWUtils setGameStatus:gsEnded];
   398                 [self gameHasEndedWithStats:statsArray];
   388                 self.statsArray = [[NSArray arrayWithArray:tempStats] retain];
       
   389                 // closing connection here would trigger a "IPC connection lost" error, so we have to wait until recv fails
   399                 break;
   390                 break;
   400             case 'Q':
   391             case 'Q':
   401                 // game exited but not completed, nothing to do (just don't save the message)
   392                 // game exited but not completed, skip this message in the savefile
       
   393                 [HWUtils setGameStatus:gsInterrupted];
       
   394                 // same here, don't set clientQuit to YES
   402                 break;
   395                 break;
   403             default:
   396             default:
   404                 [self dumpRawData:buffer ofSize:msgSize];
   397                 [self dumpRawData:buffer ofSize:msgSize];
   405                 break;
   398                 break;
   406         }
   399         }
   407     }
   400     }
   408     DLog(@"Engine exited, ending thread");
   401     DLog(@"Engine exited, ending thread");
       
   402 
   409     [self.stream close];
   403     [self.stream close];
   410     [self.stream release];
   404     [self.stream release];
   411     [statsArray release];
   405     [tempStats release];
   412 
   406 
   413     // Close the client socket
   407     // Close the client socket
   414     SDLNet_TCP_Close(csd);
   408     SDLNet_TCP_Close(csd);
   415     SDLNet_Quit();
   409     SDLNet_Quit();
   416 
   410