Logo Search packages:      
Sourcecode: castle-combat version File versions

net.c

#include "SDL_net/SDL_net.h"
#include "main.h"
#include "server.h"
#include "string.h"

static TCPsocket tcpsock = NULL;
static SDLNet_SocketSet socketset = NULL;
char Connected, GetData[512], EndSignalSent=0, EndSignalReceived=0, SyncForced=0;

void cleanup()
{
    if ( tcpsock != NULL ) {
      SDLNet_TCP_Close(tcpsock);
      tcpsock = NULL;
    }
    if ( socketset != NULL ) {
      SDLNet_FreeSocketSet(socketset);
      socketset = NULL;
    }
}

void Net_Send( char *data )
{
    if ( Connected )
      SDLNet_TCP_Send(tcpsock, data, data[0]+1);
}

void Net_Get()
{
    if ( ! Connected )
      return;
    if (Server) {
      ServerLoop();
      while ( ! Net_HasData() ) {
          ServerLoop();
          SDL_Delay(1);
      }
    }
    if ( SDLNet_TCP_Recv(tcpsock, GetData, 1) <= 0 ) {
      printf("\n ** Network connection is broken! ** \n");
      exit(1);
    }
    SDLNet_TCP_Recv(tcpsock, GetData, GetData[0]);
}

int Net_HasData()
{
    if (!Connected)
      return 0;
    else 
      if (Server) ServerLoop();

    return SDLNet_CheckSockets( socketset, 0);
}

void ReceiveSync( int y, Sint8 target[][HEIGHT], Sint8 *source, const char *name)
{
    int i;
    for ( i=0; i<WIDTH; i++) {
      if (target[i][y] != source[i]) {
          printf("SYNC LOST (%d, %d, %s), forcing sync!\n", i, y, name);
          target[i][y] = source[i];
          SyncForced = 1;
      }
    }
//    printf("Synced %s| ", name);
}

void Network()
{
    SDL_Rect rect;

    if ( ! Connected ) return;

    while (Net_HasData()) {
      Net_Get();
      switch (GetData[0]) {
// BUILD and PLACE
          case NET_BPLAYER_MOVE: {
            UndrawBlock();
            BPlayer[(int)GetData[1]].x=GetData[2];
              BPlayer[(int)GetData[1]].y=GetData[3];
            DrawBlock();
          } break;
          case NET_PLACE_PLAYER_MOVE: {
            UndrawCursor();
              BPlayer[(int)GetData[1]].x=GetData[2];
            BPlayer[(int)GetData[1]].y=GetData[3];
            DrawCursor();
            Update();
          } break;
          case NET_BLOCKGEN: {
            UndrawBlock();
            CalcBlock( GetData[1], GetData[2], GetData[3]);
            BPlayer[ (int)GetData[1] ].WaitForNextBlock = 0;
            DrawBlock();
          } break;
          case NET_TURN: {
            UndrawBlock();
            Turn( GetData[1] );
            DrawBlock();
          } break;
          case NET_PUTBLOCK: {
            ReallyPutBlock( GetData[1] );
            LookForSecuredAreas( GetData[1] );
            //UndrawBlock();
          } break;
          case NET_PUTCANNON: {
            ReallyPutCannon( GetData[1] );
              if ( PPlayer[(int)GetData[1]].CannonsLeft < 3 )
                PPlayer[(int)GetData[1]].SelectedCannon=0;
          } break;
            case NET_BUTTON2: {
              PPlayer[(int)GetData[1]].SelectedCannon=1-PPlayer[(int)GetData[1]].SelectedCannon;
            if ( PPlayer[(int)GetData[1]].CannonsLeft < 3 )
                PPlayer[(int)GetData[1]].SelectedCannon=0;
          } break;
          case NET_ENDGAME: {
            EndSignalReceived=1;
          } break;
          case NET_ADDHOUSE: {
            ReallyAddHouse( GetData[1], GetData[2] );
          } break;      
          case NET_CLEAN: {
            printf("Cleanup info received.\n");
            ReallyClean(GetData[1]);
          } break;      
// BATTLE
          case NET_BATTLE_MOVE: {
            UndrawCrosshair();
            BaPlayer[(int)GetData[1]].x=GetData[2]+GetData[3]*100;
              BaPlayer[(int)GetData[1]].y=GetData[4]+GetData[5]*100;
          } break;
          case NET_SHOOT: {
            ReallyShoot(GetData[1],GetData[2]);
          } break;
          case NET_NEWTANK: {
            House[(int)GetData[1]][(int)GetData[2]]=0;
            if (TankNum<MAX_TANKNUM-1) {
                // erase house
                rect.x=GetData[1]*BSIZE;
                rect.y=GetData[2]*BSIZE;
                rect.w=rect.h=BSIZE;
                SDL_BlitSurface( BackPic, &rect, Screen, &rect);
      
                // create Tank
                Tank[TankNum].x=GetData[1];
                Tank[TankNum].y=GetData[2];
                Tank[TankNum].dir=GetData[3];
                Tank[TankNum].WaitTime=GetData[4]*256;
                Tank[TankNum].WaitTime+=GetData[5];
                TankNum++;
      
                // Draw Tank
                Blit(GetData[1]*BSIZE, GetData[2]*BSIZE, TankPic[Tank[TankNum-1].dir]);
                SDL_BlitSurface( Screen, &rect, BackBuffer, &rect);
            }
            else printf("Too many Tanks!\n");
          } break;
          case NET_TANKMOVE: {
            UndrawTank(GetData[1]);
            Tank[(int)GetData[1]].x=GetData[2];
            Tank[(int)GetData[1]].y=GetData[3];
            Tank[(int)GetData[1]].dir=GetData[4];
            DrawTank(GetData[1]);
          } break;
          case NET_TANKSHOOT: {
            Destroy(GetData[1]*BSIZE,GetData[2]*BSIZE,0);
          } break;
// CASTLE SELECTION         
          case NET_OTHER_SELECTION: {
            UndrawSelect((int)GetData[1]);
            Selected[(int)GetData[1]]=GetData[2];
            DrawSelect((int)GetData[1]);
            Update();
          } break;
          case NET_SELECTION_FINISHED: {
            SelectFinished[(int)GetData[1]] = 1;
            Castle[(int)Selected[(int)GetData[1]]].Owner = GetData[1];
            BuildWallAroundCastle(GetData[2]);
            Update();
          } break;
// SYNCING
          case NET_SYNC_WALL: {
            ReceiveSync(GetData[1], Wall, &GetData[2], "Wall");
          } break;
          case NET_SYNC_GARBAGE: {
            ReceiveSync(GetData[1], Garbage, &GetData[2], "Garbage");
          } break;
          case NET_SYNC_HOUSE: {
            ReceiveSync(GetData[1], House, &GetData[2], "House");
          } break;
// OTHER
          case NET_PLAYERNAME: {
            strcpy( BPlayer[(int)GetData[1]].Name, &GetData[2] );
//          printf(" Setting Player%d's name to %s\n", (int)GetData[1], &GetData[2]);
          } break;
          case NET_CASTLE_RANDOMIZE: {
            if (!Master) {
                //printf("YAY\n\n\n");
                RandomizeCastles(GetData[1]);
                FinishLand();
                Blit(0,0,BackBuffer);
            }
          } break;
// ERRORs
          default: 
            printf("Unknown package received in Network()! (%d)\n", GetData[0]);
          break;
      }
    }
}

int Net_WaitForEnd()
{
    char send[2];

    if (!Connected)
      return 0;
    
    if (!EndSignalSent) {
      send[0]=1;
        send[1]=NET_ENDGAME;
      Net_Send( send );
      EndSignalSent=1;
    }
    if (Server) {
        ServerLoop();
    }
    if (EndSignalReceived) {
        EndSignalSent=0;
      EndSignalReceived=0;
        return 0;
    }
    if ((Quit)||(EndGame))
      return 0;
    
    return 1;
}

void doSync()
{
    int x, y;
    char send[WIDTH + 3];
    
    for ( y=0; y<HEIGHT; y++ ) {
      send[0] = WIDTH + 2;
      send[2] = y;
      
      send[1] = NET_SYNC_WALL;
      for ( x=0; x<WIDTH; x++ )
          send[x+3] = Wall[x][y];
      Net_Send( send );

      send[1] = NET_SYNC_GARBAGE;
      for ( x=0; x<WIDTH; x++ )
          send[x+3] = Garbage[x][y];
      Net_Send( send );

      send[1] = NET_SYNC_HOUSE;
      for ( x=0; x<WIDTH; x++ )
          send[x+3] = House[x][y];
      Net_Send( send );
    }
}

void Net_WaitForStart()
{
    SDL_Event event;

    if (!Connected)
      return;

//    printf("Start waiting ---<");
    while ((Net_WaitForEnd())&&(!Quit)) {
      SDL_PollEvent(&event);
      if (event.key.keysym.sym == SDLK_ESCAPE) {
          exit(1);
      }
      Network();
      SDL_Delay(1);
    }
//    printf(">--- Ready to proceed.\n");
}

void Net_Sync()
{
    printf("Syncing... ");
    while ((Net_WaitForEnd())&&(!Quit)) {
      SDL_PollEvent(&event);
      if (event.key.keysym.sym == SDLK_ESCAPE) {
          exit(1);
      }
      Network();
      SDL_Delay(1);
    }
    if (Master)
      doSync();
    while ((Net_WaitForEnd())&&(!Quit)) {
      SDL_PollEvent(&event);
      if (event.key.keysym.sym == SDLK_ESCAPE) {
          exit(1);
      }
      Network();
      SDL_Delay(1);
    }
    if (SyncForced) {
      SyncForced = 0;
      RedrawEverything();
    }
    printf("finished!\n");
}

void SendHello(char *name)
{
    char hello[5+256];
    int n;
    
    if ( tcpsock != NULL ) {
        // Get our handle
      if ( (name == NULL) &&
          ((name=getenv("GAME_USER")) == NULL) &&
          ((name=getenv("USER")) == NULL ) ) {
             name="Unknown";
      }
      printf("Using name '%s'\n", name);
      // Construct the packet
      hello[1] = NET_HELLO;
//    memcpy(&hello[NET_HELLO_PORT+1], &myip->port, 2);
      if ( strlen(name) > 255 ) {
          n = 255;
      } else {
          n = strlen(name);
      }
      hello[NET_HELLO_NLEN+1] = n;
      strncpy(&hello[NET_HELLO_NAME+1], name, n);
      hello[1+NET_HELLO_NAME+n++] = 0;
      hello[1+NET_HELLO_PLAYERNUM] = PlayerNum;
      hello[1+NET_HELLO_CONQUER] = Conquer;
      hello[0]=NET_HELLO_NAME+n+1;
      
      // Send it to the server
      SDLNet_TCP_Send(tcpsock, hello, NET_HELLO_NAME+n+1);
      printf("Testing network connection.\n");
      Net_Get();
      if (GetData[0]==NET_HELLO) {
          printf("Connection test successful!\n");
          PlayerNum=GetData[1];
          Conquer=GetData[2];
      } else {
          printf("Connection test FAILED!\n");
          exit(1);
      }
    }
}

void Connect( char *server )
{
    IPaddress serverIP;
    int i;

    // Init SDL_net
    if ( SDLNet_Init() < 0 ) {
       fprintf(stderr, "Couldn't initialize net: %s\n",SDLNet_GetError());
       exit(1);
    }
    atexit(cleanup);
    atexit(SDLNet_Quit);
        
    // Connect to remote host
    SDLNet_ResolveHost(&serverIP, server, NET_PORT);
    if ( serverIP.host == INADDR_NONE ) {
      printf("Couldn't resolve hostname (%s)\n", server);
    } else 
    {
      tcpsock = SDLNet_TCP_Open(&serverIP);
      if ( tcpsock == NULL ) {
          Message("Connect failed\n");
          Connected=0;
          for (i=0;i<PlayerNum;i++)
            BPlayer[i].Local=1;
      } else
      {
          printf("Connected\n");
          Connected=1;
          for (i=0;i<PlayerNum;i++)
            BPlayer[i].Local=0;
      }
    }
    
    // Allocate the socket set for polling the network
    socketset = SDLNet_AllocSocketSet(2);
    if ( socketset == NULL ) {
      fprintf(stderr, "Couldn't create socket set: %s\n",SDLNet_GetError());
      exit(2);
    }
    SDLNet_TCP_AddSocket(socketset, tcpsock);
    
    SendHello( NULL ); // client name can be inserted here
}

Generated by  Doxygen 1.6.0   Back to index