This repository has been archived on 2026-04-30. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Tortuga/server/server_connections.cpp
T
Kayne Ruse 5031352fe3 Fixed the bug (read more)
The bug was being caused by a lack of a new player object being sent to
some clients. Fixed this by adding in the sending code, and preventing the
new entries being "registered" until the end of the HandleJoinRequest()
method.

Hopefully I can simply abstract away some of this code soon.
2014-04-29 01:47:01 +10:00

187 lines
6.4 KiB
C++

/* Copyright: (c) Kayne Ruse 2013, 2014
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
#include "server_application.hpp"
#include <stdexcept>
#include <iostream>
//-------------------------
//Handle various network input
//-------------------------
void ServerApplication::HandleBroadcastRequest(SerialPacket packet) {
//pack the server's data
packet.meta.type = SerialPacket::Type::BROADCAST_RESPONSE;
packet.serverInfo.networkVersion = NETWORK_VERSION;
snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str());
packet.serverInfo.playerCount = playerMap.size();
//bounce this packet
char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer);
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
}
void ServerApplication::HandleJoinRequest(SerialPacket packet) {
//create the new client
ClientEntry newClient;
newClient.address = packet.meta.srcAddress;
//TODO: move this into the player management code
//create the new player
PlayerEntry newPlayer;
newPlayer.clientIndex = ClientEntry::uidCounter;
newPlayer.player = packet.clientInfo.player;
newPlayer.handle = packet.clientInfo.handle;
newPlayer.avatar = packet.clientInfo.avatar;
//send the client their info
packet.meta.type = SerialPacket::Type::JOIN_RESPONSE;
packet.clientInfo.clientIndex = ClientEntry::uidCounter;
packet.clientInfo.playerIndex = PlayerEntry::uidCounter;
//bounce this packet
char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer);
network.Send(&newClient.address, buffer, PACKET_BUFFER_SIZE);
//send the new player to all clients
packet.meta.type = SerialPacket::Type::PLAYER_NEW;
packet.playerInfo.playerIndex = PlayerEntry::uidCounter;
strncpy(packet.playerInfo.handle, newPlayer.handle.c_str(), PACKET_STRING_SIZE);
strncpy(packet.playerInfo.avatar, newPlayer.avatar.c_str(), PACKET_STRING_SIZE);
packet.playerInfo.position = newPlayer.position;
packet.playerInfo.motion = newPlayer.motion;
PumpPacket(packet);
//finished this routine
clientMap[ClientEntry::uidCounter] = newClient;
playerMap[PlayerEntry::uidCounter] = newPlayer;
ClientEntry::uidCounter++;
PlayerEntry::uidCounter++;
std::cout << "Connect, total: " << clientMap.size() << std::endl;
}
void ServerApplication::HandleSynchronize(SerialPacket packet) {
//TODO: compensate for large distances
//send all the server's data to this client
SerialPacket newPacket;
char buffer[PACKET_BUFFER_SIZE];
//players
newPacket.meta.type = SerialPacket::Type::PLAYER_UPDATE;
for (auto& it : playerMap) {
//TODO: update this for the expanded PlayerEntry structure
newPacket.playerInfo.playerIndex = it.first;
snprintf(newPacket.playerInfo.handle, PACKET_STRING_SIZE, "%s", it.second.handle.c_str());
snprintf(newPacket.playerInfo.avatar, PACKET_STRING_SIZE, "%s", it.second.avatar.c_str());
newPacket.playerInfo.mapIndex = it.second.mapIndex;
newPacket.playerInfo.position = it.second.position;
newPacket.playerInfo.motion = it.second.motion;
serialize(&newPacket, buffer);
network.Send(&clientMap[packet.clientInfo.clientIndex].address, buffer, PACKET_BUFFER_SIZE);
}
}
void ServerApplication::HandleDisconnect(SerialPacket packet) {
//TODO: authenticate who is disconnecting/kicking
//TODO: define the difference between unloading and deletng a player
//disconnect the specified client
char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer);
network.Send(&clientMap[packet.clientInfo.clientIndex].address, buffer, PACKET_BUFFER_SIZE);
clientMap.erase(packet.clientInfo.clientIndex);
//prep the delete packet
SerialPacket delPacket;
delPacket.meta.type = SerialPacket::Type::PLAYER_DELETE;
//delete server and client side players
erase_if(playerMap, [&](std::pair<int, PlayerEntry> it) -> bool {
//find the internal players to delete
if (it.second.clientIndex == packet.clientInfo.clientIndex) {
//send the delete player command to all clients
delPacket.playerInfo.playerIndex = it.first;
PumpPacket(delPacket);
//delete this player object
return true;
}
//don't delete this player object
return false;
});
//finished this routine
std::cout << "Disconnect, total: " << clientMap.size() << std::endl;
}
void ServerApplication::HandleShutdown(SerialPacket packet) {
//TODO: authenticate who is shutting the server down
//end the server
running = false;
//disconnect all clients
packet.meta.type = SerialPacket::Type::DISCONNECT;
packet.clientInfo.clientIndex = -1;
PumpPacket(packet);
//finished this routine
std::cout << "Shutdown signal accepted" << std::endl;
}
void ServerApplication::HandlePlayerUpdate(SerialPacket packet) {
//TODO: this should be moved elsewhere
if (playerMap.find(packet.playerInfo.playerIndex) == playerMap.end()) {
throw(std::runtime_error("Cannot update a non-existant player"));
}
//TODO: the server needs it's own movement system too
playerMap[packet.playerInfo.playerIndex].position = packet.playerInfo.position;
playerMap[packet.playerInfo.playerIndex].motion = packet.playerInfo.motion;
PumpPacket(packet);
}
void ServerApplication::HandleRegionRequest(SerialPacket packet) {
//TODO: this should be moved elsewhere
packet.meta.type = SerialPacket::Type::REGION_CONTENT;
packet.regionInfo.region = regionPager.GetRegion(packet.regionInfo.x, packet.regionInfo.y);
//send the content
char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer);
network.Send(&packet.meta.srcAddress, buffer, PACKET_BUFFER_SIZE);
}
void ServerApplication::PumpPacket(SerialPacket packet) {
//NOTE: I don't really like this, but it'll do for now
char buffer[PACKET_BUFFER_SIZE];
serialize(&packet, buffer);
for (auto& it : clientMap) {
network.Send(&it.second.address, buffer, PACKET_BUFFER_SIZE);
}
}