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

Generated on Fri Jul 28 19:15:15 2006 for MacTrek by  doxygen 1.4.7