Comm/ServerReader.m

00001 //-------------------------------------------
00002 // File:  ServerReader.m
00003 // Class: ServerReader
00004 // 
00005 // Created by Chris Lukassen 
00006 // Copyright (c) 2006 Luky Soft
00007 //-------------------------------------------
00008  
00009 #import "ServerReader.h"
00010 #import "PacketTypesDebug.h"
00011  
00012  
00013 @implementation ServerReader
00014 
00015 // some globals
00016 int NUMOFBITS = {
00017     0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
00018     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 
00019     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 
00020     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
00021     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 
00022     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
00023     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
00024     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
00025     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 
00026     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
00027     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
00028     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
00029     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 
00030     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
00031     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 
00032     4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
00033 };  
00034 // sizes of variable torpbuffers 
00035 int VTSIZE = {
00036     4, 8, 8, 12, 12, 16, 20, 20, 24
00037 };        
00038 // 4 byte Header + torpdata
00039 int VTISIZE = {
00040     4, 7, 9, 11, 13, 16, 18, 20, 22
00041 };
00042 //-
00043 int PACKET_SIZES = {
00044     0,          // NULL
00045     84,         // SP_MESSAGE
00046     4,          // SP_PLAYER_INFO
00047     8,          // SP_KILLS
00048     12,         // SP_PLAYER
00049     8,          // SP_TORP_INFO
00050     12,         // SP_TORP
00051     16,         // SP_PHASER
00052     8,          // SP_PLASMA_INFO
00053     12,         // SP_PLASMA
00054     84,         // SP_WARNING
00055     84,         // SP_MOTD
00056     32,         // SP_YOU
00057     4,          // SP_QUEUE
00058     28,         // SP_STATUS
00059     12,         // SP_PLANET
00060     4,          // SP_PICKOK
00061     104,                // SP_LOGIN
00062     8,          // SP_FLAGS
00063     4,          // SP_MASK
00064     4,          // SP_PSTATUS
00065     4,          // SP_BADVERSION
00066     4,          // SP_HOSTILE
00067     56,         // SP_STATS
00068     52,         // SP_PL_LOGIN
00069     20,         // SP_RESERVED
00070     28,         // SP_PLANET_LOC
00071     0,          // SP_SCAN
00072     8,          // SP_UDP_REPLY
00073     4,          // SP_SEQUENCE
00074     4,          // SP_SC_SEQUENCE
00075     36,         // SP_RSA_KEY
00076     12,         // SP_MOTD_PIC
00077     0,          // 33
00078     0,          // 34
00079     0,          // 35
00080     0,          // 36
00081     0,          // 37
00082     0,          // 38
00083     60,         // SP_SHIP_CAP
00084     8,          // SP_S_REPLY
00085     -1,         // SP_S_MESSAGE
00086     -1,         // SP_S_WARNING
00087     12,         // SP_S_YOU
00088     12,         // SP_S_YOU_SS
00089     -1,         // SP_S_PLAYER
00090     8,          // SP_PING
00091     -1,         // SP_S_TORP
00092     -1,         // SP_S_TORP_INFO
00093     20,         // SP_S_8_TORP
00094     -1,         // SP_S_PLANET
00095     0,          // 51
00096     0,          // 52
00097     0,          // 53
00098     0,          // 54
00099     0,          // 55
00100     0,          // SP_S_SEQUENCE
00101     -1,         // SP_S_PHASER
00102     -1,         // SP_S_KILLS
00103     36,         // SP_S_STATS
00104     88,         // SP_FEATURE
00105     524         // SP_BITMAP
00106 };
00107 
00108 PacketTypesDebug *pktConv;
00109 NSMutableData *leftOverPacket;
00110 
00111 - (id) init {
00112     self = [super init];
00113     if (self != nil) {
00114         // packet debugger
00115         pktConv = [[PacketTypesDebug alloc] init];
00116         [pktConv setDebugPackets:NO];
00117         leftOverPacket = nil;
00118         // number of bits per byte
00119 
00120         // parsing message of the day
00121         motd_done = NO;
00122         // need this frequently
00123         notificationCenter = [LLNotificationCenter defaultCenter];
00124 
00125     }
00126     return self;
00127 }
00128 
00129 - (id)initWithUniverse:(Universe*)newUniverse communication:(Communication*)comm {
00130     self = [self init];
00131     if (self != nil) {
00132         universe = newUniverse;
00133         [universe retain];
00134         communication = comm;
00135     }
00136     return self;
00137 }
00138 
00139 - (void) close {
00140     NSLog(@"ServerReader.close this should have been overwritten");
00141 }
00142 
00143 - (NSData *) doRead {
00144     NSLog(@"ServerReader.doRead this should have been overwritten");
00145     return nil;
00146 }
00147 
00148 - (void) readFromServer {
00149     
00150     NSData *dataReceived = [self doRead];
00151     if (dataReceived == nil) {  
00152         return;
00153     }
00154     
00155     int count = 0;
00156     char *buffer = nil;
00157     
00158     // check for leftovers
00159     if (leftOverPacket != nil) {
00160         //NSLog(@"ServerReader.readFromServer pre-pending %d bytes", [leftOverPacket length]);
00161         [leftOverPacket appendData:dataReceived];
00162         
00163         count = [leftOverPacket length];
00164         buffer = (char*)[leftOverPacket bytes];
00165 
00166     } else {
00167         count = [dataReceived length];
00168         buffer = (char*)[dataReceived bytes];
00169     }
00170   
00171     /*
00172     NSLog(@"ServerReader.readFromServer raw block read start:");
00173     [pktConv printPacketInBuffer:buffer size:count];
00174     NSLog(@"ServerReader.readFromServer raw block read end");
00175     */
00176     
00177     while(count > 0)  {
00178         // the first char in the buffer should tell us the type of the message
00179         int ptype = buffer & 0xFF;
00180         if(ptype < 1 || ptype > SP_BITMAP) {
00181             
00182             // debug THIS we want to see!
00183             NSLog(@"ServerReader.readFromServer received message: %@ (%d), count: %d", 
00184                   [pktConv serverPacketString:buffer[0]], buffer[0], count);
00185             bool oldSetting = [pktConv debugPackets];
00186             [pktConv setDebugPackets:YES];
00187             [pktConv printPacketInBuffer:buffer size:count];
00188             [pktConv setDebugPackets:oldSetting];
00189             
00190             // continue
00191             NSLog(@"ServerReader.readFromServer: Unknown packet type. Flushing packet buffer & input stream.");
00192             NSLog([NSString stringWithFormat:@"ServerReader.readFromServer: Last packet type: %d", ptype]);
00193             // flush
00194             count = 0;
00195             buffer = nil;
00196             [leftOverPacket release];
00197             return;
00198         }
00199         
00200         int size = PACKET_SIZES;
00201         // debug 
00202         //NSLog(@"ServerReader.readFromServer received message: %@ (%d), size %d buffer size: %d", 
00203         //      [pktConv serverPacketString:buffer[0]], buffer[0], size, count);
00204         [pktConv printPacketInBuffer:buffer size:size];
00205         
00206         // handle variable buffer packets first
00207         // determine the size of the packet before we can handle it
00208                 if (size == -1) {
00209             if(count < 4) {
00210                 NSLog(@"ServerReader.readFromServer: variable buffer too small");
00211                                 return;
00212             }
00213             
00214             switch(ptype) {
00215                                 case SP_S_MESSAGE:
00216                                         size = buffer & 0xFF;
00217                                         break;
00218                                 case SP_S_WARNING:
00219                                         if(buffer[1] == STEXTE_STRING ||
00220                        buffer[1] == SHORT_WARNING) {                                            
00221                                                 size = buffer & 0xFF;
00222                                         } 
00223                                         else {
00224                                                 size = 4;       // Normal Packet
00225                                         }
00226                                         break;
00227                                 case SP_S_PLAYER:
00228                                         if((buffer[1] & 0x80) != 0) { 
00229                                                 // Small + extended Header
00230                                                 size = (buffer & 0x3F) * 4 + 4;                                                 
00231                                         } 
00232                                         else if((buffer[1] & 0x40) != 0) {      
00233                                                 // Small Header
00234                                                 if ([communication shortVersion] == SHORTVERSION) {
00235                                                         size = (buffer & 0x3F) * 4 + 4 + (buffer[2] & 0xFF) * 4;
00236                                                 }
00237                                                 else {
00238                                                         size = (buffer & 0x3F) * 4 + 4;
00239                                                 }
00240                                         } 
00241                                         else {  
00242                                                 // Big Header
00243                                                 size = (buffer & 0xFF) * 4 + 12;
00244                                         }
00245                                         break;
00246                                 case SP_S_TORP:
00247                                         size = VTSIZE;
00248                                         break;
00249                                 case SP_S_TORP_INFO :
00250                                         size = VTISIZE + NUMOFBITS[buffer & 0xFF];
00251                                         break;
00252                                 case SP_S_PLANET:
00253                                         size = (buffer & 0xFF) * 6 + 2;
00254                                         break;
00255                                 case SP_S_PHASER:       // S_P2
00256                                         switch(buffer[1] & 0x0F) {
00257                                         case PHASER_FREE :
00258                                         case PHASER_HIT :
00259                                         case PHASER_MISS :
00260                                            size = 4;
00261                                            break;
00262                                         case PHASER_HIT2 :
00263                                            size = 8;
00264                                            break;
00265                                         default:
00266                                            size = 12;
00267                                            break;
00268                                         }
00269                                         break;
00270                                 case SP_S_KILLS :
00271                                         size = (buffer & 0xFF) * 2 + 2;
00272                                         break;
00273                                 default:                                        
00274                                         NSLog([NSString stringWithFormat:@"ServerReader.readFromServer: Unknown variable buffer: %c", ptype]);
00275                                         return;
00276             }
00277             // stuff some bits to make it fit in an integer
00278                         if ((size % 4) != 0) {
00279                 size += (4 - (size % 4));
00280             }
00281             if (size <= 0) {
00282                 NSLog([NSString stringWithFormat:@"ServerReader.readFromServer: bad size: %d", size]);
00283                                 NSLog([NSString stringWithFormat:@"ServerReader.readFromServer: for packet type: %c", ptype]);
00284                                 return;
00285             }
00286         }
00287         
00288         // we have the size and the packettype, now handle it
00289         if(count < size) {
00290             //NSLog(@"ServerReader.readFromServer message %d only %d of %d bytes in buffer, preserving", ptype, count, size);
00291             [leftOverPacket release];
00292             leftOverPacket = [NSMutableData dataWithBytes:buffer length:count];
00293             [leftOverPacket retain];
00294                         return;
00295         }               
00296         
00297         // during the handling we cannot allow others to modify or access
00298         // the universal data
00299         [[universe synchronizeAccess] lock];
00300         // directly unlock, we wait for the painter, but the painter does not wait for us
00301         [[universe synchronizeAccess] unlock];
00302         bool result = [self handlePacket:ptype withSize:size inBuffer:buffer];
00303         //[[universe synchronizeAccess] unlock];
00304         
00305         if (result) {
00306             // successfull? then on to the next
00307             count -= size;
00308             
00309             // move on!
00310             buffer += size;
00311         } else {
00312             NSLog(@"ServerReader.readFromServer packet %d was not handled correctly", buffer[0]);
00313         }
00314         
00315         // exact fit in frame, no leftover
00316         [leftOverPacket release];
00317         leftOverPacket = nil;
00318 
00319     }
00320 }
00321 
00322 
00323 /*******************************************/
00324 /* support functions, direct copy from COW */
00325 /*******************************************/
00326 
00328 int intFromPacket(char *buffer, int offset) {
00329         return (buffer[offset] & 0xFF) << 24 | (buffer & 0xFF) << 16 
00330     | (buffer[offset + 2] & 0xFF) << 8 | buffer & 0xFF;
00331 }
00332 
00334 int shortFromPacket(char *buffer, int offset) { 
00335         return (buffer[offset] & 0xFF) << 8 | buffer & 0xFF;
00336 }
00337 
00339 -(void) newFlags:(int)dat target:(int)which {
00340     int status;
00341     int new_flags_set;
00342     Player *player;
00343     for(int pnum = which * 16; pnum < (which + 1) * 16 && pnum < [universe playerCount]; ++pnum) {
00344         
00345         new_flags_set = dat & 0x03;
00346         dat >>= 2;
00347         
00348         player = [universe playerWithId: pnum];
00349         if([player status] == PLAYER_FREE) {
00350             continue;
00351         }
00352         
00353         switch(new_flags_set) {
00354                         case 0 :        // DEAD/EXPLODE
00355                                 status = PLAYER_EXPLODE;
00356                                 [player setFlags: [player flags] & ~PLAYER_CLOAK];
00357                                 break;
00358                         case 1 :        // ALIVE & CLOAK
00359                                 status = PLAYER_ALIVE;
00360                                 [player setFlags: [player flags] | PLAYER_CLOAK];
00361                                 break;
00362                         case 2 :        // ALIVE & SHIELD
00363                                 status = PLAYER_ALIVE;
00364                                 [player setFlags: [player flags] | PLAYER_SHIELD];
00365                                 [player setFlags: [player flags] & ~PLAYER_CLOAK];
00366                                 break;
00367                         case 3 :        // ALIVE & NO shields
00368                                 status = PLAYER_ALIVE;
00369                                 [player setFlags: [player flags] & ~(PLAYER_SHIELD | PLAYER_CLOAK)];
00370                                 break;
00371                         default:
00372                                 status = 0;
00373                                 break;
00374         }
00375         
00376         if ([player status] == status) {
00377             continue;
00378         }
00379         
00380         if (status == PLAYER_EXPLODE) {
00381             if ([player status] == PLAYER_ALIVE) {
00382                 [player setExplode: 0];
00383                 [player setStatus: status];
00384             }
00385         } 
00386         else {
00387             if([player isMe]) {
00388                 // Wait for PLAYER_OUTFIT $$
00389                                 // i wonder if this is correct! PLAYER_OUTFIT should generate a 
00390                                 // [notificationCenter postNotificationName:@"CC_GO_OUTFIT"     object:self userInfo:nil];
00391                                 // to get the outfit panel again
00392                 if ([player status] == PLAYER_OUTFIT || [player status] == PLAYER_FREE) {
00393                     [player setStatus: PLAYER_ALIVE];
00394                 }
00395             }
00396             else {
00397                 [player setStatus: status];                     
00398             }
00399         }
00400     }
00401 }       
00402 
00403 
00404 // too big to be in switch
00405 -(void) handleUdpReply:(char*) buffer {
00406     
00407     NSLog([NSString stringWithFormat:@"ServerReader.handleUdpReply: UDP: Received UDP reply %c", (buffer[1])]);
00408     
00409     switch (buffer[1] & 0xFF) {
00410         case SWITCH_TCP_OK:
00411             if ([communication commMode] == COMM_TCP) {
00412                 NSLog(@"ServerReader.handleUdpReply: Got SWITCH_TCP_OK while in TCP mode; ignoring");
00413             }
00414             else {
00415                 [communication setCommMode: COMM_TCP];
00416                 [communication setCommStatus: STAT_CONNECTED];
00417                 NSLog(@"ServerReader.handleUdpReply: Connected to server's TCP port");
00418                                 // close UDP in comm
00419                 [notificationCenter postNotificationName:@"SP_UDP_SWITCHED_TO_TCP" object:self userInfo:nil];
00420             }
00421             break;
00422         case SWITCH_UDP_OK:
00423             if ([communication commMode] == COMM_UDP) {
00424                 NSLog(@"ServerReader.handleUdpReply: Got SWITCH_UDP_OK while in UDP mode; ignoring");
00425             }
00426             else {
00427                 // the server is forcing UDP down our throat?
00428                 if ([communication commModeRequest] != COMM_UDP) {
00429                     NSLog(@"ServerReader.handleUdpReply: Got unsolicited SWITCH_UDP_OK; ignoring");
00430                 }
00431                 else {
00432                     NSLog(@"ServerReader.handleUdpReply: Connected to server's UDP port");
00433                     [communication setCommMode: COMM_UDP];
00434                     [communication setCommStatus: STAT_VERIFY_UDP];    
00435                     int port = intFromPacket(buffer, 4);
00436                     /* the following should be done by the comm class upon receiving the event 
00437                         comm.connUdpConn(); comm.sendUdpVerify(); */
00438                                         [communication connectToServerUsingPort:port]; // should be event trigger but this is soo much
00439                                                                                                                                    // easier
00440                     [notificationCenter postNotificationName:@"SP_TCP_SWITCHED_TO_UDP" 
00441                                                       object:self 
00442                                                     userInfo:[NSNumber numberWithInt:port]];
00443                 }
00444             }
00445             break;
00446         case SWITCH_DENIED:     
00447             // look for some scary bits in the reason byte
00448             if (intFromPacket(buffer, 4) == 0) {
00449                 NSLog(@"ServerReader.handleUdpReply: Switch to UDP failed (different version)");
00450             }
00451             else {
00452                 NSLog(@"ServerReader.handleUdpReply: Switch to UDP denied");
00453             }
00454             // reset mode request to org mode
00455             [communication setCommModeRequest:[communication commMode]];
00456             [communication setCommStatus: STAT_CONNECTED];
00457             /* communication should close the udp on reception of the event
00458             actually, it is strange because you do not know if you switched to TCP or UDP.....
00459             comm.closeUdpConn(); */
00460             [notificationCenter postNotificationName:@"SP_SWITCHED_DENIED" object:self userInfo:nil];            
00461             break;
00462         case SWITCH_VERIFY:
00463             [notificationCenter postNotificationName:@"SP_SWITCH_VERIFY" object:self userInfo:nil];
00464             NSLog(@"ServerReader.handleUdpReply: Received UDP verification");
00465             // This is here because I noticed player stats weren't being 
00466             // updated unless I sent this request manually
00467             [notificationCenter postNotificationName:@"SP_ASK_FOR_COMM_UPDATE" object:self userInfo:nil];
00468                         break;
00469         default:
00470             NSLog([NSString stringWithFormat: @"ServerReader.handleUdpReply: Got funny reply (%c) in UDP_REPLY packet",
00471                 (buffer[1])]);
00472             break;
00473     }
00474 }
00475 
00476 
00477 // way too big for switch
00478 // even too big for one method, moved some to newFlags
00479 -(void) handleVPlayer:(char *)buffer {
00480     int x, y, player_index, save;
00481     Player *player;
00482     int numofplayers = buffer & 0x3F;
00483     
00484     int pos = 0;
00485     
00486     // $$$ CORRUPTED_PACKETS
00487     // should do something clever here - jmn if(pl_no < 0 || pl_no >= MAXPLAYER){ return; }
00488     
00489     // $$ MAXPLAYER > 32 WAS HERE
00490     if ((buffer[1] & 0x40) != 0) {                                                              // Short Header
00491         if ([communication shortVersion] == SHORTVERSION) {                             // flags S_P2
00492             if (buffer[2] == 2) {
00493                 [self newFlags: intFromPacket(buffer, 4) target:buffer & 0xFF];
00494                 [self newFlags: intFromPacket(buffer, 8) target: 0];
00495                 pos += 8;
00496             }
00497             else if (buffer[2] == 1) {
00498                 [self newFlags: intFromPacket(buffer, 4) target: buffer & 0xFF];
00499                 pos += 4;
00500             }
00501         }
00502         pos += 4;
00503         for(int p = 0; p < numofplayers; p++) {
00504             player_index = buffer & 0x1F;
00505             if(player_index >= [universe playerCount]) {
00506                 continue;
00507             }
00508             save = buffer;
00509             pos++;
00510             player = [universe playerWithId:player_index];
00511             
00512             // SPEED
00513             [player setSpeed: (buffer & 0x0F)];
00514             // freaky bit stuff
00515             FeatureList *fList = [communication featureList];                
00516             if([player isMe] && [fList valueForFeature: FEATURE_LIST_CLOAK_MAXWARP] != FEATURE_OFF) {
00517                 if([player speed] == 0xF) {
00518                     [player setFlags: [player flags] | PLAYER_CLOAK];
00519                 }
00520                 else if(([player flags] & PLAYER_CLOAK) != 0) {
00521                     [player setFlags: [player flags] & ~PLAYER_CLOAK];
00522                 }
00523             }
00524             
00525             // realDIR
00526             [player setNetrekFormatCourse: ((buffer & 0xFF) >> 4) * 16];
00527             pos++;
00528             x = buffer & 0xFF;
00529             pos++;
00530             y = buffer & 0xFF;
00531             pos++;
00532             
00533             // The lower 8 Bits are saved
00534             // Now we must preprocess the coordinates
00535             NSPoint position;
00536             if((save & 0x40) != 0) {
00537                 x |= 0x100;
00538             }
00539             if((save & 0x80) != 0) {
00540                 y |= 0x100;
00541             }
00542             // Now test if it's galactic or local coord
00543             if((save & 0x20) != 0) { 
00544                 // It's galactic
00545                 if (x == 501 || y == 501) {
00546                     x = -500;
00547                     y = -500;
00548                 }
00549                 
00550                 // galactic coordinates are global
00551                 position.x = x * (UNIVERSE_PIXEL_SIZE / SPWINSIDE);
00552                 position.y = y * (UNIVERSE_PIXEL_SIZE / SPWINSIDE);
00553             }
00554             else { 
00555                 // Local coordinates are relative to my position
00556                 // recalculate to galactic
00557                 Player *me = [universe playerThatIsMe];
00558                 NSPoint myPos = [me position];
00559                 position.x = myPos.x + ((x - SPWINSIDE / 2) * UNIVERSE_SCALE);
00560                 position.y = myPos.y + ((y - SPWINSIDE / 2) * UNIVERSE_SCALE);
00561             }            
00562             [player setPosition:position];
00563             /*
00564              Point point = Rotate.rotateCoord(
00565                                               player.x,
00566                                               player.y,
00567                                               data.rotate,
00568                                               Universe.HALF_PIXEL_SIZE,
00569                                               Universe.HALF_PIXEL_SIZE);
00570              
00571              player.x = point.x;
00572              player.y = point.y;
00573              
00574              player.dir = Rotate.rotateDir(player.dir, data.rotate);
00575              */
00576             [notificationCenter postNotificationName:@"SP_V_PLAYER" object:self userInfo:player];     
00577         }
00578     }
00579     else { // Big Packet
00580         
00581         player = [universe playerThatIsMe];
00582         [player setNetrekFormatCourse:buffer & 0xFF];
00583         [player setSpeed: buffer & 0xFF];
00584         
00585         // freaky bit stuff
00586         FeatureList *fList = [communication featureList];                
00587         if([fList valueForFeature: FEATURE_LIST_CLOAK_MAXWARP] != FEATURE_OFF) {
00588             if([player speed] == 0xF) {
00589                 [player setFlags: [player flags] | PLAYER_CLOAK];
00590             }
00591             else if(([player flags] & PLAYER_CLOAK) != 0) {
00592                 [player setFlags: [player flags] & ~PLAYER_CLOAK];
00593             }
00594         }
00595         
00596         NSPoint position;
00597         if ([communication shortVersion] == SHORTVERSION) {     // S_P2            
00598             position.x = UNIVERSE_SCALE * shortFromPacket(buffer, 4);
00599             position.y = UNIVERSE_SCALE * shortFromPacket(buffer, 6);            
00600             [self newFlags: intFromPacket(buffer, 8) target: 0];
00601         }
00602         else {  // OLDSHORTVERSION
00603             position.x = intFromPacket(buffer, 4);
00604             position.y = intFromPacket(buffer, 8);
00605         }
00606         [player setPosition:position];
00607         
00608         /*
00609          Point point = Rotate.rotateCoord(
00610                                           player.x,
00611                                           player.y,
00612                                           data.rotate,
00613                                           Universe.HALF_PIXEL_SIZE,
00614                                           Universe.HALF_PIXEL_SIZE);
00615          
00616          player.x = point.x;
00617          player.y = point.y;
00618          
00619          player.dir = Rotate.rotateDir(player.dir, data.rotate); 
00620          */
00621         
00622         if (buffer[1] == 0) {
00623             return;
00624         }
00625         pos += 12;
00626         
00627         // Now the small packets
00628         for(int p = 0; p < [universe playerCount]; ++p) {
00629             player_index = buffer & 0x1F;
00630             if (player_index >= [universe playerCount]) {
00631                 continue;
00632             }
00633             save = buffer;
00634             pos++;
00635             player = [universe playerWithId:player_index];
00636                         
00637             // SPEED
00638             [player setSpeed: buffer & 0xFF];
00639             
00640             // freaky bit stuff
00641             FeatureList *fList = [communication featureList];                
00642             if([player isMe] && [fList valueForFeature: FEATURE_LIST_CLOAK_MAXWARP] != FEATURE_OFF) {
00643                 if([player speed] == 0xF) {
00644                     [player setFlags: [player flags] | PLAYER_CLOAK];
00645                 }
00646                 else if(([player flags] & PLAYER_CLOAK) != 0) {
00647                     [player setFlags: [player flags] & ~PLAYER_CLOAK];
00648                 }
00649             }
00650             
00651             // realDIR
00652             [player setNetrekFormatCourse: ((buffer & 0xFF) >> 4) * 16];
00653             pos++;
00654             x = buffer & 0xFF;
00655             pos++;
00656             y = buffer & 0xFF;
00657             pos++;
00658             
00659             // The lower 8 Bits are saved
00660             // Now we must preprocess the coordinates
00661             NSPoint position;
00662             if((save & 0x40) != 0) {
00663                 x |= 0x100;
00664             }
00665             if((save & 0x80) != 0) {
00666                 y |= 0x100;
00667             }
00668             // Now test if it's galactic or local coord
00669             if((save & 0x20) != 0) { 
00670                 // It's galactic
00671                 if (x == 501 || y == 501) {
00672                     x = -500;
00673                     y = -500;
00674                 }
00675                 
00676                 // galactic coordinates are global
00677                 position.x = x * (UNIVERSE_PIXEL_SIZE / SPWINSIDE);
00678                 position.y = y * (UNIVERSE_PIXEL_SIZE / SPWINSIDE);
00679             }
00680             else { 
00681                 // Local coordinates are relative to my position
00682                 // recalculate to galactic
00683                 Player *me = [universe playerThatIsMe];
00684                 NSPoint myPos = [me position];
00685                 position.x = myPos.x + ((x - SPWINSIDE / 2) * UNIVERSE_SCALE);
00686                 position.y = myPos.y + ((y - SPWINSIDE / 2) * UNIVERSE_SCALE);
00687             }            
00688             [player setPosition:position];
00689             /*
00690              Point point = Rotate.rotateCoord(
00691                                               player.x,
00692                                               player.y,
00693                                               data.rotate,
00694                                               Universe.HALF_PIXEL_SIZE,
00695                                               Universe.HALF_PIXEL_SIZE);
00696              
00697              player.x = point.x;
00698              player.y = point.y;
00699              
00700              player.dir = Rotate.rotateDir(player.dir, data.rotate);
00701              */
00702             [notificationCenter postNotificationName:@"SP_V_PLAYER" object:self userInfo:player];   
00703         } 
00704     }
00705 }
00706 
00708 -(void) handleVTorp:(char*)buffer {
00709     
00710     int torp_index = 0;
00711     int bitset;                                         // bit=1 that torp is in packet
00712     int dx;
00713     int dy;
00714     int shiftvar;
00715     int torp_data_pos;
00716     
00717     if(buffer[0] == SP_S_8_TORP) { // MAX packet
00718         bitset = 0xFF;
00719         torp_index = (buffer & 0xFF) * 8;
00720         torp_data_pos = 2;
00721     }       
00722     else { // Normal packet
00723         bitset = buffer;
00724         torp_index = (buffer & 0xFF) * 8;
00725         torp_data_pos = 3;
00726     }
00727     
00728     int shift = 0;
00729     Torp *torp;
00730     
00731     for(int t = 0; t < 8; ++t, ++torp_index, bitset >>= 1) {
00732         torp = [universe torpWithId:torp_index];
00733         
00734         if((bitset & 0x01) != 0) {
00735             // extract the x coordinates from the bits
00736             dx = ((buffer[torp_data_pos] & 0xFF) >> shift);
00737             shiftvar = (buffer & 0xFF) << (8 - shift);
00738             dx |= (shiftvar & 0x1FF);
00739             shift++;
00740             
00741             // extract the y coordinates from the bits
00742             dy = ((buffer & 0xFF) >> shift);
00743             shiftvar = (buffer & 0xFF) << (8 - shift);
00744             dy |= (shiftvar & 0x1FF);
00745             shift++;
00746             
00747             if (shift == 8) {
00748                 shift = 0;
00749                 ++torp_data_pos;
00750             }
00751             
00752             // This is necessary because TORP_FREE/TORP_MOVE is now encoded in the bitset
00753             if ([torp status] == TORP_FREE) {
00754                 // guess
00755                 [torp setStatus: TORP_MOVE];
00756             }
00757             else if ([[torp owner] isMe] && [torp status] == TORP_EXPLODE) {
00758                 [torp setStatus: TORP_MOVE];
00759             }
00760             
00761             NSPoint pos;
00762             // Check if torp is visible
00763             if (dx > SPWINSIDE || dy > SPWINSIDE) { // Not visible
00764                 pos.x = -100000;
00765                 pos.y = -100000;
00766             }
00767             else { // visible
00768                    // Rotate coordinates
00769                 /*
00770                  Point point = Rotate.rotateCoord(
00771                                                   my_x + ((dx - SPWINSIDE / 2) * UNIVERSE_SCALE),
00772                                                   my_y + ((dy - SPWINSIDE / 2) * UNIVERSE_SCALE),
00773                                                   data.rotate,
00774                                                   Universe.HALF_PIXEL_SIZE,
00775                                                   Universe.HALF_PIXEL_SIZE);
00776                  
00777                  torp.x = point.x;
00778                  torp.y = point.y;
00779                  */
00780                 pos.x = dx;
00781                 pos.y = dy;
00782             }
00783         }
00784         else { // We got a TORP_FREE
00785             if([torp status] != TORP_FREE && [torp status] != TORP_EXPLODE) {
00786                 [torp setStatus: TORP_FREE];
00787             }
00788         }
00789         [notificationCenter postNotificationName:@"SP_V_TORP" object:self userInfo:torp];   
00790     }
00791     
00792 }
00793 
00795 - (void) handleVTorpInfo:(char*) buffer {
00796     int torp_index = 0;
00797     
00798     int dx;
00799     int dy;
00800     int shiftvar;
00801     int status;
00802     char war;
00803     
00804     int bitset = buffer & 0xFF;
00805     torp_index = (buffer & 0xFF) * 8;
00806     int infobitset = buffer & 0xFF;
00807     
00808     int torp_data_pos = 4;
00809     int info_data_pos = VTISIZE;
00810     
00811     int shift = 0;      // How many torps are extracted (for shifting)
00812     
00813     Torp *torp;
00814     
00815     for(int t = 0; t < 8; ++t, ++torp_index, bitset >>= 1, infobitset >>= 1) {
00816         torp = [universe torpWithId:torp_index];
00817         
00818         if((bitset & 0x01) != 0) {
00819             // extract the x coordinates from the bits
00820             dx = ((buffer[torp_data_pos] & 0xFF) >> shift);
00821             shiftvar = (buffer & 0xFF) << (8 - shift);
00822             dx |= (shiftvar & 0x1FF);
00823             shift++;
00824             
00825             // extract the y coordinates from the bits
00826             dy = ((buffer & 0xFF) >> shift);
00827             shiftvar = (buffer & 0xFF) << (8 - shift);
00828             dy |= (shiftvar & 0x1FF);
00829             shift++;
00830             
00831             if (shift == 8) {
00832                 shift = 0;
00833                 ++torp_data_pos;
00834             }
00835             
00836             // Check for torp with no TorpInfo ( In case we missed a n updateAll)
00837             if ((infobitset & 0x01) == 0) {
00838                 if([torp status] == TORP_FREE) {
00839                     // guess
00840                     [torp setStatus: TORP_MOVE];
00841                 } else if ([[torp owner] isMe] && [torp status] == TORP_EXPLODE) {
00842                     [torp setStatus: TORP_MOVE];
00843                 }
00844             }
00845             NSPoint pos;
00846             // Check if torp is visible
00847             if (dx > SPWINSIDE || dy > SPWINSIDE) { // Not visible
00848                 pos.x = -100000;
00849                 pos.y = -100000;
00850             }
00851             else { // visible
00852                    // Rotate coordinates
00853                 /*
00854                  Point point = Rotate.rotateCoord(
00855                                                   my_x + ((dx - SPWINSIDE / 2) * UNIVERSE_SCALE),
00856                                                   my_y + ((dy - SPWINSIDE / 2) * UNIVERSE_SCALE),
00857                                                   data.rotate,
00858                                                   Universe.HALF_PIXEL_SIZE,
00859                                                   Universe.HALF_PIXEL_SIZE);
00860                  
00861                  torp.x = point.x;
00862                  torp.y = point.y;
00863                  */
00864                 pos.x = dx;
00865                 pos.y = dy;
00866             }
00867         }
00868         else { // Got a TFREE ?
00869             if ((infobitset & 0x01) == 0) {     
00870                 // No other TorpInfo for this Torp
00871                 if([torp status] != TORP_FREE && [torp status] != TORP_EXPLODE) {
00872                     [torp setStatus: TORP_FREE];
00873                 }
00874             }
00875         }
00876         // Now the TorpInfo
00877         if((infobitset & 0x01) != 0) {
00878             war = (char)(buffer[info_data_pos] & 0xF0);
00879             status = (buffer & 0xF0) >> 4;
00880             info_data_pos++;
00881             
00882             if (status == TORP_EXPLODE && [torp status] == TORP_FREE) {
00883                 // FAT: redundant explosion; don't update p_ntorp
00884                 continue;
00885             }
00886             [torp setWar:war];
00887             if(status != [torp status]) {
00888                 // FAT: prevent explosion reset
00889                 [torp setStatus: status];
00890             }
00891         }
00892         [notificationCenter postNotificationName:@"SP_V_TORP_INFO" object:self userInfo:torp];
00893     }
00894 }
00895 
00896 -(void) handleVPlanet:(char*)buffer {
00897     int planet_index = 0;
00898     bool redraw = NO;
00899     int numofplanets = buffer & 0xFF;
00900     int ownerId;
00901     int info;
00902     int flags;
00903     int armies;
00904     Team *owner;
00905     
00906     Planet *planet;
00907     for(int pos = 2, p = 0; p < numofplanets; ++p, pos += 2) {
00908         planet_index = buffer & 0xFF;
00909         planet = [universe planetWithId: planet_index];
00910         redraw = NO;
00911         
00912         @try {
00913             // get the owner
00914             ownerId = buffer & 0xFF;
00915             owner = [universe teamWithId:[universe remappedTeamIdWithId: ownerId]];
00916             if ([planet owner] != owner) {
00917                 redraw = YES;
00918                 [universe movePlanet:planet toTeam:owner];
00919                 [owner addPlanet:planet];
00920             }
00921         }
00922         @catch (NSException * e) {
00923             NSLog([NSString stringWithFormat: @"ServerReader.handleVPlanet: planet owner out of bounds: ", ownerId]);
00924             NSLog([NSString stringWithFormat: @"ServerReader.handleVPlanet: planet : ", planet_index]);
00925             [universe movePlanet:planet toTeam:[universe teamWithId:TEAM_NOBODY]];
00926         }
00927         
00928         // get the info
00929         info = buffer & 0xFF;
00930         if ([planet info] != info) {
00931             [planet setInfo: info];
00932             if([planet info] == 0) {
00933                 [universe movePlanet:planet toTeam:[universe teamWithId:TEAM_NOBODY]];
00934             }
00935             redraw = YES;
00936         }
00937         
00938         // get the armies
00939         armies = buffer & 0xFF;
00940         if ([planet armies] != armies
00941             // don't redraw when armies change unless it crosses the '4' * army limit. 
00942             // Keeps people from watching for planet 'flicker' when players are beaming
00943             && (([planet armies] < 5 && armies > 4) || ([planet armies] > 4 && armies < 5))) {
00944             redraw = YES;
00945         }
00946         [planet setArmies: armies];
00947         
00948         // get the flags
00949         flags = shortFromPacket(buffer, ++pos);
00950         if ([planet flags] != flags) {
00951             [planet setFlags: flags];
00952             redraw = YES;
00953         }
00954         
00955         if (redraw) {
00956             [planet setFlags: ([planet flags] | PLANET_REDRAW)];
00957         }
00958         [notificationCenter postNotificationName:@"SP_V_PLANET" object:self userInfo:planet];
00959     }
00960     
00961 }
00962 
00963 -(void) handleVPhaser:(char *)buffer {
00964     
00965     int pnum = buffer & 0x3F;
00966     int x = 0;
00967     int y = 0;
00968     int dir = 0;
00969     int target = 0;   
00970     
00971     int status = buffer & 0x0F;   
00972     
00973     Phaser *phaser = [universe phaserWithId:pnum];
00974     [phaser setStatus: status];
00975     
00976     switch(status) {
00977         case PHASER_FREE:
00978             break;
00979         case PHASER_HIT:
00980             target =  buffer & 0x3F;
00981             break;
00982         case PHASER_MISS:
00983             dir = buffer & 0xFF;
00984             break;
00985         case PHASER_HIT2:
00986             x = UNIVERSE_SCALE * shortFromPacket(buffer, 4);
00987             y = UNIVERSE_SCALE * shortFromPacket(buffer, 6);
00988             target = buffer & 0x3F;
00989             break;
00990         default:
00991             x = UNIVERSE_SCALE * shortFromPacket(buffer, 4);
00992             y = UNIVERSE_SCALE * shortFromPacket(buffer, 6);
00993             target = buffer & 0x3F;
00994             dir = buffer & 0xFF;
00995             break;
00996     }
00997     
00998     NSPoint pos;                                
00999     pos.x = x;
01000     pos.y = y;
01001     [phaser setPosition:pos];
01002     [phaser setNetrekFormatCourse:dir];    
01003     
01004     if (status != PHASER_FREE) {
01005         // normalized maxfuse
01006         Ship *ship = [universe shipWithPhaserId:pnum];
01007         [phaser setMaxFuse:[ship maxPhaserFuse]];
01008     }
01009     
01010     [phaser setTarget:[universe playerWithId:target]];
01011     [phaser setFuse:0];
01012     
01013     [notificationCenter postNotificationName:@"SP_V_PHASER" object:self userInfo:phaser];
01014     
01015     /* 
01016         Point point = Rotate.rotateCoord(
01017                                          x,
01018                                          y,
01019                                          data.rotate,
01020                                          Universe.HALF_PIXEL_SIZE,
01021                                          Universe.HALF_PIXEL_SIZE);
01022      phaser.dir = Rotate.rotateDir(dir, data.rotate); */
01023     
01024     
01025 }
01026 
01027 - (void) handleSequence:(char *) buffer {
01028     NSLog(@"ServerReader.handleSequence: SP_SEQUENCE not implemented");
01029 }
01030 
01032 - (bool) handlePacket:(int)ptype withSize:(int)size inBuffer:(char *)buffer {
01033         
01034     // check some timeing
01035     //NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];   
01036     
01037     //bool result = NO;
01038                 // call the appropriate buffer handler.
01039                 switch(ptype) {
01040                 case SP_MESSAGE :
01041             @try {
01042                 NSString *message = [self stringFromBuffer:buffer startFrom:4 maxLength:80];
01043                 NSNumber *flags   = [NSNumber numberWithInt: buffer & 0xFF];
01044                 NSNumber *from    = [NSNumber numberWithInt: buffer & 0xFF];
01045                 NSNumber *to      = [NSNumber numberWithInt: buffer & 0xFF]; 
01046                 NSDictionary *obj = [NSDictionary dictionaryWithObjectsAndKeys:
01047                     message, @"message", flags, @"flags", from, @"from", to, @"to", nil];
01048                 [notificationCenter postNotificationName:@"SP_MESSAGE" object:self userInfo:obj];  
01049             }
01050             @catch (NSException * e) {
01051                 NSLog(@"ServerReader.handlePacket: SP_MESSAGE error");
01052                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01053             }        
01054                         break; 
01055                 case SP_PLAYER_INFO :
01056             @try {
01057                 int playerId = buffer; // this player
01058                 Player *player = [universe playerWithId:playerId];
01059                 int shipType = buffer; // flies this ship
01060                 Ship *ship = [universe shipOfType:shipType];
01061                 [player setShip:ship];
01062                 int teamId = [universe remappedTeamIdWithId: buffer]; // and is with this team
01063                 if (teamId > TEAM_MAX) {
01064                     NSLog(@"ServerReader.handlePacket: SP_PLAYER_INFO error team %d unknown", teamId);
01065                     break;
01066                 }
01067                 Team *team = [universe teamWithId:teamId];
01068                 [player setTeam:team];  // player is on this team
01069                 [universe movePlayer:player toTeam:team]; // so move it from the old one if needed
01070                 [notificationCenter postNotificationName:@"SP_PLAYER_INFO" object:self userInfo:player];
01071             }
01072             @catch (NSException * e) {
01073                 NSLog(@"ServerReader.handlePacket: SP_PLAYER_INFO error");
01074                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01075             }
01076                         break;
01077                 case SP_KILLS :
01078             @try {
01079                 int playerId = buffer; // this player
01080                 Player *player = [universe playerWithId:playerId];
01081                 [player setKills: ((float)intFromPacket(buffer, 4) / 100)];     
01082                 //[notificationCenter postNotificationName:@"SP_KILLS" object:self userInfo:player];
01083             }
01084             @catch (NSException * e) {
01085                 NSLog(@"ServerReader.handlePacket: SP_KILLS error"); 
01086                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01087             }
01088             break;
01089                 case SP_PLAYER :
01090             @try {                
01091                 int playerId = buffer; // this player
01092                 Player *player = [universe playerWithId:playerId];
01093                 
01094                 NSPoint pos;
01095                 pos.x = intFromPacket(buffer, 4);
01096                 pos.y = intFromPacket(buffer, 8);
01097                 
01098                 /*
01099                  // Rotate direction and coordinates
01100                  player.dir = Rotate.rotateDir(buffer[2] & 0xFF, data.rotate);
01101                  Point point = Rotate.rotateCoord(x, y, data.rotate,
01102                                                   Universe.HALF_PIXEL_SIZE, Universe.HALF_PIXEL_SIZE);
01103                  
01104                  player.x = point.x;
01105                  player.y = point.y;
01106                  */
01107                 [player setNetrekFormatCourse: (buffer & 0xFF)];
01108                 [player setPosition:pos];
01109                 [player setSpeed: (buffer & 0xFF)];
01110                 //[notificationCenter postNotificationName:@"SP_PLAYER" object:self userInfo:player];     
01111             }
01112             @catch (NSException * e) {
01113                 NSLog(@"ServerReader.handlePacket: SP_PLAYER error");
01114                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01115             }
01116             break;
01117                 case SP_TORP_INFO :
01118             @try {
01119                 Torp *torp = [universe torpWithId:shortFromPacket(buffer, 4)];
01120                 int status = buffer;
01121                 if(status != [torp status]) {
01122                     if(status == TORP_EXPLODE && [torp status] == TORP_FREE) {
01123                         return YES;
01124                     }
01125 
01126                     [torp setStatus: status];
01127                 }
01128                 int war = buffer;
01129                 [torp setWar: war];
01130                 //[notificationCenter postNotificationName:@"SP_TORP_INFO" object:self userInfo:torp];
01131             }
01132             @catch (NSException * e) {
01133                 NSLog(@"ServerReader.handlePacket: SP_TORP_INFO error");
01134                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01135             }
01136                         break;
01137                 case SP_TORP :
01138             @try {
01139                 Torp *torp = [universe torpWithId:shortFromPacket(buffer, 2)];
01140                 
01141                 NSPoint pos;
01142                 pos.x = intFromPacket(buffer, 4);
01143                 pos.y = intFromPacket(buffer, 8);
01144                     /*
01145                 // Rotate direction and coordinates
01146                 torp.dir = Rotate.rotateDir(buffer[1] & 0xFF, data.rotate);
01147                 Point point = Rotate.rotateCoord(intFromPacket(4), intFromPacket(8),
01148                                                  data.rotate, Universe.HALF_PIXEL_SIZE, Universe.HALF_PIXEL_SIZE);
01149                      */
01150                 [torp setNetrekFormatCourse: (buffer & 0xFF)];
01151                 [torp setPosition: pos];
01152                 //[notificationCenter postNotificationName:@"SP_TORP" object:self userInfo:torp];         
01153             }
01154             @catch (NSException * e) {
01155                 NSLog(@"ServerReader.handlePacket: SP_TORP error");
01156                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01157             }
01158                         break;
01159                 case SP_PHASER :
01160             @try {
01161              
01162                 int phaserId = buffer;
01163                 Phaser *phaser = [universe phaserWithId:phaserId];
01164                 
01165                 int playerId = intFromPacket(buffer, 12);
01166                 Player *target = [universe playerWithId:playerId];
01167                 
01168                 [phaser setTarget: target];
01169                 int status = buffer;
01170                 [phaser setStatus: status];
01171                 
01172                 if(status != PHASER_FREE) {
01173                     // normalized maxfuse
01174                     Ship *ship = [universe shipWithPhaserId:phaserId];
01175                     [phaser setMaxFuse:[ship maxPhaserFuse]];
01176                 }
01177                 
01178                     /*
01179                 // Rotate coordinates
01180                 phaser.dir = Rotate.rotateDir(buffer[3] & 0xFF, data.rotate);
01181                 Point point = Rotate.rotateCoord(intFromPacket(4), intFromPacket(8),
01182                                                  data.rotate, Universe.HALF_PIXEL_SIZE, Universe.HALF_PIXEL_SIZE);
01183                 */
01184                     
01185                 NSPoint pos;
01186                 pos.x = intFromPacket(buffer, 4);
01187                 pos.y = intFromPacket(buffer, 8);
01188                 [phaser setPosition: pos];
01189                     
01190                 [phaser setNetrekFormatCourse: (buffer & 0xFF)];                   
01191                     
01192                 [phaser setFuse: 0];  
01193                 //[notificationCenter postNotificationName:@"SP_PHASER" object:self userInfo:phaser];  
01194                     
01195             }
01196             @catch (NSException * e) {
01197                 NSLog(@"ServerReader.handlePacket: SP_PHASER error");
01198                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01199             }
01200                         break;
01201                 case SP_PLASMA_INFO :
01202             @try {
01203                 Plasma *plasma = [universe plasmaWithId:shortFromPacket(buffer, 4)];
01204                     int status = buffer;
01205                     if(status != [plasma status]) {
01206                         if(status == PLASMA_EXPLODE && [plasma status] == PLASMA_FREE) {
01207                             return YES;
01208                         }
01209                         [plasma setStatus: status];
01210                     }
01211                     int war = buffer;
01212                     [plasma setWar: war];
01213                     //[notificationCenter postNotificationName:@"SP_PLASMA_INFO" object:self userInfo:plasma];  
01214             }
01215             @catch (NSException * e) {
01216                 NSLog(@"ServerReader.handlePacket: SP_PLASMA_INFO error");
01217                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01218             }
01219                         break;
01220                 case SP_PLASMA :
01221             @try {
01222                 
01223                 Plasma *plasma = [universe plasmaWithId:shortFromPacket(buffer, 2)];
01224                     
01225                 NSPoint pos;
01226                 pos.x = intFromPacket(buffer, 4);
01227                 pos.y = intFromPacket(buffer, 8);
01228                     /*
01229                      // Rotate direction and coordinates
01230                      torp.dir = Rotate.rotateDir(buffer[1] & 0xFF, data.rotate);
01231                      Point point = Rotate.rotateCoord(intFromPacket(4), intFromPacket(8),
01232                                                       data.rotate, Universe.HALF_PIXEL_SIZE, Universe.HALF_PIXEL_SIZE);
01233                      */
01234                 [plasma setNetrekFormatCourse: (buffer & 0xFF)];
01235                 [plasma setPosition: pos];
01236                 //[notificationCenter postNotificationName:@"SP_PLASMA" object:self userInfo:plasma];         
01237             }
01238             @catch (NSException * e) {
01239                 NSLog(@"ServerReader.handlePacket: SP_PLASMA error");
01240                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01241             }
01242             break;
01243                 case SP_WARNING :
01244             @try {
01245                 NSString *warning = [self stringFromBuffer:buffer startFrom:4 maxLength:80];
01246                 [notificationCenter postNotificationName:@"SP_WARNING" object:self userInfo:warning];    
01247             }
01248             @catch (NSException * e) {
01249                 NSLog(@"ServerReader.handlePacket: SP_WARNING error");
01250                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01251             }
01252                         break;
01253                 case SP_MOTD :
01254             @try {
01255                 NSString *line = [self stringFromBuffer:buffer startFrom:4 maxLength:80];
01256                 if([line hasPrefix:@"\t@@@"]) {
01257                     motd_done = YES;
01258                 } 
01259                 else if(!motd_done) { // part of the message of the day
01260                     //NSLog(@"ServerReader.handlePacket: SP_MOTD: %@", line);
01261                     //[notificationCenter postNotificationName:@"SP_MOTD" object:self userInfo:line];
01262                 }
01263                 else {                // server info message
01264                     //NSLog(@"ServerReader.handlePacket: SP_MOTD: %@", line);
01265                     //[notificationCenter postNotificationName:@"SP_MOTD_SERVER_INFO" object:self userInfo:line];
01266                 }                
01267             }
01268             @catch (NSException * e) {
01269                 NSLog(@"ServerReader.handlePacket: SP_MOTD error");
01270                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01271             }
01272             break;
01273                 case SP_YOU :
01274             @try {
01275                 int ghostSlot = ([communication ghostSlot] == -1) ? buffer[1] : [communication ghostSlot];
01276                 Player *me;
01277                 if (ghostSlot == -1) {
01278                     int playerId = buffer; // this player
01279                     me = [universe playerWithId:playerId];
01280                 } else {
01281                     me = [universe playerWithId:ghostSlot];
01282                 }
01283 
01284                 [me updateHostile: buffer
01285                         stickyWar: buffer
01286                            armies: buffer
01287                             flags: intFromPacket(buffer, 8)
01288                            damage: intFromPacket(buffer, 12)
01289                    shieldStrenght: intFromPacket(buffer, 16)
01290                              fuel: intFromPacket(buffer, 20)
01291                        engineTemp: (short)shortFromPacket(buffer, 24)
01292                       weaponsTemp: (short)shortFromPacket(buffer, 26)
01293                           whyDead: (short)shortFromPacket(buffer, 28)
01294                       whoKilledMe: (short)shortFromPacket(buffer, 30)
01295                          thisIsMe: YES];
01296                 
01297                 if(([me flags] & PLAYER_PLOCK) != 0) {
01298                     if (([me flags] & PLAYER_OBSERV) != 0) {
01299                         [[universe status] setObserver:YES];
01300                     }
01301                     else {
01302                         [[universe status] setObserver:NO]; 
01303                     }
01304                 }
01305                 else {  
01306                     [[universe status] setObserver:NO];
01307                 } 
01308                 //[notificationCenter postNotificationName:@"SP_YOU" object:self userInfo:me];  
01309             }
01310             @catch (NSException * e) {
01311                 NSLog(@"ServerReader.handlePacket: SP_YOU error");
01312                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01313             }
01314             break;
01315                 case SP_QUEUE :
01316             @try {
01317                 NSNumber *queueSize = [NSNumber numberWithInt:(int)shortFromPacket(buffer, 2)];
01318                 [notificationCenter postNotificationName:@"SP_QUEUE" object:self userInfo:queueSize];
01319             }
01320             @catch (NSException * e) {
01321                 NSLog(@"ServerReader.handlePacket: SP_QUEUE error");
01322                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01323             }
01324                         break;
01325                 case SP_STATUS :
01326             @try {
01327                 Status *status = [universe status];
01328                 
01329                 [status updateTournament: (buffer != 0)
01330                             armiesBombed: intFromPacket(buffer, 4)
01331                             planetsTaken: intFromPacket(buffer, 8)
01332                                    kills: intFromPacket(buffer, 12)     
01333                                   losses: intFromPacket(buffer, 16)
01334                                     time: intFromPacket(buffer, 20)
01335                                 timeProd: intFromPacket(buffer, 24)];
01336                 //[notificationCenter postNotificationName:@"SP_STATUS" object:self userInfo:status];
01337             }
01338             @catch (NSException * e) {
01339                 NSLog(@"ServerReader.handlePacket: SP_STATUS error");
01340                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01341             }
01342             break;
01343                 case SP_PLANET :
01344             @try {                
01345                 Planet *planet = [universe planetWithId:(buffer)];
01346 
01347                 // update
01348                 [planet setInfo: (buffer)];                     
01349                 [planet setFlags: shortFromPacket(buffer, 4)];
01350                 [planet setArmies: intFromPacket(buffer, 8)];
01351                 [planet setNeedsDisplay: YES]; 
01352                 
01353                 // allocate
01354                 int teamId = [universe remappedTeamIdWithId: buffer]; 
01355                 Team *team = [universe teamWithId:teamId];
01356                 [universe movePlanet:planet toTeam:team];
01357                 [team addPlanet:planet];
01358                 
01359                 //[notificationCenter postNotificationName:@"SP_PLANET" object:self userInfo:planet];
01360             }
01361             @catch (NSException * e) {
01362                 NSLog(@"ServerReader.handlePacket: SP_PLANET error");
01363                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01364             }
01365             break;
01366                 case SP_PICKOK :
01367             @try 
01368             {
01369                 bool pickOk = (buffer != 0);
01370                 if (pickOk) {
01371                     [notificationCenter postNotificationName:@"SP_PICKOK" object:self userInfo:nil]; 
01372                 } else {
01373                     [notificationCenter postNotificationName:@"SP_PICKNOK" object:self userInfo:nil];  
01374                 }                
01375             }
01376             @catch (NSException * e) {
01377                 NSLog(@"ServerReader.handlePacket: SP_PICKOK error");
01378                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01379             }
01380             break;
01381                 case SP_LOGIN :
01382             @try {                         
01383                 // check to see if this is a paradise server
01384                 if(buffer[2] == 69 && buffer[3] == 42) {
01385                     [notificationCenter postNotificationName:@"SP_LOGIN_INVALID_SERVER" object:self userInfo:nil];
01386                     return NO;
01387                 }
01388                 Player *me = [universe playerThatIsMe];
01389                 
01390                 bool accept = (buffer != 0);
01391                 if(accept) {
01392                     [[me stats] setFlags: intFromPacket(buffer, 4)];
01393                     [notificationCenter postNotificationName:@"SP_LOGIN_ACCEPTED" object:self userInfo:me];
01394                 } else {
01395                     [notificationCenter postNotificationName:@"SP_LOGIN_NOT_ACCEPTED" object:self userInfo:nil];
01396                 }
01397             }
01398             @catch (NSException * e) {
01399                 NSLog(@"ServerReader.handlePacket: SP_LOGIN error");
01400                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01401             }
01402             break;
01403                 case SP_FLAGS :
01404             @try {
01405                 int playerId = buffer; 
01406                 Player *player = [universe playerWithId:playerId];
01407                 [player setFlags: intFromPacket(buffer, 4)]; 
01408                 //[notificationCenter postNotificationName:@"SP_FLAGS" object:self userInfo:player];     
01409             }
01410             @catch (NSException * e) {
01411                 NSLog(@"ServerReader.handlePacket: SP_FLAGS error");
01412                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01413             }
01414             break;
01415                 case SP_MASK :
01416             @try {
01417                 int teamMask = buffer;
01418                 [notificationCenter postNotificationName:@"SP_MASK" 
01419                                                   object:self userInfo:[NSNumber numberWithInt:teamMask]];                
01420             }
01421             @catch (NSException * e) {
01422                 NSLog(@"ServerReader.handlePacket: SP_MASK error");
01423                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01424             }
01425             break;
01426                 case SP_PSTATUS :
01427             @try {
01428                 int playerId = buffer; 
01429                 Player *player = [universe playerWithId:playerId];
01430                 int status = buffer;
01431                 if([player status] != status) {
01432                     // process the new status
01433                     [player setStatus:status];
01434                     switch(status) {
01435                             //we did boom
01436                         case PLAYER_EXPLODE :
01437                             [player setExplode: 0];
01438                             // $$ this should trigger and drawing of the explosion
01439                             // which should set the status to PLAYER_DEAD (i think)
01440                             break;
01441                         case PLAYER_DEAD :
01442                             // if we become dead, we should explode
01443                            [player setStatus:PLAYER_EXPLODE];
01444                             break;
01445                         default :
01446                             // reset kills
01447                             [player setKills: 0];
01448                             break;
01449                     }
01450                     [notificationCenter postNotificationName:@"SP_PSTATUS" object:self userInfo:player];
01451                 }
01452             }
01453             @catch (NSException * e) {
01454                 NSLog(@"ServerReader.handlePacket: SP_PSTATUS error");
01455                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01456             }
01457             break;
01458                 case SP_BADVERSION :
01459             NSLog(@"ServerReader.handlePacket: SP_BADVERSION not implemented");
01460             break;
01461                 case SP_HOSTILE :
01462             @try {
01463                 int playerId = buffer; 
01464                 Player *player = [universe playerWithId:playerId];
01465                 [player setStickyWar: (buffer)];
01466                 [player setHostile:(buffer)];
01467                 //[notificationCenter postNotificationName:@"SP_HOSTILE" object:self userInfo:player];
01468             }
01469             @catch (NSException * e) {
01470                 NSLog(@"ServerReader.handlePacket: SP_HOSTILE error");
01471                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01472             }
01473             break;
01474                 case SP_STATS :
01475             @try {
01476                 int playerId = buffer; 
01477                 Player *player = [universe playerWithId:playerId];
01478                 PlayerStats *stats = [player stats];
01479                 [stats updateTournamentKills: intFromPacket(buffer, 4)
01480                             tournamentLosses: intFromPacket(buffer, 8)
01481                                        kills: intFromPacket(buffer, 12)
01482                                       losses: intFromPacket(buffer, 16)
01483                              tournamentTicks: intFromPacket(buffer, 20)
01484                            tournamentPlanets: intFromPacket(buffer, 24)
01485                       tournamentArmiesBombed: intFromPacket(buffer, 28)
01486                                starbaseKills: intFromPacket(buffer, 32)
01487                               starbaseLosses: intFromPacket(buffer, 36)
01488                                 armiesBombed: intFromPacket(buffer, 40)
01489                                      planets: intFromPacket(buffer, 44)
01490                             starbaseMaxKills: (double)intFromPacket(buffer, 52) / 100];
01491 
01492                 FeatureList *fList = [communication featureList];
01493                 if([[player ship] type] == SHIP_SB  && 
01494                    [fList valueForFeature: FEATURE_LIST_SB_HOURS] != FEATURE_OFF) {
01495                     [stats setStarbaseTicks: intFromPacket(buffer, 48)];
01496                 }
01497                 else {
01498                     [stats setMaxKills: (double)intFromPacket(buffer, 48) / 100];
01499                 }
01500                 //[notificationCenter postNotificationName:@"SP_STATS" object:self userInfo:player];
01501             }
01502             @catch (NSException * e) {
01503                 NSLog(@"ServerReader.handlePacket: SP_STATS error");
01504                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01505             }
01506             break;
01507                 case SP_PL_LOGIN :
01508             @try {
01509                 int playerId = buffer; 
01510                 Player *player = [universe playerWithId:playerId];
01511                 // check for promotion
01512                 PlayerStats *pstats  = [player stats];
01513                 Rank *oldRank = [pstats rank];
01514                 Rank *newRank = [pstats setRankWithId: (buffer)];
01515                 // removed check for is != ensign
01516                 if([player isMe] && newRank != oldRank) {
01517                     // promoted flag is in the status 
01518                     Status *stats = [universe status];
01519                     [stats setPromoted: YES];
01520                 }
01521                 NSString *name    = [self stringFromBuffer:buffer startFrom:4 maxLength:16];
01522                 [player setName:name];
01523                 NSString *monitor = [self stringFromBuffer:buffer startFrom:20 maxLength:16];
01524                 [player setMonitor:monitor];
01525                 NSString *login   = [self stringFromBuffer:buffer startFrom:36 maxLength:16];
01526                 [player setLogin:login];
01527                 //[notificationCenter postNotificationName:@"SP_PL_LOGIN" object:self userInfo:player];
01528             }
01529             @catch (NSException * e) {
01530                 NSLog(@"ServerReader.handlePacket: SP_PL_LOGIN error");
01531                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01532             }
01533                         break;
01534                 case SP_RESERVED :
01535                         @try {
01536                 NSData *sreserved = [NSData dataWithBytes:(buffer+4) length:16];
01537                 
01538                 // do some stuff with RSA,
01539                 // looks very specific, let the RSA handler take care of it when
01540                 // it receives the notification
01541                 [notificationCenter postNotificationName:@"SP_RESERVED" object:self userInfo:sreserved];
01542             }
01543             @catch (NSException * e) {
01544                 NSLog(@"ServerReader.handlePacket: SP_RESERVED error");
01545                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01546             }            
01547             break;
01548                 case SP_PLANET_LOC :
01549                         @try {
01550                 Planet *planet = [universe planetWithId:(buffer)];
01551                 /*
01552                 // Rotate coordinates
01553                 Point point = Rotate.rotateCoord(
01554                                                  intFromPacket(4),
01555                                                  intFromPacket(8),
01556                                                  data.rotate,
01557                                                  Universe.HALF_PIXEL_SIZE,
01558                                                  Universe.HALF_PIXEL_SIZE);
01559                 */
01560                 NSPoint pos;
01561                 pos.x = intFromPacket(buffer, 4);
01562                 pos.y = intFromPacket(buffer, 8);
01563                 [planet setPosition: pos];
01564                 
01565                 NSString *name    = [self stringFromBuffer:buffer startFrom:12 maxLength:16];
01566                 [planet setName:name];
01567                 [planet setNeedsDisplay:YES];  
01568                 //[notificationCenter postNotificationName:@"SP_PLANET_LOC" object:self userInfo:planet];
01569             }
01570             @catch (NSException * e) {
01571                 NSLog(@"ServerReader.handlePacket: SP_PLANET_LOC error");
01572                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01573             }            
01574             break;
01575                 case SP_UDP_REPLY :
01576                         @try {
01577                 // to big to be in this switch
01578                 [self handleUdpReply:buffer];
01579             }
01580             @catch (NSException * e) {
01581                 NSLog(@"ServerReader.handlePacket: SP_PLANET_LOC error");
01582                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01583             }            
01584             break;       
01585                 case SP_SEQUENCE : 
01586         case SP_SC_SEQUENCE :
01587             // to be overwritten by UDP
01588             [self handleSequence:buffer];            
01589             break;          
01590                 case SP_RSA_KEY :
01591                         @try {
01592                 NSLog(@"ServerReader.handlePacket: RSA verification requested.");
01593                 NSData *data = [NSData dataWithBytes:(buffer+4) length:RSA_KEY_SIZE];                
01594                 // do some stuff with RSA,
01595                 // looks very specific, let the RSA handler take care of it when
01596                 // it receives the notification
01597                 [notificationCenter postNotificationName:@"SP_RSA_KEY" object:self userInfo:data];
01598             }
01599             @catch (NSException * e) {
01600                 NSLog(@"ServerReader.handlePacket: SP_RSA_KEY error");
01601                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01602             }            
01603             break;            
01604                 case SP_MOTD_PIC :
01605             NSLog(@"ServerReader.handlePacket: SP_MOTD_PIC not implemented");           
01606             break; 
01607                 case SP_SHIP_CAP :
01608                         @try {
01609                 // setup the properties of this ship
01610                 int shipType = shortFromPacket(buffer, 2);
01611                 Ship *ship = [universe shipOfType:shipType];
01612                 
01613                 [ship setTorpSpeed: shortFromPacket(buffer, 4)];
01614                 [ship setPhaserDamage: shortFromPacket(buffer, 6)];
01615                 [ship setMaxSpeed: intFromPacket(buffer, 8)];
01616                 [ship setMaxFuel: intFromPacket(buffer, 12)];
01617                 [ship setMaxShield: intFromPacket(buffer, 16)];
01618                 [ship setMaxDamage: intFromPacket(buffer, 20)];
01619                 [ship setMaxWeaponTemp: intFromPacket(buffer, 24)];
01620                 [ship setMaxEngineTemp: intFromPacket(buffer, 28)];
01621                 [ship setWidth: shortFromPacket(buffer, 30)];
01622                 [ship setHeight: shortFromPacket(buffer, 32)];
01623                 [ship setMaxArmies: shortFromPacket(buffer, 34)];
01624                 
01625                 [notificationCenter postNotificationName:@"SP_SHIP_CAP" object:self userInfo:ship];
01626             }
01627             @catch (NSException * e) {
01628                 NSLog(@"ServerReader.handlePacket: SP_SHIP_CAP error");
01629                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01630             }            
01631             break; 
01632                 case SP_S_REPLY :
01633                         @try {
01634                 int reply = buffer;
01635                 switch(reply) {
01636                     case SPK_VOFF :
01637                         if([communication shortVersion] == SHORTVERSION && ![communication receiveShort]) {
01638                             NSLog(@"ServerReader.handlePacket: Using Short Packet Version 1.");
01639                             // funny, this never rolls back?
01640                             [communication setShortVersion: OLDSHORTVERSION];
01641                             //comm.sendShortReq(SPK_VON); should be done by communication upon                                                  
01642                             // receiving the event
01643                             [notificationCenter postNotificationName:@"SP_S_REPLY_SPK_OLD" object:self 
01644                                                             userInfo:[NSNumber numberWithInt:SPK_VON]];
01645                         }
01646                         else {
01647                             [communication setReceiveShort: NO];
01648                             //[communication sendUdpReq:[NSNumber numberWithInt:COMM_UPDATE]];
01649                             //view.short_win.refresh(); should be done by communication upon 
01650                             // receiving the event
01651                             [notificationCenter postNotificationName:@"SP_S_REPLY_SPK_VOFF" object:self 
01652                                                             userInfo:[NSNumber numberWithInt:COMM_UPDATE]];
01653                         }
01654                         break;
01655                     case SPK_VON:
01656                         [communication setReceiveShort: YES];
01657                         //view.short_win.refresh();
01658                         // I didn't know what spwinside and spgwidth where used for.
01659                         //int spwinside = shortFromPacket(2);
01660                         //int spgwidth = shortFromPacket(4);
01661                         /* 
01662                         * Get a `-' style update to fix the kills shown on the playerlist
01663                          * when you first enter and to fix other loss if short packets
01664                          * have just been turned back on.
01665                          */
01666                                                 //[communication sendShortReq:[NSNumber numberWithInt:SPK_SALL]];
01667                         [notificationCenter postNotificationName:@"SP_S_REPLY_SPK_VON" object:self 
01668                                                         userInfo:[NSNumber numberWithInt:SPK_SALL]];
01669                         NSLog(@"ServerReader.handlePacket: Receiving Short Packet Version ");
01670                         break;
01671                     case SPK_THRESHOLD:
01672                         break;
01673                     default:
01674                         NSLog(@"ServerReader.handlePacket: Unknown response packet value short-req ");
01675                         break;
01676                 }
01677             }
01678             @catch (NSException * e) {
01679                 NSLog(@"ServerReader.handlePacket: SP_S_REPLY error");
01680                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01681             }            
01682             break; 
01683                 case SP_S_MESSAGE :
01684                         @try {
01685                 
01686                 // from part
01687                 NSMutableString *message = [NSString stringWithString: @"   ->   "];
01688                 int from = buffer & 0xFF;
01689                 if(from > [universe playerCount]) {
01690                     from = 255;
01691                 }
01692                 if(from == 255) {
01693                     message = [NSString stringWithString: @"GOD->"];                    
01694                 }
01695                 else {
01696                     Player *player = [universe playerWithId:from];
01697                     message = [NSString stringWithFormat:@" %@->", [player mapChars]];
01698                 }
01699                 
01700                 // to part
01701                 Player *me = [universe playerThatIsMe];
01702                 Team* myTeam = [me team];
01703                 switch(buffer[1] & (TEAM | INDIV | ALL)) {
01704                     case TEAM :
01705                         [message appendString:[myTeam abbreviation]];                       
01706                         break;
01707                     case INDIV :
01708                         [message appendString:[me mapChars]];
01709                         break;
01710                     default :
01711                         [message appendString: @"ALL"];
01712                         break;
01713                 }
01714                 
01715                 // the message
01716                 [message appendString:[self stringFromBuffer:buffer startFrom:5 maxLength:79]];
01717                 [notificationCenter postNotificationName:@"SP_S_MESSAGE" object:self userInfo:message];
01718             }
01719             @catch (NSException * e) {
01720                 NSLog(@"ServerReader.handlePacket: SP_S_MESSAGE error");
01721                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01722             }            
01723             break; 
01724                 case SP_S_WARNING :
01725                         @try {
01726                 if(swarningHandler == nil) {
01727                     swarningHandler = [[ShortPacketWarningHandler alloc] init];
01728                 }
01729                 // way to much code to handle in here, create seperate class as helper
01730                 NSLog(@"ServerReader.handlePacket: SP_S_WARNING passing to ShortPacketWarningHandler");
01731                 [swarningHandler handleSWarning:buffer];
01732             }
01733             @catch (NSException * e) {
01734                 NSLog(@"ServerReader.handlePacket: SP_S_WARNING error");
01735                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01736             }            
01737             break; 
01738                 case SP_S_YOU :
01739                         @try {
01740                 int ghostSlot = ([communication ghostSlot] == -1) ? buffer[1] : [communication ghostSlot];
01741                 Player *me;
01742                 if (ghostSlot == -1) {
01743                     int playerId = buffer; // this player
01744                     me = [universe playerWithId:playerId];
01745                 } else {
01746                     me = [universe playerWithId:ghostSlot];
01747                 }
01748                 
01749                 [me updateHostile: buffer
01750                         stickyWar: buffer
01751                            armies: buffer
01752                             flags: intFromPacket(buffer, 8)
01753                           whyDead: buffer
01754                       whoKilledMe: buffer
01755                          thisIsMe: YES];
01756                 
01757                 if(([me flags] & PLAYER_PLOCK) != 0) {
01758                     if (([me flags] & PLAYER_OBSERV) != 0) {
01759                         [[universe status] setObserver:YES];
01760                     }
01761                     else {
01762                         [[universe status] setObserver:NO]; 
01763                     }
01764                 }
01765                 else {  
01766                     [[universe status] setObserver:NO];
01767                 } 
01768                 [notificationCenter postNotificationName:@"SP_S_YOU" object:self userInfo:me];                
01769             }
01770             @catch (NSException * e) {
01771                 NSLog(@"ServerReader.handlePacket: SP_S_YOU error");
01772                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01773             }            
01774             break; 
01775                 case SP_S_YOU_SS :
01776                         @try {
01777                 Player* me = [universe playerThatIsMe];
01778                 
01779                 // Ignore this message until I know what player slot I am.
01780                 if(me == nil) {
01781                     return YES;
01782                 }
01783                 
01784                 [me updateDamage: shortFromPacket(buffer, 2)
01785                    shieldStrenght: shortFromPacket(buffer, 4)
01786                              fuel: shortFromPacket(buffer, 6)
01787                        engineTemp: (short)shortFromPacket(buffer, 8)
01788                       weaponsTemp: (short)shortFromPacket(buffer, 10)                          
01789                          thisIsMe: YES];
01790                 
01791                 // freaky bit stuff
01792                 FeatureList *fList = [communication featureList];                
01793                 if([fList valueForFeature: FEATURE_LIST_SELF_8FLAGS] != FEATURE_OFF) {
01794                     [me setFlags: (([me flags] & 0xFFFFFF00) | (buffer & 0xFF))];
01795                 }
01796                 else if([fList valueForFeature: FEATURE_LIST_SELF_8FLAGS2] != FEATURE_OFF) {
01797                     int new_flags = [me flags] & ~(PLAYER_SHIELD | PLAYER_REPAIR | PLAYER_CLOAK 
01798                                 | PLAYER_GREEN | PLAYER_YELLOW | PLAYER_RED | PLAYER_TRACT | PLAYER_PRESS);
01799                     
01800                     int pad1 = buffer & 0xFF;
01801                     
01802                     new_flags |= ((pad1 & PLAYER_SHIELD) | (pad1 & PLAYER_REPAIR) 
01803                                   | ((pad1 & (PLAYER_CLOAK << 2)) >> 2) | ((pad1 & (PLAYER_GREEN << 7)) >> 7) 
01804                                   | ((pad1 & (PLAYER_YELLOW << 7)) >> 7) | ((pad1 & (PLAYER_RED << 7)) >> 7) 
01805                                   | ((pad1 & (PLAYER_TRACT << 15)) >> 15)  | ((pad1 & (PLAYER_PRESS << 15)) >> 15));
01806                     
01807                     [me setFlags: new_flags];
01808                 }
01809                 [notificationCenter postNotificationName:@"SP_S_YOU_SS" object:self userInfo:me];     
01810             }
01811             @catch (NSException * e) {
01812                 NSLog(@"ServerReader.handlePacket: SP_S_YOU_SS error");
01813                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01814             }            
01815             break; 
01816                 case SP_S_PLAYER :
01817                         @try {
01818                 // to big to be in this switch
01819                 [self handleVPlayer:buffer];
01820             }
01821             @catch (NSException * e) {
01822                 NSLog(@"ServerReader.handlePacket: SP_S_PLAYER error");
01823                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01824             }            
01825             break; 
01826                 case SP_PING :
01827                         @try {
01828                 int response = (buffer);
01829                 [communication setPing:YES withResponse:response]; // we got a ping
01830                 // update the stats
01831                 PingStats *pingStats = [communication pingStats];
01832                 
01833                 [pingStats setLag: (short)shortFromPacket(buffer, 2)];
01834                 [pingStats setTotalLossServerToClient:(buffer & 0xFF) 
01835                                        ClientToServer:(buffer & 0xFF)];
01836                 [pingStats setIncrementalLossServerToClient:(buffer & 0xFF) 
01837                                              ClientToServer:(buffer & 0xFF)];
01838                 [pingStats calculateLag];
01839                 [notificationCenter postNotificationName:@"SP_PING" object:self userInfo:pingStats];  
01840             }
01841             @catch (NSException * e) {
01842                 NSLog(@"ServerReader.handlePacket: SP_PING error");
01843                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01844             }            
01845             break; 
01846                 case SP_S_TORP :
01847                 case SP_S_8_TORP :
01848                         @try {
01849                 [self handleVTorp:buffer];
01850             }
01851             @catch (NSException * e) {
01852                 NSLog(@"ServerReader.handlePacket: SP_S_TORP error");
01853                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01854             }            
01855             break; 
01856                 case SP_S_TORP_INFO :
01857                         @try {
01858                 [self handleVTorpInfo:buffer];
01859             }
01860             @catch (NSException * e) {
01861                 NSLog(@"ServerReader.handlePacket: SP_S_TORP_INFO error");
01862                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01863             }            
01864             break; 
01865                 case SP_S_PLANET :
01866                         @try {
01867                 [self handleVPlanet:buffer];
01868             }
01869             @catch (NSException * e) {
01870                 NSLog(@"ServerReader.handlePacket: SP_S_PLANET error");
01871                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01872             }            
01873             break; 
01874                 case SP_S_PHASER :
01875                         @try {
01876                 [self handleVPhaser:buffer];
01877             }
01878             @catch (NSException * e) {
01879                 NSLog(@"ServerReader.handlePacket: SP_S_PHASER error");
01880                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01881             }            
01882             break; 
01883                 case SP_S_KILLS :
01884                         @try {                
01885                 int player_index = 0;
01886                 Player *player;
01887                 int data_pos = 2;
01888                 int numofkills = buffer & 0xFF;                
01889                 
01890                 for(int p = 0; p < numofkills; ++p, data_pos += 2) {
01891                     player_index = buffer[data_pos + 1] >> 2;
01892                     player = [universe playerWithId:player_index];
01893                     [player setKills: (float)(buffer & 0xFF | ((buffer & 0x03) << 8)) / 100];
01894                     [notificationCenter postNotificationName:@"SP_S_KILLS" object:self userInfo:player];
01895                 }            
01896             }
01897             @catch (NSException * e) {
01898                 NSLog(@"ServerReader.handlePacket: SP_S_KILLS error");
01899                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01900             }            
01901             break; 
01902                 case SP_S_STATS :
01903                         @try {
01904                 Player *player = [universe playerWithId:buffer];
01905                 PlayerStats *stats = [player stats];
01906                 
01907                 [stats updateTournamentKills:shortFromPacket(buffer, 4) 
01908                             tournamentLosses:shortFromPacket(buffer, 6) 
01909                                        kills:shortFromPacket(buffer, 8) 
01910                                       losses:shortFromPacket(buffer, 10) 
01911                              tournamentTicks:intFromPacket(buffer, 12) 
01912                            tournamentPlanets:shortFromPacket(buffer, 2) 
01913                       tournamentArmiesBombed:intFromPacket(buffer, 16) 
01914                                starbaseKills:shortFromPacket(buffer, 24) 
01915                               starbaseLosses:shortFromPacket(buffer, 26) 
01916                                 armiesBombed:shortFromPacket(buffer, 28) 
01917                                      planets:shortFromPacket(buffer, 30) 
01918                             starbaseMaxKills:intFromPacket(buffer, 32) / 100];
01919                 
01920                 FeatureList *fList = [communication featureList];
01921                                     
01922                 if([[player ship] type]  == SHIP_SB && [fList valueForFeature: FEATURE_LIST_SB_HOURS] != FEATURE_OFF) {
01923                     [stats setStarbaseTicks: intFromPacket(buffer, 48)];
01924                 }
01925                 else {
01926                     [stats setMaxKills: (double)intFromPacket(buffer, 48) / 100];
01927                 }
01928                 [notificationCenter postNotificationName:@"SP_S_STATS" object:self userInfo:player];
01929             }
01930             @catch (NSException * e) {
01931                 NSLog(@"ServerReader.handlePacket: SP_S_STATS error");
01932                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01933             }            
01934             break; 
01935                 case SP_FEATURE :
01936                         @try {
01937                 FeatureList *fList = [communication featureList]; 
01938                                 
01939                 char type = (char)buffer[1];
01940                 int  arg1 = (int)buffer[2]; 
01941                 int  arg2 = (int)buffer[3]; 
01942                 int value = intFromPacket(buffer, 4);
01943                 NSString *name = [self stringFromBuffer:buffer startFrom:8 maxLength:80];
01944                 [fList checkFeature:name withType:type withArg1:arg1 withArg2:arg2 withValue:value];                
01945                 [notificationCenter postNotificationName:@"SP_FEATURE" object:self userInfo:nil];
01946             }            
01947             @catch (NSException * e) {
01948                 NSLog(@"ServerReader.handlePacket: SP_FEATURE error");
01949                 NSLog([NSString stringWithFormat:@"%@: %@", [e name], [e reason]]);
01950             }            
01951             break; 
01952                 case SP_BITMAP :
01953             NSLog(@"ServerReader.handlePacket: SP_BITMAP not implemented");           
01954                         break;                                          
01955                 }
01956         
01957         
01958         //NSTimeInterval stop = [NSDate timeIntervalSinceReferenceDate];  
01959         //NSLog(@"ServerReader.handlePacket took: %f sec", (stop-start));    
01960         
01961     return YES;
01962 }
01963 
01964 - (NSString*) stringFromBuffer:(char*)buffer startFrom:(int)start maxLength:(int)max {
01965     
01966     // looks for null temination it self, i could check maxlength, but it's okay
01967     NSString *line = [NSString stringWithUTF8String:(buffer + start)];
01968     //NSLog(@"ServerReader.stringFromBuffer (%@)", line);
01969     return line;
01970     /*
01971     
01972     int end = max;
01973     for (int i = start; i < max; i++) {
01974         if (buffer[i] == '\0') {
01975             end = i;
01976             NSString *line = [NSString stringWithCString:(buffer + start) length:end + 1];
01977             NSLog(@"ServerReader.stringFromBuffer (%@)", line);
01978             return line;
01979         }
01980     }
01981     NSString *line = [NSString stringWithCString:(buffer + start) length:end + 1];
01982     NSLog(@"ServerReader.stringFromBuffer (%@)", line);
01983     return line;
01984      */
01985 }
01986 
01987 
01988 
01989 @end

Generated on Sat Aug 26 21:14:10 2006 for MacTrek by  doxygen 1.4.7