26 #import "OverlayViewController.h" |
26 #import "OverlayViewController.h" |
27 |
27 |
28 #define BUFFER_SIZE 255 // like in original frontend |
28 #define BUFFER_SIZE 255 // like in original frontend |
29 |
29 |
30 @implementation GameSetup |
30 @implementation GameSetup |
31 @synthesize systemSettings, gameConfig, savePath, menuStyle; |
31 @synthesize systemSettings, gameConfig, statsDictionary, savePath, menuStyle; |
32 |
32 |
33 -(id) initWithDictionary:(NSDictionary *)gameDictionary { |
33 -(id) initWithDictionary:(NSDictionary *)gameDictionary { |
34 if (self = [super init]) { |
34 if (self = [super init]) { |
35 ipcPort = randomPort(); |
35 ipcPort = randomPort(); |
36 |
36 |
55 NSString *newDateString = [outputFormatter stringFromDate:[NSDate date]]; |
55 NSString *newDateString = [outputFormatter stringFromDate:[NSDate date]]; |
56 self.savePath = [SAVES_DIRECTORY() stringByAppendingFormat:@"%@.hws", newDateString]; |
56 self.savePath = [SAVES_DIRECTORY() stringByAppendingFormat:@"%@.hws", newDateString]; |
57 [outputFormatter release]; |
57 [outputFormatter release]; |
58 } else |
58 } else |
59 self.savePath = path; |
59 self.savePath = path; |
|
60 |
|
61 self.statsDictionary = nil; |
60 } |
62 } |
61 return self; |
63 return self; |
62 } |
64 } |
63 |
65 |
64 -(void) dealloc { |
66 -(void) dealloc { |
|
67 [statsDictionary release]; |
65 [gameConfig release]; |
68 [gameConfig release]; |
66 [systemSettings release]; |
69 [systemSettings release]; |
67 [savePath release]; |
70 [savePath release]; |
68 [super dealloc]; |
71 [super dealloc]; |
69 } |
72 } |
202 return result; |
205 return result; |
203 } |
206 } |
204 |
207 |
205 #pragma mark - |
208 #pragma mark - |
206 #pragma mark Network relevant code |
209 #pragma mark Network relevant code |
207 -(void) dumpRawData:(const uint8_t*)buffer ofSize:(uint8_t) length { |
210 -(void) dumpRawData:(const char *)buffer ofSize:(uint8_t) length { |
208 // is it performant to reopen the stream every time? |
211 // is it performant to reopen the stream every time? |
209 NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:self.savePath append:YES]; |
212 NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:self.savePath append:YES]; |
210 [os open]; |
213 [os open]; |
211 [os write:&length maxLength:1]; |
214 [os write:&length maxLength:1]; |
212 [os write:buffer maxLength:length]; |
215 [os write:(const uint8_t *)buffer maxLength:length]; |
213 [os close]; |
216 [os close]; |
214 [os release]; |
217 [os release]; |
215 } |
218 } |
216 |
219 |
217 // wrapper that computes the length of the message and then sends the command string, saving the command on a file |
220 // wrapper that computes the length of the message and then sends the command string, saving the command on a file |
218 -(int) sendToEngine:(NSString *)string { |
221 -(int) sendToEngine:(NSString *)string { |
219 uint8_t length = [string length]; |
222 uint8_t length = [string length]; |
220 |
223 |
221 [self dumpRawData:(const uint8_t *)[string UTF8String] ofSize:length]; |
224 [self dumpRawData:[string UTF8String] ofSize:length]; |
222 SDLNet_TCP_Send(csd, &length, 1); |
225 SDLNet_TCP_Send(csd, &length, 1); |
223 return SDLNet_TCP_Send(csd, [string UTF8String], length); |
226 return SDLNet_TCP_Send(csd, [string UTF8String], length); |
224 } |
227 } |
225 |
228 |
226 // wrapper that computes the length of the message and then sends the command string, skipping file writing |
229 // wrapper that computes the length of the message and then sends the command string, skipping file writing |
266 csd = SDLNet_TCP_Accept(sd); |
269 csd = SDLNet_TCP_Accept(sd); |
267 SDLNet_TCP_Close(sd); |
270 SDLNet_TCP_Close(sd); |
268 |
271 |
269 while (!clientQuit) { |
272 while (!clientQuit) { |
270 msgSize = 0; |
273 msgSize = 0; |
271 memset(buffer, '\0', BUFFER_SIZE); |
274 memset((void *)buffer, '\0', BUFFER_SIZE); |
272 if (SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)) <= 0) |
275 if (SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)) <= 0) |
273 break; |
276 break; |
274 if (SDLNet_TCP_Recv(csd, buffer, msgSize) <=0) |
277 if (SDLNet_TCP_Recv(csd, (void *)buffer, msgSize) <= 0) |
275 break; |
278 break; |
276 |
279 |
277 switch (buffer[0]) { |
280 switch (buffer[0]) { |
278 case 'C': |
281 case 'C': |
279 DLog(@"sending game config...\n%@",self.gameConfig); |
282 DLog(@"sending game config...\n%@",self.gameConfig); |
281 if (isNetGame == YES) |
284 if (isNetGame == YES) |
282 [self sendToEngineNoSave:@"TN"]; |
285 [self sendToEngineNoSave:@"TN"]; |
283 else |
286 else |
284 [self sendToEngineNoSave:@"TL"]; |
287 [self sendToEngineNoSave:@"TL"]; |
285 NSString *saveHeader = @"TS"; |
288 NSString *saveHeader = @"TS"; |
286 [self dumpRawData:(const uint8_t *)[saveHeader UTF8String] ofSize:[saveHeader length]]; |
289 [self dumpRawData:[saveHeader UTF8String] ofSize:[saveHeader length]]; |
287 |
290 |
288 // seed info |
291 // seed info |
289 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]]; |
292 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]]; |
290 |
293 |
291 // dimension of the map |
294 // dimension of the map |
343 DLog(@"ERROR - wrong protocol number: %d (expecting %d)", netProto, eProto); |
346 DLog(@"ERROR - wrong protocol number: %d (expecting %d)", netProto, eProto); |
344 clientQuit = YES; |
347 clientQuit = YES; |
345 } |
348 } |
346 break; |
349 break; |
347 case 'i': |
350 case 'i': |
|
351 // initialized with maximum |
|
352 if (self.statsDictionary == nil) |
|
353 self.statsDictionary = [[NSMutableDictionary alloc] initWithCapacity:10]; |
348 switch (buffer[1]) { |
354 switch (buffer[1]) { |
349 case 'r': |
355 case 'r': |
350 DLog(@"Winning team: %s", &buffer[2]); |
356 DLog(@"Winning team: %s", &buffer[2]); |
|
357 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"winning_team"]; |
351 break; |
358 break; |
352 case 'D': |
359 case 'D': |
353 DLog(@"Best Shot: %s", &buffer[2]); |
360 DLog(@"Best Shot: %s", &buffer[2]); |
|
361 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"best_shot"]; |
354 break; |
362 break; |
355 case 'k': |
363 case 'k': |
356 DLog(@"Best Hedgehog: %s", &buffer[2]); |
364 DLog(@"Best Hedgehog: %s", &buffer[2]); |
|
365 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"best_hog"]; |
357 break; |
366 break; |
358 case 'K': |
367 case 'K': |
359 DLog(@"Hogs Killed: %s", &buffer[2]); |
368 DLog(@"Hogs Killed: %s", &buffer[2]); |
|
369 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"kills"]; |
360 break; |
370 break; |
361 case 'H': |
371 case 'H': |
362 //something about team health |
372 //something about team health |
363 break; |
373 break; |
364 case 'T': |
374 case 'T': |
367 case 'P': |
377 case 'P': |
368 // player postion |
378 // player postion |
369 break; |
379 break; |
370 case 's': |
380 case 's': |
371 DLog(@"Most self damage: %s", &buffer[2]); |
381 DLog(@"Most self damage: %s", &buffer[2]); |
|
382 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"self_dmg"]; |
372 break; |
383 break; |
373 case 'S': |
384 case 'S': |
374 DLog(@"Most friendly fire: %s", &buffer[2]); |
385 DLog(@"Most friendly fire: %s", &buffer[2]); |
|
386 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"friendly_fire"]; |
375 break; |
387 break; |
376 case 'B': |
388 case 'B': |
377 DLog(@"Most turn skipped by: %s", &buffer[2]); |
389 DLog(@"Most turn skipped by: %s", &buffer[2]); |
|
390 [self.statsDictionary setObject:[NSString stringWithUTF8String:&buffer[2]] forKey:@"turn_skips"]; |
378 break; |
391 break; |
379 default: |
392 default: |
380 DLog(@"Unhandled stat message, see statsPage.cpp"); |
393 DLog(@"Unhandled stat message, see statsPage.cpp"); |
381 break; |
394 break; |
382 } |
395 } |
383 break; |
396 break; |
384 case 'q': |
397 case 'q': |
385 // game ended, can remove the savefile |
398 // game ended, can remove the savefile |
386 [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil]; |
399 [[NSFileManager defaultManager] removeItemAtPath:self.savePath error:nil]; |
387 //[[NSNotificationCenter defaultCenter] postNotificationName:@"removedSave" object:nil]; |
|
388 // and remove + disable the overlay |
400 // and remove + disable the overlay |
389 [[NSNotificationCenter defaultCenter] postNotificationName:@"remove overlay" object:nil]; |
401 [[NSNotificationCenter defaultCenter] postNotificationName:@"remove overlay" object:nil]; |
390 break; |
402 break; |
391 default: |
403 default: |
392 [self dumpRawData:buffer ofSize:msgSize]; |
404 [self dumpRawData:buffer ofSize:msgSize]; |
406 } |
418 } |
407 |
419 |
408 #pragma mark - |
420 #pragma mark - |
409 #pragma mark Setting methods |
421 #pragma mark Setting methods |
410 // returns an array of c-strings that are read by engine at startup |
422 // returns an array of c-strings that are read by engine at startup |
411 -(const char **)getSettings: (NSString *)recordFile { |
423 -(const char **)getGameSettings:(NSString *)recordFile { |
412 NSInteger width, height; |
424 NSInteger width, height; |
413 NSString *ipcString = [[NSString alloc] initWithFormat:@"%d", ipcPort]; |
425 NSString *ipcString = [[NSString alloc] initWithFormat:@"%d", ipcPort]; |
414 NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]]; |
426 NSString *localeString = [[NSString alloc] initWithFormat:@"%@.txt", [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]]; |
415 NSString *rotation; |
427 NSString *rotation; |
416 if (IS_DUALHEAD()) { |
428 if (IS_DUALHEAD()) { |
429 rotation = @"90"; |
441 rotation = @"90"; |
430 } |
442 } |
431 |
443 |
432 NSString *horizontalSize = [[NSString alloc] initWithFormat:@"%d", width]; |
444 NSString *horizontalSize = [[NSString alloc] initWithFormat:@"%d", width]; |
433 NSString *verticalSize = [[NSString alloc] initWithFormat:@"%d", height]; |
445 NSString *verticalSize = [[NSString alloc] initWithFormat:@"%d", height]; |
434 const char **gameArgs = (const char**) malloc(sizeof(char *) * 10); |
446 const char **gameArgs = (const char **)malloc(sizeof(char *) * 10); |
|
447 BOOL enhanced = [[self.systemSettings objectForKey:@"enhanced"] boolValue]; |
|
448 |
|
449 NSString *modelId = modelType(); |
435 NSInteger tmpQuality; |
450 NSInteger tmpQuality; |
436 BOOL enhanced = [[self.systemSettings objectForKey:@"enhanced"] boolValue]; |
|
437 |
|
438 NSString *modelId = modelType(); |
|
439 if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) // = iPhone and iPhone 3G or iPod Touch or iPod Touch 2G |
451 if ([modelId hasPrefix:@"iPhone1"] || [modelId hasPrefix:@"iPod1,1"] || [modelId hasPrefix:@"iPod2,1"]) // = iPhone and iPhone 3G or iPod Touch or iPod Touch 2G |
440 tmpQuality = 0x00000001 | 0x00000002 | 0x00000008 | 0x00000040; // rqLowRes | rqBlurryLand | rqSimpleRope | rqKillFlakes |
452 tmpQuality = 0x00000001 | 0x00000002 | 0x00000008 | 0x00000040; // rqLowRes | rqBlurryLand | rqSimpleRope | rqKillFlakes |
441 else if ([modelId hasPrefix:@"iPhone2"] || [modelId hasPrefix:@"iPod3"]) // = iPhone 3GS or iPod Touch 3G |
453 else if ([modelId hasPrefix:@"iPhone2"] || [modelId hasPrefix:@"iPod3"]) // = iPhone 3GS or iPod Touch 3G |
442 tmpQuality = 0x00000002 | 0x00000040; // rqBlurryLand | rqKillFlakes |
454 tmpQuality = 0x00000002 | 0x00000040; // rqBlurryLand | rqKillFlakes |
443 else if ([modelId hasPrefix:@"iPad1"] || [modelId hasPrefix:@"iPod4"] || enhanced == NO) // = iPad 1G or iPod Touch 4G or not enhanced mode |
455 else if ([modelId hasPrefix:@"iPad1"] || [modelId hasPrefix:@"iPod4"] || enhanced == NO) // = iPad 1G or iPod Touch 4G or not enhanced mode |