Init
This commit is contained in:
307
Samples/MasterServer/MasterClient.cpp
Normal file
307
Samples/MasterServer/MasterClient.cpp
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oculus VR, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* RakNet License.txt file in the licenses directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the RakNet Patents.txt file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MasterClient.h"
|
||||
#include "RakPeerInterface.h"
|
||||
#include "PacketEnumerations.h"
|
||||
#include "RakNetworkFactory.h"
|
||||
#include "StringCompressor.h"
|
||||
#include "GetTime.h"
|
||||
#include <cstring>
|
||||
|
||||
// Uncomment this define for debugging printfs
|
||||
#define _SHOW_MASTER_SERVER_PRINTF
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
MasterClient::MasterClient()
|
||||
{
|
||||
}
|
||||
|
||||
MasterClient::~MasterClient()
|
||||
{
|
||||
ClearServerList();
|
||||
}
|
||||
|
||||
bool MasterClient::Connect(char* host, int masterServerPort)
|
||||
{
|
||||
localServer.Clear();
|
||||
listServer=serverListed=localServerModified=false;
|
||||
localServer.connectionIdentifier.port=rakPeer->GetInternalID().port;
|
||||
ruleIdentifierList.Reset();
|
||||
|
||||
return rakPeer->Connect(host, masterServerPort, 0, 0);
|
||||
}
|
||||
|
||||
void MasterClient::Disconnect(void)
|
||||
{
|
||||
if (IsConnected())
|
||||
DelistServer();
|
||||
|
||||
rakPeer->Disconnect(100);
|
||||
}
|
||||
|
||||
bool MasterClient::IsConnected(void)
|
||||
{
|
||||
unsigned short numberOfSystems;
|
||||
rakPeer->GetConnectionList(0, &numberOfSystems);
|
||||
return numberOfSystems==1;
|
||||
}
|
||||
|
||||
void MasterClient::AddQueryRule(char *ruleIdentifier)
|
||||
{
|
||||
if (ruleIdentifier && IsReservedRuleIdentifier(ruleIdentifier)==false)
|
||||
stringCompressor->EncodeString(ruleIdentifier, 256, &ruleIdentifierList);
|
||||
}
|
||||
void MasterClient::ClearQueryRules(void)
|
||||
{
|
||||
ruleIdentifierList.Reset();
|
||||
}
|
||||
void MasterClient::QueryMasterServer(void)
|
||||
{
|
||||
BitStream outgoingBitStream;
|
||||
// Request to the master server for the list of servers that contain at least one of the specified keys
|
||||
outgoingBitStream.Write((unsigned char)ID_QUERY_MASTER_SERVER);
|
||||
if (ruleIdentifierList.GetNumberOfBitsUsed()>0)
|
||||
outgoingBitStream.WriteBits(ruleIdentifierList.GetData(), ruleIdentifierList.GetNumberOfBitsUsed(), false);
|
||||
rakPeer->Send(&outgoingBitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_PLAYER_ID, true);
|
||||
}
|
||||
|
||||
void MasterClient::PingServers(void)
|
||||
{
|
||||
unsigned serverIndex;
|
||||
|
||||
for (serverIndex=0; serverIndex < gameServerList.serverList.Size(); serverIndex++)
|
||||
{
|
||||
rakPeer->Ping((char*)rakPeer->PlayerIDToDottedIP(gameServerList.serverList[serverIndex]->connectionIdentifier),
|
||||
gameServerList.serverList[serverIndex]->connectionIdentifier.port, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterClient::Update(RakPeerInterface *peer)
|
||||
{
|
||||
BitStream outgoingBitStream;
|
||||
|
||||
if (listServer && ((serverListed && localServerModified) || (serverListed==false)))
|
||||
{
|
||||
outgoingBitStream.Write((unsigned char)ID_MASTER_SERVER_SET_SERVER);
|
||||
SerializeServer(&localServer, &outgoingBitStream);
|
||||
rakPeer->Send(&outgoingBitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_PLAYER_ID, true);
|
||||
serverListed=true;
|
||||
localServerModified=false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MasterClient::OnReceive(RakPeerInterface *peer, Packet *packet)
|
||||
{
|
||||
switch(packet->data[0])
|
||||
{
|
||||
case ID_NO_FREE_INCOMING_CONNECTIONS:
|
||||
OnMasterServerFull();
|
||||
return false; // Do not absorb packet
|
||||
case ID_DISCONNECTION_NOTIFICATION:
|
||||
OnLostConnection();
|
||||
return false; // Do not absorb packet
|
||||
case ID_CONNECTION_LOST:
|
||||
OnLostConnection();
|
||||
return false; // Do not absorb packet
|
||||
case ID_MODIFIED_PACKET:
|
||||
OnModifiedPacket();
|
||||
return false;
|
||||
case ID_CONNECTION_ATTEMPT_FAILED:
|
||||
OnConnectionAttemptFailed();
|
||||
return false; // Do not absorb packet
|
||||
case ID_MASTER_SERVER_UPDATE_SERVER:
|
||||
HandleServerListResponse(packet, false);
|
||||
return true; // Absorb packet
|
||||
case ID_MASTER_SERVER_SET_SERVER:
|
||||
HandleServerListResponse(packet, true);
|
||||
return true; // Absorb packet
|
||||
case ID_PONG:
|
||||
HandlePong(packet);
|
||||
return false; // Absorb packet
|
||||
case ID_RELAYED_CONNECTION_NOTIFICATION:
|
||||
HandleRelayedConnectionNotification(packet);
|
||||
return true; // Absorb packet
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MasterClient::ConnectionAttemptNotification(char *serverIP, unsigned short serverPort)
|
||||
{
|
||||
if (serverIP==0)
|
||||
return;
|
||||
|
||||
BitStream bitStream(23);
|
||||
bitStream.Write((unsigned char)ID_RELAYED_CONNECTION_NOTIFICATION);
|
||||
bitStream.Write(localServer.connectionIdentifier.port); // Your own game client port
|
||||
bitStream.Write(serverPort); // The game server you are connecting to port
|
||||
stringCompressor->EncodeString(serverIP, 22, &bitStream); // The game server IP you are connecting to
|
||||
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true);
|
||||
}
|
||||
void MasterClient::ListServer(void)
|
||||
{
|
||||
listServer=true;
|
||||
}
|
||||
void MasterClient::DelistServer(void)
|
||||
{
|
||||
BitStream bitStream;
|
||||
listServer=false;
|
||||
if (serverListed)
|
||||
{
|
||||
bitStream.Write((unsigned char)ID_MASTER_SERVER_DELIST_SERVER);
|
||||
bitStream.Write(localServer.connectionIdentifier.port);
|
||||
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_PLAYER_ID, true);
|
||||
serverListed=false;
|
||||
}
|
||||
}
|
||||
void MasterClient::HandleServerListResponse(Packet *packet, bool overwriteExisting)
|
||||
{
|
||||
int serverIndex;
|
||||
bool newServerAdded;
|
||||
unsigned short numberOfServers;
|
||||
GameServer *gameServer;
|
||||
RakNetTime currentTime;
|
||||
BitStream inputBitStream(packet->data, packet->length, false);
|
||||
inputBitStream.IgnoreBits(8*sizeof(unsigned char));
|
||||
|
||||
if (inputBitStream.ReadCompressed(numberOfServers)==false)
|
||||
return;
|
||||
|
||||
currentTime=RakNet::GetTime();
|
||||
|
||||
for (serverIndex=0; serverIndex < numberOfServers; serverIndex++)
|
||||
{
|
||||
gameServer = DeserializeServer(&inputBitStream);
|
||||
|
||||
// Find the existing game server that matches this port/address.
|
||||
// If not found, then add it to the list.
|
||||
// else update it
|
||||
// If (overwriteExisting)
|
||||
// - Delete any fields that exist in the old and not in the new
|
||||
// Add any fields that exist in the new and do not exist in the old
|
||||
// Update any fields that exist in both
|
||||
// Unset the deletion mark
|
||||
gameServer=UpdateServerList(gameServer,overwriteExisting, &newServerAdded);
|
||||
if (newServerAdded)
|
||||
{
|
||||
// Ping the new server
|
||||
rakPeer->Ping((char*)rakPeer->PlayerIDToDottedIP(gameServer->connectionIdentifier),
|
||||
gameServer->connectionIdentifier.port, false);
|
||||
|
||||
// Returns true if new server updated
|
||||
OnGameServerListAddition(gameServer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// returns false if an existing server is modified
|
||||
OnGameServerListRuleUpdate(gameServer);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Any servers that were not updated on the last call to UpdateServerList
|
||||
// will have lastUpdateTime time as less than the current time
|
||||
// Delete those
|
||||
serverIndex=0;
|
||||
while (serverIndex < (int) gameServerList.serverList.Size())
|
||||
{
|
||||
if (gameServerList.serverList[serverIndex]->lastUpdateTime < currentTime)
|
||||
{
|
||||
delete gameServerList.serverList[serverIndex];
|
||||
gameServerList.serverList.RemoveAtIndex(serverIndex);
|
||||
}
|
||||
else
|
||||
serverIndex++;
|
||||
}
|
||||
|
||||
OnGameServerListQueryComplete();
|
||||
}
|
||||
void MasterClient::HandleRelayedConnectionNotification(Packet *packet)
|
||||
{
|
||||
PlayerID clientSystem;
|
||||
BitStream incomingBitStream(packet->data, packet->length, false);
|
||||
incomingBitStream.IgnoreBits(8*sizeof(unsigned char));
|
||||
incomingBitStream.Read(clientSystem.binaryAddress);
|
||||
incomingBitStream.Read(clientSystem.port);
|
||||
|
||||
OnConnectionRequest(rakPeer->PlayerIDToDottedIP(clientSystem), clientSystem.port);
|
||||
}
|
||||
void MasterClient::PostRule(char *ruleIdentifier, char *stringData, int intData)
|
||||
{
|
||||
if (ruleIdentifier)
|
||||
{
|
||||
if (IsReservedRuleIdentifier(ruleIdentifier))
|
||||
return;
|
||||
|
||||
localServerModified |= UpdateServerRule(&localServer, ruleIdentifier, stringData, intData);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterClient::RemoveRule(char *ruleIdentifier)
|
||||
{
|
||||
if (ruleIdentifier)
|
||||
localServerModified |= RemoveServerRule(&localServer, ruleIdentifier);
|
||||
}
|
||||
|
||||
void MasterClient::OnLostConnection(void)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Connection lost.\n");
|
||||
#endif
|
||||
}
|
||||
void MasterClient::OnConnectionAttemptFailed(void)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Connection attempt failed.\n");
|
||||
#endif
|
||||
}
|
||||
void MasterClient::OnMasterServerFull(void)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Server full.\n");
|
||||
#endif
|
||||
}
|
||||
void MasterClient::OnModifiedPacket(void)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Modified packet.\n");
|
||||
#endif
|
||||
}
|
||||
void MasterClient::OnGameServerListAddition(GameServer *newServer)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Server added.\n");
|
||||
#endif
|
||||
}
|
||||
void MasterClient::OnGameServerListRuleUpdate(GameServer *updatedServer)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Rules updated for a server.\n");
|
||||
#endif
|
||||
}
|
||||
void MasterClient::OnGameServerListQueryComplete(void)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Query complete.\n");
|
||||
#endif
|
||||
}
|
||||
// Event when a game client wants to connect to our server
|
||||
// You should call AdvertiseSystem to the passed IP and port from your game instance
|
||||
void MasterClient::OnConnectionRequest(const char *clientIP, unsigned short clientPort)
|
||||
{
|
||||
#ifdef _SHOW_MASTER_SERVER_PRINTF
|
||||
printf("Master client indicates a connection request from %s:%i.\n", clientIP, clientPort);
|
||||
#endif
|
||||
rakPeer->AdvertiseSystem((char*)clientIP, clientPort,0,0);
|
||||
}
|
||||
Reference in New Issue
Block a user