Game Development Community

Master server problem

by CIMO · in Torque Game Engine · 10/01/2006 (8:45 am) · 8 replies

I use this for create a my master server:

First we create a structure to hold the address and the time we last got a heartbeat from the server, place the following in \engine\game\net\serverQuery.h after the structure for MasterInfo (line 35):
struct ExampleServerData
{
   NetAddress address; 
   U32 lastBeatTime;   
      
   ExampleServerData()
   {
         lastBeatTime = 0;
   }
};

#1
10/01/2006 (8:46 am)
Add the following to \engine\game\net\serverQuery.cc (at line 102)
Vector<ExampleServerData> gExampleServerList(__FILE__, __LINE__);
static const U32 gExampleHeartbeatTimeout = 120000;

Find the last function definition at the bottom of the file, add the following code above that function (at aound line 2014):
static void handleGameHeartbeat( const NetAddress* address, U32 key, U8 flags )
{
  // post message to console
  char netString[256];
  Net::addressToString(address, netString);
  Con::printf( "Received Heartbeat from [%s].", netString);
   
  // scan through the list of servers and find the sending server
  // then set its "last heartbeat value" to timenow
  // if the server is not in the list add it.
  U32 TimeNow = Sim::getCurrentTime();
  bool found = false;
   
  for ( U32 i = 0; i < gExampleServerList.size(); i++ )
  {
    // if this address is in the list update the time and flag it as found
    if(Net::compareAddresses(&gExampleServerList[i].address, address))
    {
       gExampleServerList[i].lastBeatTime = TimeNow;
       found = true;
       break;
    }
  }
   
  // if we did not find the address add it with the current time
  if(!found)
  {
    Con::printf( "Adding [%s] to list", netString);
    ExampleServerData update;

    update.address = *address;
    update.lastBeatTime = TimeNow;
    gExampleServerList.push_back(update);
  }
   
  // dump the current list to console,
  // this has only been included for development.
  Con::printf( "----- Current List ------");
  Con::printf( " Time now:  %u",TimeNow);
  for ( U32 i = 0; i < gExampleServerList.size(); i++ )
  {
    char tempString[256];
    Net::addressToString(&gExampleServerList[i].address, tempString);
    Con::printf( " %u. [%s] expires at %u ",
            i,
            tempString,
            gExampleServerList[i].lastBeatTime+gExampleHeartbeatTimeout);
  }
  Con::printf( "-------------------------");
}

static void handleMasterServerListRequest(const NetAddress* address,U32 key,U8 flags)

{
  // Rather than adding a house keeping function to find and remove inactive
  // servers it has been simpler to do it here, to ensure only an upto date 
  // list is sent to the client.

  // post message to console 
  char netString[256];
  Net::addressToString(address, netString);
  Con::printf( "Received MasterServerListRequest packet from [%s].", netString);

   
  // remove any servers where:
  // "time now" > "last heartbeat time" + "heart beat timeout"
  U32 TimeNow = Sim::getCurrentTime();   
  U32 i = 0;

  while(true)
  {
    // exit loop if we are out of range
    if(i >= gExampleServerList.size() )
      break;

    if (TimeNow > (gExampleServerList[i].lastBeatTime + gExampleHeartbeatTimeout))
    {
      // for development we are posting our removal of this server to console
      Net::addressToString(address, netString);
      Con::printf( "[%s] has timed out, and has been removed from the list",
                   netString);

      // this server has timed out so remove it from the list
      gExampleServerList.erase(i);
      continue;
    }

    ++i;
  }

  // Send each server to the calling network address
  // NOTE we *should* fill a packet with a list of servers but we
  // are sending a packet for each server.
  for(U32 i = 0; i < gExampleServerList.si ze() ; ++i)
  {
    BitStream *out = BitStream::getPacketStream();

    out->write( U8( NetInterface::MasterServerListResponse ) );
    out->write( U8(flags) );
    out->write( U32(key) );
    out->write( U8(i) ); // packet index
    out->write( U8(gExampleServerList.size()) );  // total number of packets
    out->write( U16(1) );  // servers in this packet
    out->write( U8(gExampleServerList[i].address.netNum[0]));  // server address
    out->write( U8(gExampleServerList[i].address.netNum[1]));  // server address
    out->write( U8(gExampleServerList[i].address.netNum[2]));  // server address
    out->write( U8(gExampleServerList[i].address.netNum[3]));  // server address
    out->write( U16(gExampleServerList[i].address.port));  // server port
      
     BitStream::sendPacketStream(address);
  }
}
#2
10/01/2006 (8:47 am)
Before the closing break on the switch statement, add the following:
case GameHeartbeat:
         handleGameHeartbeat( address, key, flags );
         break;
                 

    case MasterServerListRequest:
         handleMasterServerListRequest( address, key, flags );
         break;

compile the changes.
#3
10/01/2006 (8:47 am)
We need to change the default master server that our build will use, open \example\starter.fps\server\defaults.cs

Edit the master server address on line 9 from:

"2:master.garagegames.com:28002"; to "2:<your ip address here>:28111"

example: "2:192.168.2.4:28111" (although your IP will likley be different!)
Note: do not use 127.0.0.1 because this address is filtered out by code in Net::process(), you must use your workstations IP
#4
10/01/2006 (8:48 am)
To run multiple servers out of the same directory we need to create a different pref file for each server, make a copy of \example\starter.fps\server\defaults.cs and name it master_prefs.cs

open it and make the following changes:

Change the server name from "FPS Starter Kit" to "Master Server" on line 12
Change the server port from 28000 to 28111 on line 28.

Now make 3 copies of master_prefs.cs and name them:
game_1_prefs.cs
game_2_prefs.cs
game_3_prefs.cs

open game_1_prefs.cs and change the server name (on line 12) to "Game Server 1" and the server port (on line 28) to 28101
open game_2_prefs.cs and change the server name (on line 12) to "Game Server 2" and the server port (on line 28) to 28102
open game_3_prefs.cs and change the server name (on line 12) to "Game Server 3" and the server port (on line 28) to 28103

now move up to the "example" directory and create a batch file named run_master.bat

open it and add this line:

torquedemo.exe -dedicated -prefs starter.fps/server/master_prefs.cs -mission starter.
fps/data/missions/stronghold.mis
#5
10/01/2006 (8:49 am)
Make three copies of this file and name them:
run_game_1.bat
run_game_2.bat
run_game_3.bat

Edit each file and change master_prefs.cs to game_1_prefs.cs, game_2_prefs.cs and game_3_prefs.cs respectively.

Start the master server with run_master.bat, once its up and running start up the three game servers with the other batch files.
the master server will list the new game servers as they are started, along with itself.

There are a couple of problems to sort out before we can run the client the first one one is a small bug in \example\starter.fps\client\ui\joinServerGui.gui

open this file and find this line: (its on line 348)

%index = getField(JS_serverList.getRowTextById(%id),6);


change the 6 to a 3 and save the file.

The second problem relates to the pref.cs file created when the servers are stopped, the client will use this file with the servers settings, to avoid this we need to force the client to use the default.cs file, the easiest way to do this is to start the client from a batch file that deletes the offending pref.cs files before running TorqueDemo.exe

create \example\run_client.bat

open if and paste the following:

del \starter.fps\server\prefs.cs.dso
del \starter.fps\server\prefs.cs
torquedemo.exe

start the client using run_client.bat

hit Join Server and then Query Master, all of your servers should be listed.
#6
10/01/2006 (8:51 am)
My game see my server in list....But if try enter in a one sever tha LOAD MISSION GUI stay in "load mission..." and load never....
Why?
had the problem? PLEASE HELP ME
#7
10/01/2006 (10:03 am)
Now funciton..The problem stay in a file BAT
Ii i use a gg server the my select type of player function
If i use a my server the select type of player not function??????
WHY
#8
10/01/2006 (1:23 pm)
Ehi never say help me?