Files
minecraft-pe-0.6.1/src/network/RakNetInstance.cpp
2026-03-02 22:04:18 +03:00

741 lines
18 KiB
C++
Executable File

#include "RakNetInstance.h"
#include "Packet.h"
#include "NetEventCallback.h"
#include "../raknet/RakPeerInterface.h"
#include "../raknet/BitStream.h"
#include "../raknet/MessageIdentifiers.h"
#include "../raknet/GetTime.h"
#include "../AppConstants.h"
#include "../platform/log.h"
#define APP_IDENTIFIER "MCCPP;" APP_VERSION_STRING ";"
#define APP_IDENTIFIER_MINECON "MCCPP;MINECON;"
RakNetInstance::RakNetInstance()
: rakPeer(NULL),
_isServer(false),
_isLoggedIn(false)
{
rakPeer = RakNet::RakPeerInterface::GetInstance();
rakPeer->SetTimeoutTime(20000, RakNet::UNASSIGNED_SYSTEM_ADDRESS);
rakPeer->SetOccasionalPing(true);
}
RakNetInstance::~RakNetInstance()
{
if (rakPeer)
{
rakPeer->Shutdown(100, 0);
RakNet::RakPeerInterface::DestroyInstance(rakPeer);
rakPeer = NULL;
}
}
bool RakNetInstance::host(const std::string& localName, int port, int maxConnections /* = 4 */)
{
if (rakPeer->IsActive())
{
rakPeer->Shutdown(500);
}
RakNet::SocketDescriptor socket(port, 0);
socket.socketFamily = AF_INET;
rakPeer->SetMaximumIncomingConnections(maxConnections);
RakNet::StartupResult result = rakPeer->Startup(maxConnections, &socket, 1);
_isServer = true;
isPingingForServers = false;
return (result == RakNet::RAKNET_STARTED);
}
void RakNetInstance::announceServer(const std::string& localName)
{
if (_isServer && rakPeer->IsActive())
{
RakNet::RakString connectionData;
#if defined(MINECON)
connectionData += APP_IDENTIFIER_MINECON;
#else
connectionData += APP_IDENTIFIER;
#endif
connectionData += localName.c_str();
RakNet::BitStream bitStream;
bitStream.Write(connectionData);
rakPeer->SetOfflinePingResponse((const char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
}
}
bool RakNetInstance::connect(const char* host, int port)
{
_isLoggedIn = false;
RakNet::StartupResult result;
RakNet::SocketDescriptor socket(0, 0);
socket.socketFamily = AF_INET;
if (rakPeer->IsActive())
{
rakPeer->Shutdown(500);
}
result = rakPeer->Startup(4, &socket, 1);
_isServer = false;
isPingingForServers = false;
if (result == RakNet::RAKNET_STARTED)
{
RakNet::ConnectionAttemptResult connectResult = rakPeer->Connect(host, port, NULL, 0, NULL, 0, 12, 500, 0);
return (connectResult == RakNet::CONNECTION_ATTEMPT_STARTED);
}
return false;
}
void RakNetInstance::disconnect()
{
if (rakPeer->IsActive())
{
rakPeer->Shutdown(500);
}
_isLoggedIn = false;
_isServer = false;
isPingingForServers = false;
}
void RakNetInstance::pingForHosts(int basePort)
{
if (!rakPeer->IsActive())
{
RakNet::SocketDescriptor socket(0, 0);
rakPeer->Startup(4, &socket, 1);
}
isPingingForServers = true;
pingPort = basePort;
lastPingTime = RakNet::GetTimeMS();
for (int i = 0; i < 4; ++i)
rakPeer->Ping("255.255.255.255", basePort + i, true);
}
void RakNetInstance::stopPingForHosts()
{
if (isPingingForServers)
{
rakPeer->Shutdown(0);
isPingingForServers = false;
}
}
const ServerList& RakNetInstance::getServerList()
{
return availableServers;
}
void RakNetInstance::clearServerList()
{
availableServers.clear();
/*
for (int i = 0; i < 20; ++i) {
PingedCompatibleServer ps;
ps.isSpecial = false;
ps.name = "Fake-Real";
ps.address.FromString("192.168.1.236|19132");
availableServers.push_back(ps);
}
*/
}
RakNet::RakPeerInterface* RakNetInstance::getPeer()
{
return rakPeer;
}
bool RakNetInstance::isProbablyBroken() {
return rakPeer->errorState < -100;
}
void RakNetInstance::resetIsBroken() {
rakPeer->errorState = 0;
}
bool RakNetInstance::isMyLocalGuid(const RakNet::RakNetGUID& guid)
{
return rakPeer->IsActive() && rakPeer->GetMyGUID() == guid;
}
void RakNetInstance::runEvents(NetEventCallback* callback)
{
RakNet::Packet* currentEvent;
while ((currentEvent = rakPeer->Receive()) != NULL)
{
int packetId = currentEvent->data[0];
int length = currentEvent->length;
RakNet::BitStream activeBitStream(currentEvent->data + 1, length - 1, false);
if (callback) {
if (packetId < ID_USER_PACKET_ENUM)
{
//LOGI("Received event: %s\n", getPacketName(packetId));
switch (packetId)
{
case ID_NEW_INCOMING_CONNECTION:
callback->onNewClient(currentEvent->guid);
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
serverGuid = currentEvent->guid;
callback->onConnect(currentEvent->guid);
break;
case ID_CONNECTION_ATTEMPT_FAILED:
callback->onUnableToConnect();
break;
case ID_DISCONNECTION_NOTIFICATION:
case ID_CONNECTION_LOST:
callback->onDisconnect(currentEvent->guid);
break;
case ID_UNCONNECTED_PONG:
{
RakNet::TimeMS time;
RakNet::RakString data;
activeBitStream.Read(time);
activeBitStream.Read(data);
int index = handleUnconnectedPong(data, currentEvent, APP_IDENTIFIER, false);
if (index < 0) {
// Check if it's an official Mojang MineCon server
index = handleUnconnectedPong(data, currentEvent, APP_IDENTIFIER_MINECON, true);
if (index >= 0) availableServers[index].isSpecial = true;
}
}
break;
}
}
else
{
int userPacketId = packetId - ID_USER_PACKET_ENUM;
bool isStatusPacket = userPacketId <= PACKET_READY;
if (isStatusPacket || _isServer || _isLoggedIn) {
if (Packet* packet = MinecraftPackets::createPacket(packetId)) {
packet->read(&activeBitStream);
packet->handle(currentEvent->guid, callback);
delete packet;
}
}
}
}
rakPeer->DeallocatePacket(currentEvent);
//delete activeBitStream;
}
if (isPingingForServers)
{
if (RakNet::GetTimeMS() - lastPingTime > 1000)
{
// remove servers that hasn't responded for a while
ServerList::iterator it = availableServers.begin();
for (; it != availableServers.end(); )
{
if (RakNet::GetTimeMS() - it->pingTime > 3000)
{
it = availableServers.erase(it);
}
else
{
++it;
}
}
pingForHosts(pingPort);
}
}
}
void RakNetInstance::send(Packet& packet) {
RakNet::BitStream bitStream;
packet.write(&bitStream);
if (_isServer)
{
// broadcast to all connected clients
rakPeer->Send(&bitStream, packet.priority, packet.reliability, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true);
}
else
{
// send to server
rakPeer->Send(&bitStream, packet.priority, packet.reliability, 0, serverGuid, false);
}
}
void RakNetInstance::send(const RakNet::RakNetGUID& guid, Packet& packet) {
RakNet::BitStream bitStream;
packet.write(&bitStream);
rakPeer->Send(&bitStream, packet.priority, packet.reliability, 0, guid, false);
}
void RakNetInstance::send(Packet* packet)
{
send(*packet);
delete packet;
}
void RakNetInstance::send(const RakNet::RakNetGUID& guid, Packet* packet)
{
send(guid, *packet);
delete packet;
}
#ifdef _DEBUG
const char* RakNetInstance::getPacketName(int packetId)
{
switch (packetId)
{
case ID_CONNECTED_PING:
return "ID_CONNECTED_PING";
case ID_UNCONNECTED_PING:
return "ID_UNCONNECTED_PING";
case ID_UNCONNECTED_PING_OPEN_CONNECTIONS:
return "ID_UNCONNECTED_PING_OPEN_CONNECTIONS";
case ID_CONNECTED_PONG:
return "ID_CONNECTED_PONG";
case ID_DETECT_LOST_CONNECTIONS:
return "ID_DETECT_LOST_CONNECTIONS";
case ID_OPEN_CONNECTION_REQUEST_1:
return "ID_OPEN_CONNECTION_REQUEST_1";
case ID_OPEN_CONNECTION_REPLY_1:
return "ID_OPEN_CONNECTION_REPLY_1";
case ID_OPEN_CONNECTION_REQUEST_2:
return "ID_OPEN_CONNECTION_REQUEST_2";
case ID_OPEN_CONNECTION_REPLY_2:
return "ID_OPEN_CONNECTION_REPLY_2";
case ID_CONNECTION_REQUEST:
return "ID_CONNECTION_REQUEST";
case ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY:
return "ID_REMOTE_SYSTEM_REQUIRES_PUBLIC_KEY";
case ID_OUR_SYSTEM_REQUIRES_SECURITY:
return "ID_OUR_SYSTEM_REQUIRES_SECURITY";
case ID_PUBLIC_KEY_MISMATCH:
return "ID_PUBLIC_KEY_MISMATCH";
case ID_OUT_OF_BAND_INTERNAL:
return "ID_OUT_OF_BAND_INTERNAL";
case ID_SND_RECEIPT_ACKED:
return "ID_SND_RECEIPT_ACKED";
case ID_SND_RECEIPT_LOSS:
return "ID_SND_RECEIPT_LOSS";
case ID_CONNECTION_REQUEST_ACCEPTED:
return "ID_CONNECTION_REQUEST_ACCEPTED";
case ID_CONNECTION_ATTEMPT_FAILED:
return "ID_CONNECTION_ATTEMPT_FAILED";
case ID_ALREADY_CONNECTED:
return "ID_ALREADY_CONNECTED";
case ID_NEW_INCOMING_CONNECTION:
return "ID_NEW_INCOMING_CONNECTION";
case ID_NO_FREE_INCOMING_CONNECTIONS:
return "ID_NO_FREE_INCOMING_CONNECTIONS";
case ID_DISCONNECTION_NOTIFICATION:
return "ID_DISCONNECTION_NOTIFICATION";
case ID_CONNECTION_LOST:
return "ID_CONNECTION_LOST";
case ID_CONNECTION_BANNED:
return "ID_CONNECTION_BANNED";
case ID_INVALID_PASSWORD:
return "ID_INVALID_PASSWORD";
case ID_INCOMPATIBLE_PROTOCOL_VERSION:
return "ID_INCOMPATIBLE_PROTOCOL_VERSION";
case ID_IP_RECENTLY_CONNECTED:
return "ID_IP_RECENTLY_CONNECTED";
case ID_TIMESTAMP:
return "ID_TIMESTAMP";
case ID_UNCONNECTED_PONG:
return "ID_UNCONNECTED_PONG";
case ID_ADVERTISE_SYSTEM:
return "ID_ADVERTISE_SYSTEM";
case ID_DOWNLOAD_PROGRESS:
return "ID_DOWNLOAD_PROGRESS";
case ID_REMOTE_DISCONNECTION_NOTIFICATION:
return "ID_REMOTE_DISCONNECTION_NOTIFICATION";
case ID_REMOTE_CONNECTION_LOST:
return "ID_REMOTE_CONNECTION_LOST";
case ID_REMOTE_NEW_INCOMING_CONNECTION:
return "ID_REMOTE_NEW_INCOMING_CONNECTION";
case ID_FILE_LIST_TRANSFER_HEADER:
return "ID_FILE_LIST_TRANSFER_HEADER";
case ID_FILE_LIST_TRANSFER_FILE:
return "ID_FILE_LIST_TRANSFER_FILE";
case ID_FILE_LIST_REFERENCE_PUSH_ACK:
return "ID_FILE_LIST_REFERENCE_PUSH_ACK";
case ID_DDT_DOWNLOAD_REQUEST:
return "ID_DDT_DOWNLOAD_REQUEST";
case ID_TRANSPORT_STRING:
return "ID_TRANSPORT_STRING";
case ID_REPLICA_MANAGER_CONSTRUCTION:
return "ID_REPLICA_MANAGER_CONSTRUCTION";
case ID_REPLICA_MANAGER_SCOPE_CHANGE:
return "ID_REPLICA_MANAGER_SCOPE_CHANGE";
case ID_REPLICA_MANAGER_SERIALIZE:
return "ID_REPLICA_MANAGER_SERIALIZE";
case ID_REPLICA_MANAGER_DOWNLOAD_STARTED:
return "ID_REPLICA_MANAGER_DOWNLOAD_STARTED";
case ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE:
return "ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE";
case ID_RAKVOICE_OPEN_CHANNEL_REQUEST:
return "ID_RAKVOICE_OPEN_CHANNEL_REQUEST";
case ID_RAKVOICE_OPEN_CHANNEL_REPLY:
return "ID_RAKVOICE_OPEN_CHANNEL_REPLY";
case ID_RAKVOICE_CLOSE_CHANNEL:
return "ID_RAKVOICE_CLOSE_CHANNEL";
case ID_RAKVOICE_DATA:
return "ID_RAKVOICE_DATA";
case ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE:
return "ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE";
case ID_AUTOPATCHER_CREATION_LIST:
return "ID_AUTOPATCHER_CREATION_LIST";
case ID_AUTOPATCHER_DELETION_LIST:
return "ID_AUTOPATCHER_DELETION_LIST";
case ID_AUTOPATCHER_GET_PATCH:
return "ID_AUTOPATCHER_GET_PATCH";
case ID_AUTOPATCHER_PATCH_LIST:
return "ID_AUTOPATCHER_PATCH_LIST";
case ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR:
return "ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR";
case ID_AUTOPATCHER_FINISHED_INTERNAL:
return "ID_AUTOPATCHER_FINISHED_INTERNAL";
case ID_AUTOPATCHER_FINISHED:
return "ID_AUTOPATCHER_FINISHED";
case ID_AUTOPATCHER_RESTART_APPLICATION:
return "ID_AUTOPATCHER_RESTART_APPLICATION";
case ID_NAT_PUNCHTHROUGH_REQUEST:
return "ID_NAT_PUNCHTHROUGH_REQUEST";
case ID_NAT_GROUP_PUNCHTHROUGH_REQUEST:
return "ID_NAT_GROUP_PUNCHTHROUGH_REQUEST";
case ID_NAT_GROUP_PUNCHTHROUGH_REPLY:
return "ID_NAT_GROUP_PUNCHTHROUGH_REPLY";
case ID_NAT_CONNECT_AT_TIME:
return "ID_NAT_CONNECT_AT_TIME";
case ID_NAT_GET_MOST_RECENT_PORT:
return "ID_NAT_GET_MOST_RECENT_PORT";
case ID_NAT_CLIENT_READY:
return "ID_NAT_CLIENT_READY";
case ID_NAT_GROUP_PUNCHTHROUGH_FAILURE_NOTIFICATION:
return "ID_NAT_GROUP_PUNCHTHROUGH_FAILURE_NOTIFICATION";
case ID_NAT_TARGET_NOT_CONNECTED:
return "ID_NAT_TARGET_NOT_CONNECTED";
case ID_NAT_TARGET_UNRESPONSIVE:
return "ID_NAT_TARGET_UNRESPONSIVE";
case ID_NAT_CONNECTION_TO_TARGET_LOST:
return "ID_NAT_CONNECTION_TO_TARGET_LOST";
case ID_NAT_ALREADY_IN_PROGRESS:
return "ID_NAT_ALREADY_IN_PROGRESS";
case ID_NAT_PUNCHTHROUGH_FAILED:
return "ID_NAT_PUNCHTHROUGH_FAILED";
case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
return "ID_NAT_PUNCHTHROUGH_SUCCEEDED";
case ID_NAT_GROUP_PUNCH_FAILED:
return "ID_NAT_GROUP_PUNCH_FAILED";
case ID_NAT_GROUP_PUNCH_SUCCEEDED:
return "ID_NAT_GROUP_PUNCH_SUCCEEDED";
case ID_READY_EVENT_SET:
return "ID_READY_EVENT_SET";
case ID_READY_EVENT_UNSET:
return "ID_READY_EVENT_UNSET";
case ID_READY_EVENT_ALL_SET:
return "ID_READY_EVENT_ALL_SET";
case ID_READY_EVENT_QUERY:
return "ID_READY_EVENT_QUERY";
case ID_LOBBY_GENERAL:
return "ID_LOBBY_GENERAL";
case ID_RPC_REMOTE_ERROR:
return "ID_RPC_REMOTE_ERROR";
case ID_RPC_PLUGIN:
return "ID_RPC_PLUGIN";
case ID_FILE_LIST_REFERENCE_PUSH:
return "ID_FILE_LIST_REFERENCE_PUSH";
case ID_READY_EVENT_FORCE_ALL_SET:
return "ID_READY_EVENT_FORCE_ALL_SET";
case ID_ROOMS_EXECUTE_FUNC:
return "ID_ROOMS_EXECUTE_FUNC";
case ID_ROOMS_LOGON_STATUS:
return "ID_ROOMS_LOGON_STATUS";
case ID_ROOMS_HANDLE_CHANGE:
return "ID_ROOMS_HANDLE_CHANGE";
case ID_LOBBY2_SEND_MESSAGE:
return "ID_LOBBY2_SEND_MESSAGE";
case ID_LOBBY2_SERVER_ERROR:
return "ID_LOBBY2_SERVER_ERROR";
case ID_FCM2_NEW_HOST:
return "ID_FCM2_NEW_HOST";
case ID_FCM2_REQUEST_FCMGUID:
return "ID_FCM2_REQUEST_FCMGUID";
case ID_FCM2_RESPOND_CONNECTION_COUNT:
return "ID_FCM2_RESPOND_CONNECTION_COUNT";
case ID_FCM2_INFORM_FCMGUID:
return "ID_FCM2_INFORM_FCMGUID";
case ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT:
return "ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT";
case ID_UDP_PROXY_GENERAL:
return "ID_UDP_PROXY_GENERAL";
case ID_SQLite3_EXEC:
return "ID_SQLite3_EXEC";
case ID_SQLite3_UNKNOWN_DB:
return "ID_SQLite3_UNKNOWN_DB";
case ID_SQLLITE_LOGGER:
return "ID_SQLLITE_LOGGER";
case ID_NAT_TYPE_DETECTION_REQUEST:
return "ID_NAT_TYPE_DETECTION_REQUEST";
case ID_NAT_TYPE_DETECTION_RESULT:
return "ID_NAT_TYPE_DETECTION_RESULT";
case ID_ROUTER_2_INTERNAL:
return "ID_ROUTER_2_INTERNAL";
case ID_ROUTER_2_FORWARDING_NO_PATH:
return "ID_ROUTER_2_FORWARDING_NO_PATH";
case ID_ROUTER_2_FORWARDING_ESTABLISHED:
return "ID_ROUTER_2_FORWARDING_ESTABLISHED";
case ID_ROUTER_2_REROUTED:
return "ID_ROUTER_2_REROUTED";
case ID_TEAM_BALANCER_INTERNAL:
return "ID_TEAM_BALANCER_INTERNAL";
case ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING:
return "ID_TEAM_BALANCER_REQUESTED_TEAM_CHANGE_PENDING";
case ID_TEAM_BALANCER_TEAMS_LOCKED:
return "ID_TEAM_BALANCER_TEAMS_LOCKED";
case ID_TEAM_BALANCER_TEAM_ASSIGNED:
return "ID_TEAM_BALANCER_TEAM_ASSIGNED";
case ID_LIGHTSPEED_INTEGRATION:
return "ID_LIGHTSPEED_INTEGRATION";
case ID_XBOX_LOBBY:
return "ID_XBOX_LOBBY";
case ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_SUCCESS:
return "ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_SUCCESS";
case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS:
return "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_SUCCESS";
case ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILURE:
return "ID_TWO_WAY_AUTHENTICATION_INCOMING_CHALLENGE_FAILURE";
case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE:
return "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_FAILURE";
case ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT:
return "ID_TWO_WAY_AUTHENTICATION_OUTGOING_CHALLENGE_TIMEOUT";
case ID_TWO_WAY_AUTHENTICATION_NEGOTIATION:
return "ID_TWO_WAY_AUTHENTICATION_NEGOTIATION";
case ID_CLOUD_POST_REQUEST:
return "ID_CLOUD_POST_REQUEST";
case ID_CLOUD_RELEASE_REQUEST:
return "ID_CLOUD_RELEASE_REQUEST";
case ID_CLOUD_GET_REQUEST:
return "ID_CLOUD_GET_REQUEST";
case ID_CLOUD_GET_RESPONSE:
return "ID_CLOUD_GET_RESPONSE";
case ID_CLOUD_UNSUBSCRIBE_REQUEST:
return "ID_CLOUD_UNSUBSCRIBE_REQUEST";
case ID_CLOUD_SERVER_TO_SERVER_COMMAND:
return "ID_CLOUD_SERVER_TO_SERVER_COMMAND";
case ID_CLOUD_SUBSCRIPTION_NOTIFICATION:
return "ID_CLOUD_SUBSCRIPTION_NOTIFICATION";
case ID_RESERVED_1:
return "ID_RESERVED_1";
case ID_RESERVED_2:
return "ID_RESERVED_2";
case ID_RESERVED_3:
return "ID_RESERVED_3";
case ID_RESERVED_4:
return "ID_RESERVED_4";
case ID_RESERVED_5:
return "ID_RESERVED_5";
case ID_RESERVED_6:
return "ID_RESERVED_6";
case ID_RESERVED_7:
return "ID_RESERVED_7";
case ID_RESERVED_8:
return "ID_RESERVED_8";
case ID_RESERVED_9:
return "ID_RESERVED_9";
default:
break;
}
return "Unknown or user-defined";
}
#endif
int RakNetInstance::handleUnconnectedPong(const RakNet::RakString& data, const RakNet::Packet* p, const char* appid, bool insertAtBeginning)
{
RakNet::RakString appIdentifier(appid);
// This weird code is a result of RakString.Find being pretty useless
bool emptyNameOrLonger = data.GetLength() >= appIdentifier.GetLength();
if ( !emptyNameOrLonger || appIdentifier.StrCmp(data.SubStr(0, appIdentifier.GetLength())) != 0)
return -1;
bool found = false;
for (unsigned int i = 0; i < availableServers.size(); i++) {
if (availableServers[i].address == p->systemAddress) {
availableServers[i].pingTime = RakNet::GetTimeMS();
bool emptyName = data.GetLength() == appIdentifier.GetLength();
if (emptyName)
availableServers[i].name = "";
else {
availableServers[i].name = data.SubStr(appIdentifier.GetLength(), data.GetLength() - appIdentifier.GetLength());
}
//LOGI("Swapping name: %s\n", availableServers[i].name.C_String());
return i;
}
}
PingedCompatibleServer server;
server.address = p->systemAddress;
server.pingTime = RakNet::GetTimeMS();
server.isSpecial = false;
server.name = data.SubStr(appIdentifier.GetLength(), data.GetLength() - appIdentifier.GetLength());
if (insertAtBeginning) {
availableServers.insert(availableServers.begin(), server);
return 0;
} else {
availableServers.push_back(server);
return availableServers.size() - 1;
}
}
void RakNetInstance::setIsLoggedIn( bool status ) {
_isLoggedIn = status;
}