project_files/HedgewarsMobile/Classes/GameSetup.m
changeset 3548 4d220ee7c75f
parent 3547 02875b1145b7
child 3551 d4de36b3801a
equal deleted inserted replaced
3547:02875b1145b7 3548:4d220ee7c75f
    14 #import "SDL_net.h"
    14 #import "SDL_net.h"
    15 #import "PascalImports.h"
    15 #import "PascalImports.h"
    16 #import "CommodityFunctions.h"
    16 #import "CommodityFunctions.h"
    17 
    17 
    18 #define BUFFER_SIZE 256
    18 #define BUFFER_SIZE 256
    19 #define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
       
    20 
    19 
    21 @implementation GameSetup
    20 @implementation GameSetup
    22 
    21 
    23 @synthesize systemSettings, gameConfig;
    22 @synthesize systemSettings, gameConfig;
    24 
    23 
    36         [dictGame release];
    35         [dictGame release];
    37     } 
    36     } 
    38     return self;
    37     return self;
    39 }
    38 }
    40 
    39 
    41 -(NSString *)description {
       
    42     return [NSString stringWithFormat:@"ipcport: %d\nsockets: %d,%d\n teams: %@\n systemSettings: %@",ipcPort,sd,csd,gameConfig,systemSettings];
       
    43 }
       
    44 
       
    45 -(void) dealloc {
    40 -(void) dealloc {
    46     [gameConfig release];
    41     [gameConfig release];
    47     [systemSettings release];
    42     [systemSettings release];
    48     [super dealloc];
    43     [super dealloc];
    49 }
    44 }
   233 }
   228 }
   234 
   229 
   235 // method that handles net setup with engine and keeps connection alive
   230 // method that handles net setup with engine and keeps connection alive
   236 -(void) engineProtocol {
   231 -(void) engineProtocol {
   237     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   232     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
   233     TCPsocket sd;
   238     IPaddress ip;
   234     IPaddress ip;
   239     int eProto;
   235     int eProto;
   240     BOOL clientQuit, serverQuit;
   236     BOOL clientQuit;
   241     char buffer[BUFFER_SIZE], string[BUFFER_SIZE];
   237     char buffer[BUFFER_SIZE];
   242     uint8_t msgSize;
   238     uint8_t msgSize;
   243     uint16_t gameTicks;
   239     uint16_t gameTicks;
   244 
   240     
   245     serverQuit = NO;
   241     clientQuit = NO;
       
   242     csd = NULL;
   246 
   243 
   247     if (SDLNet_Init() < 0) {
   244     if (SDLNet_Init() < 0) {
   248         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
   245         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
   249         serverQuit = YES;
   246         clientQuit = YES;
   250     }
   247     }
   251     
   248     
   252     // Resolving the host using NULL make network interface to listen
   249     // Resolving the host using NULL make network interface to listen
   253     if (SDLNet_ResolveHost(&ip, NULL, ipcPort) < 0) {
   250     if (SDLNet_ResolveHost(&ip, NULL, ipcPort) < 0 && !clientQuit) {
   254         DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
   251         DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
   255         serverQuit = YES;
   252         clientQuit = YES;
   256     }
   253     }
   257     
   254     
   258     // Open a connection with the IP provided (listen on the host's port) 
   255     // Open a connection with the IP provided (listen on the host's port) 
   259     if (!(sd = SDLNet_TCP_Open(&ip))) {
   256     if (!(sd = SDLNet_TCP_Open(&ip)) && !clientQuit) {
   260         DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), ipcPort);
   257         DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), ipcPort);
   261         serverQuit = YES;
   258         clientQuit = YES;
   262     }
   259     }
   263     
   260     
   264     DLog(@"Waiting for a client on port %d", ipcPort);
   261     DLog(@"Waiting for a client on port %d", ipcPort);
   265     while (!serverQuit) {
   262     while (csd == NULL) 
   266         // This check the sd if there is a pending connection.
       
   267         // If there is one, accept that, and open a new socket for communicating
       
   268         csd = SDLNet_TCP_Accept(sd);
   263         csd = SDLNet_TCP_Accept(sd);
   269         if (NULL != csd) {
   264     SDLNet_TCP_Close(sd);
   270             // Now we can communicate with the client using csd socket
   265     
   271             // sd will remain opened waiting other connections
   266     while (!clientQuit) {
   272             DLog(@"client found");
   267         msgSize = 0;
   273             
   268         memset(buffer, 0, BUFFER_SIZE);
   274             //first byte of the command alwayas contain the size of the command
   269         if (SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)) <= 0)
   275             SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t));
   270             clientQuit = YES;
   276             
   271         if (SDLNet_TCP_Recv(csd, buffer, msgSize) <=0)
   277             SDLNet_TCP_Recv(csd, buffer, msgSize);
   272             clientQuit = YES;
   278             gameTicks = SDLNet_Read16 (&buffer[msgSize - 2]);
   273         
   279             //DLog(@"engineProtocol - %d: received [%s]", gameTicks, buffer);
   274         switch (buffer[0]) {
   280             
   275             case 'C':
   281             if ('C' == buffer[0]) {
       
   282                 DLog(@"sending game config");
   276                 DLog(@"sending game config");
   283                 
   277                 
   284                 // local game
   278                 // local game
   285                 [self sendToEngine:@"TL"];
   279                 [self sendToEngine:@"TL"];
   286                 
   280                 
   287                 // seed info
   281                 // seed info
   288                 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]];
   282                 [self sendToEngine:[self.gameConfig objectForKey:@"seed_command"]];
   289 
   283                 
   290                 // dimension of the map
   284                 // dimension of the map
   291                 [self sendToEngine:[self.gameConfig objectForKey:@"templatefilter_command"]];
   285                 [self sendToEngine:[self.gameConfig objectForKey:@"templatefilter_command"]];
   292                 [self sendToEngine:[self.gameConfig objectForKey:@"mapgen_command"]];
   286                 [self sendToEngine:[self.gameConfig objectForKey:@"mapgen_command"]];
   293                 [self sendToEngine:[self.gameConfig objectForKey:@"mazesize_command"]];
   287                 [self sendToEngine:[self.gameConfig objectForKey:@"mazesize_command"]];
   294 
   288                 
   295                 // theme info
   289                 // theme info
   296                 [self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]];
   290                 [self sendToEngine:[self.gameConfig objectForKey:@"theme_command"]];
   297                 
   291                 
   298                 // scheme (returns initial health)
   292                 // scheme (returns initial health)
   299                 NSInteger health = [self provideScheme:[self.gameConfig objectForKey:@"scheme"]];
   293                 NSInteger health = [self provideScheme:[self.gameConfig objectForKey:@"scheme"]];
   304                                   forHogs:[[teamData objectForKey:@"number"] intValue]
   298                                   forHogs:[[teamData objectForKey:@"number"] intValue]
   305                                withHealth:health
   299                                withHealth:health
   306                                   ofColor:[teamData objectForKey:@"color"]];
   300                                   ofColor:[teamData objectForKey:@"color"]];
   307                 }
   301                 }
   308                 
   302                 
   309                 [self provideAmmoData:@"Default.plist" forPlayingTeams:[teamsConfig count]];
   303                 [self provideAmmoData:[self.gameConfig objectForKey:@"weapon"] forPlayingTeams:[teamsConfig count]];
   310                 
   304                 
   311                 clientQuit = NO;
   305                 clientQuit = NO;
   312             } else {
   306                 break;
   313                 DLog(@"wrong message or client closed connection");
   307             case '?':
       
   308                 // without this sleep sometimes frontend replies before engine has processed any flag (resulting in an error)
       
   309                 [NSThread sleepForTimeInterval:0.4];
       
   310                 DLog(@"Ping? Pong!");
       
   311                 [self sendToEngine:@"!"];
       
   312                 break;
       
   313             case 'E':
       
   314                 DLog(@"ERROR - last console line: [%s]", &buffer[1]);
   314                 clientQuit = YES;
   315                 clientQuit = YES;
   315             }
   316                 break;
   316             
   317             case 'e':
   317             while (!clientQuit){
   318                 sscanf(buffer, "%*s %d", &eProto);
   318                 msgSize = 0;
   319                 short int netProto = 0;
   319                 memset(buffer, 0, BUFFER_SIZE);
   320                 char *versionStr;
   320                 memset(string, 0, BUFFER_SIZE);
   321                 
   321                 if (SDLNet_TCP_Recv(csd, &msgSize, sizeof(uint8_t)) <= 0)
   322                 HW_versionInfo(&netProto, &versionStr);
       
   323                 if (netProto == eProto) {
       
   324                     DLog(@"Setting protocol version %d (%s)", eProto, versionStr);
       
   325                 } else {
       
   326                     DLog(@"ERROR - wrong protocol number: [%s] - expecting %d", &buffer[1], eProto);
   322                     clientQuit = YES;
   327                     clientQuit = YES;
   323                 if (SDLNet_TCP_Recv(csd, buffer, msgSize) <=0)
   328                 }
   324                     clientQuit = YES;
   329                 
   325                 
   330                 break;
   326                 gameTicks = SDLNet_Read16(&buffer[msgSize - 2]);
   331             case 'i':
   327                 //DLog(@"engineProtocolThread - %d: received [%s]", gameTicks, buffer);
   332                 switch (buffer[1]) {
   328                 
   333                     case 'r':
   329                 switch (buffer[0]) {
   334                         NSLog(@"Winning team: %s", &buffer[2]);
   330                     case '?':
       
   331                         DLog(@"Ping? Pong!");
       
   332                         [self sendToEngine:@"!"];
       
   333                         break;
   335                         break;
   334                     case 'E':
   336                     case 'k':
   335                         DLog(@"ERROR - last console line: [%s]", buffer);
   337                         NSLog(@"Best Hedgehog: %s", &buffer[2]);
   336                         clientQuit = YES;
       
   337                         break;
   338                         break;
   338                     case 'e':
       
   339                         sscanf(buffer, "%*s %d", &eProto);
       
   340                         short int netProto = 0;
       
   341                         char *versionStr;
       
   342                         
       
   343                         HW_versionInfo(&netProto, &versionStr);
       
   344                         if (netProto == eProto) {
       
   345                             DLog(@"Setting protocol version %d (%s)", eProto, versionStr);
       
   346                         } else {
       
   347                             DLog(@"ERROR - wrong protocol number: [%s] - expecting %d", buffer, eProto);
       
   348                             clientQuit = YES;
       
   349                         }
       
   350                         
       
   351                         break;
       
   352                     case 'i':
       
   353                         switch (buffer[1]) {
       
   354                             case 'r':
       
   355                                 NSLog(@"Winning team: %s", &buffer[2]);
       
   356                                 break;
       
   357                             case 'k':
       
   358                                 NSLog(@"Best Hedgehog: %s", &buffer[2]);
       
   359                                 break;
       
   360                         }
       
   361                         break;
       
   362                     default:
       
   363                         // empty packet or just statistics
       
   364                         break;
       
   365                     // missing case for exiting right away
       
   366                 }
   339                 }
   367             }
   340                 break;
   368             DLog(@"Engine exited, closing server");
   341             default:
   369             // wait a little to let the client close cleanly
   342                 // empty packet or just statistics -- in either cases gameTicks is sent
   370             [NSThread sleepForTimeInterval:2];
   343                 //gameTicks = SDLNet_Read16 (&buffer[msgSize - 2]);
   371             // Close the client socket
   344                 //DLog(@"engineProtocol - %d: received [%s]", gameTicks, buffer);
   372             SDLNet_TCP_Close(csd);
   345                 break;
   373             serverQuit = YES;
       
   374         }
   346         }
   375     }
   347     }
   376     
   348     DLog(@"Engine exited, closing server");
   377     SDLNet_TCP_Close(sd);
   349     // wait a little to let the client close cleanly
       
   350     [NSThread sleepForTimeInterval:2];
       
   351     // Close the client socket
       
   352     SDLNet_TCP_Close(csd);    
   378     SDLNet_Quit();
   353     SDLNet_Quit();
   379 
   354     
   380     [[NSFileManager defaultManager] removeItemAtPath:GAMECONFIG_FILE() error:NULL];
   355     [[NSFileManager defaultManager] removeItemAtPath:GAMECONFIG_FILE() error:NULL];
   381     
   356     
   382     [pool release];
   357     [pool release];
   383     //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.
   358     //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.
   384     //[NSThread exit];
   359     //[NSThread exit];