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 } |
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 |