Merge branch 'develop', read more

This merge handles a number of backend features, including error handling and other types of messages. I think there's more I could've done in this time, but this is what I have nonetheless.
This commit is contained in:
Kayne Ruse
2014-09-13 12:01:48 +10:00
21 changed files with 213 additions and 65 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ private:
//base statistics
Statistics stats;
//TODO: gameplay components: equipment, items, buffs, debuffs
//gameplay components: equipment, items, buffs, debuffs...
//metadata
int owner;
+3
View File
@@ -89,6 +89,7 @@ void ClientApplication::Init(int argc, char** argv) {
std::cout << "Internal sizes:" << std::endl;
DEBUG_OUTPUT_VAR(NETWORK_VERSION);
DEBUG_OUTPUT_VAR(sizeof(Region::type_t));
DEBUG_OUTPUT_VAR(sizeof(Region));
DEBUG_OUTPUT_VAR(REGION_WIDTH);
@@ -96,8 +97,10 @@ void ClientApplication::Init(int argc, char** argv) {
DEBUG_OUTPUT_VAR(REGION_DEPTH);
DEBUG_OUTPUT_VAR(REGION_TILE_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT);
DEBUG_OUTPUT_VAR(PACKET_STRING_SIZE);
DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE);
DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE);
DEBUG_OUTPUT_VAR(static_cast<int>(SerialPacketType::LAST));
#undef DEBUG_OUTPUT_VAR
+4 -2
View File
@@ -85,13 +85,15 @@ void CleanUp::Update() {
SetNextScene(SceneList::MAINMENU);
}
//BUGFIX: Eat incoming packets
//Eat incoming packets
while(network.Receive());
}
void CleanUp::Render(SDL_Surface* const screen) {
ConfigUtility& config = ConfigUtility::GetSingleton();
backButton.DrawTo(screen);
font.DrawStringTo("You have been disconnected.", screen, 50, 30);
font.DrawStringTo(config["client.disconnectMessage"], screen, 50, 30);
}
//-------------------------
+24 -4
View File
@@ -73,6 +73,14 @@ InWorld::InWorld(
//TODO: Tile size and tile sheet should be loaded elsewhere
tileSheet.Load(config["dir.tilesets"] + "terrain.bmp", 32, 32);
//send this player's character info
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_NEW;
strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
//request a sync
RequestSynchronize();
@@ -142,9 +150,11 @@ void InWorld::Update() {
camera.y = localCharacter->GetOrigin().y - camera.marginY;
//check the connection
if (Clock::now() - lastBeat > std::chrono::seconds(5)) {
if (Clock::now() - lastBeat > std::chrono::seconds(3)) {
if (attemptedBeats > 2) {
throw(std::runtime_error("Connection lost"));
RequestDisconnect();
SetNextScene(SceneList::CLEANUP);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "Error: Lost connection to the server";
}
ServerPacket newPacket;
@@ -302,6 +312,9 @@ void InWorld::HandlePacket(SerialPacket* const argPacket) {
case SerialPacketType::CHARACTER_UPDATE:
HandleCharacterUpdate(static_cast<CharacterPacket*>(argPacket));
break;
case SerialPacketType::CHARACTER_REJECTION:
HandleCharacterRejection(static_cast<TextPacket*>(argPacket));
break;
case SerialPacketType::REGION_CONTENT:
HandleRegionContent(static_cast<RegionPacket*>(argPacket));
break;
@@ -330,6 +343,7 @@ void InWorld::HandlePong(ServerPacket* const argPacket) {
void InWorld::HandleDisconnect(ClientPacket* const argPacket) {
//TODO: More needed in the disconnection
SetNextScene(SceneList::CLEANUP);
ConfigUtility::GetSingleton()["client.disconnectMessage"] = "You have been disconnected";
}
void InWorld::HandleCharacterNew(CharacterPacket* const argPacket) {
@@ -366,7 +380,6 @@ void InWorld::HandleCharacterNew(CharacterPacket* const argPacket) {
localCharacter = &newCharacter;
//setup the camera
//TODO: move this?
camera.width = GetScreen()->w;
camera.height = GetScreen()->h;
@@ -390,7 +403,6 @@ void InWorld::HandleCharacterDelete(CharacterPacket* const argPacket) {
void InWorld::HandleCharacterUpdate(CharacterPacket* const argPacket) {
if (characterMap.find(argPacket->characterIndex) == characterMap.end()) {
std::cout << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl;
HandleCharacterNew(argPacket);
return;
}
@@ -405,6 +417,14 @@ void InWorld::HandleCharacterUpdate(CharacterPacket* const argPacket) {
}
}
void InWorld::HandleCharacterRejection(TextPacket* const argPacket) {
RequestDisconnect();
SetNextScene(SceneList::CLEANUP);
ConfigUtility& config = ConfigUtility::GetSingleton();
config["client.disconnectMessage"] = "Error: ";
config["client.disconnectMessage"] += argPacket->text;
}
void InWorld::HandleRegionContent(RegionPacket* const argPacket) {
//replace existing regions
regionPager.UnloadRegion(argPacket->x, argPacket->y);
+4 -1
View File
@@ -83,6 +83,7 @@ protected:
void HandleCharacterNew(CharacterPacket* const);
void HandleCharacterDelete(CharacterPacket* const);
void HandleCharacterUpdate(CharacterPacket* const);
void HandleCharacterRejection(TextPacket* const);
void HandleRegionContent(RegionPacket* const);
//Server control
@@ -113,7 +114,8 @@ protected:
//UI
Button disconnectButton;
Button shutDownButton;
//TODO: Review the camera
//the camera structure
struct {
int x = 0, y = 0;
int width = 0, height = 0;
@@ -125,6 +127,7 @@ protected:
Character* localCharacter = nullptr;
//connections
//TODO: This needs it's own utility, for both InWorld and InCombat
typedef std::chrono::steady_clock Clock;
Clock::time_point lastBeat = Clock::now();
int attemptedBeats = 0;
+9 -8
View File
@@ -25,6 +25,7 @@
#include "utility.hpp"
#include <stdexcept>
#include <iostream>
//-------------------------
//Public access members
@@ -63,7 +64,7 @@ LobbyMenu::LobbyMenu(int* const argClientIndex, int* const argAccountIndex):
//set the server list's position
listBox = {300, 50, 200, font.GetCharH()};
//BUGFIX: Eat incoming packets
//Eat incoming packets
while(network.Receive());
//Initial broadcast
@@ -192,6 +193,9 @@ void LobbyMenu::HandlePacket(SerialPacket* const argPacket) {
case SerialPacketType::JOIN_RESPONSE:
HandleJoinResponse(static_cast<ClientPacket*>(argPacket));
break;
case SerialPacketType::JOIN_REJECTION:
HandleJoinRejection(static_cast<TextPacket*>(argPacket));
break;
//handle errors
default:
throw(std::runtime_error(std::string() + "Unknown SerialPacketType encountered in LobbyMenu: " + to_string_custom(static_cast<int>(argPacket->type)) ));
@@ -219,14 +223,11 @@ void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) {
accountIndex = argPacket->accountIndex;
network.Bind(argPacket->srcAddress, Channels::SERVER);
SetNextScene(SceneList::INWORLD);
}
//send this player's character info
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_NEW;
strncpy(newPacket.handle, config["client.handle"].c_str(), PACKET_STRING_SIZE);
strncpy(newPacket.avatar, config["client.avatar"].c_str(), PACKET_STRING_SIZE);
newPacket.accountIndex = accountIndex;
network.SendTo(Channels::SERVER, &newPacket);
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
//TODO: Better output
std::cerr << "Error: " << argPacket->text << std::endl;
}
//-------------------------
+1
View File
@@ -63,6 +63,7 @@ protected:
void HandlePacket(SerialPacket* const);
void HandleBroadcastResponse(ServerPacket* const);
void HandleJoinResponse(ClientPacket* const);
void HandleJoinRejection(TextPacket* const);
//server control
void SendBroadcastRequest();
@@ -46,7 +46,7 @@ void serializeCharacter(void* buffer, CharacterPacket* packet) {
//stats structure
serializeStatistics(&buffer, &packet->stats);
//TODO: gameplay components: equipment, items, buffs, debuffs
//gameplay components: equipment, items, buffs, debuffs...
}
void deserializeCharacter(void* buffer, CharacterPacket* packet) {
@@ -70,5 +70,5 @@ void deserializeCharacter(void* buffer, CharacterPacket* packet) {
//stats structure
deserializeStatistics(&buffer, &packet->stats);
//TODO: gameplay components: equipment, items, buffs, debuffs
//gameplay components: equipment, items, buffs, debuffs...
}
@@ -44,7 +44,7 @@ struct CharacterPacket : SerialPacketBase {
//gameplay
Statistics stats;
//TODO: gameplay components: equipment, items, buffs, debuffs
//gameplay components: equipment, items, buffs, debuffs...
};
void serializeCharacter(void* buffer, CharacterPacket* packet);
@@ -0,0 +1,40 @@
/* 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 "text_packet.hpp"
#include "serial_utility.hpp"
void serializeText(void* buffer, TextPacket* packet) {
serialCopy(&buffer, &packet->type, sizeof(SerialPacketType));
//content
serialCopy(&buffer, packet->name, PACKET_STRING_SIZE);
serialCopy(&buffer, packet->text, PACKET_STRING_SIZE);
}
void deserializeText(void* buffer, TextPacket* packet) {
deserialCopy(&buffer, &packet->type, sizeof(SerialPacketType));
//content
deserialCopy(&buffer, packet->name, PACKET_STRING_SIZE);
deserialCopy(&buffer, packet->text, PACKET_STRING_SIZE);
}
@@ -0,0 +1,35 @@
/* 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.
*/
#ifndef TEXTPACKET_HPP_
#define TEXTPACKET_HPP_
#include "serial_packet_base.hpp"
struct TextPacket : SerialPacketBase {
char name[PACKET_STRING_SIZE];
char text[PACKET_STRING_SIZE];
};
void serializeText(void* buffer, TextPacket* packet);
void deserializeText(void* buffer, TextPacket* packet);
#endif
+3 -1
View File
@@ -27,18 +27,20 @@
#include "client_packet.hpp"
#include "region_packet.hpp"
#include "server_packet.hpp"
#include "text_packet.hpp"
//SerialPacketBase is defined in serial_packet_base.hpp
typedef SerialPacketBase SerialPacket;
//DOCS: NETWORK_VERSION is used to discern compatible servers and clients
constexpr int NETWORK_VERSION = 20140831;
constexpr int NETWORK_VERSION = 20140909;
union MaxPacket {
CharacterPacket a;
ClientPacket b;
RegionPacket c;
ServerPacket d;
TextPacket e;
};
constexpr int MAX_PACKET_SIZE = sizeof(MaxPacket);
+14 -2
View File
@@ -52,7 +52,6 @@ enum class SerialPacketType {
//Connecting to a server as a client
JOIN_REQUEST,
JOIN_RESPONSE,
JOIN_REJECTION,
//client requests all information from the server
SYNCHRONIZE,
@@ -88,10 +87,23 @@ enum class SerialPacketType {
CHARACTER_STATS_REQUEST,
CHARACTER_STATS_RESPONSE,
//reject a character request
//-------------------------
//TextPacket
// name, text
//-------------------------
//general speech
TEXT_BROADCAST,
//rejection/error messages
SHUTDOWN_REJECTION,
JOIN_REJECTION,
CHARACTER_REJECTION,
//-------------------------
//not used
//-------------------------
LAST
};
+13 -4
View File
@@ -26,6 +26,7 @@
#include "client_packet.hpp"
#include "region_packet.hpp"
#include "server_packet.hpp"
#include "text_packet.hpp"
#include <cstring>
@@ -53,7 +54,6 @@ void serializePacket(void* buffer, SerialPacketBase* packet) {
break;
case SerialPacketType::JOIN_REQUEST:
case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::SYNCHRONIZE:
case SerialPacketType::DISCONNECT:
case SerialPacketType::SHUTDOWN:
@@ -68,9 +68,14 @@ void serializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
case SerialPacketType::CHARACTER_STATS_RESPONSE:
case SerialPacketType::CHARACTER_REJECTION:
serializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
break;
case SerialPacketType::TEXT_BROADCAST:
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::SHUTDOWN_REJECTION:
case SerialPacketType::CHARACTER_REJECTION:
serializeText(buffer, static_cast<TextPacket*>(packet));
break;
}
}
@@ -88,7 +93,6 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
break;
case SerialPacketType::JOIN_REQUEST:
case SerialPacketType::JOIN_RESPONSE:
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::SYNCHRONIZE:
case SerialPacketType::DISCONNECT:
case SerialPacketType::SHUTDOWN:
@@ -103,8 +107,13 @@ void deserializePacket(void* buffer, SerialPacketBase* packet) {
case SerialPacketType::CHARACTER_UPDATE:
case SerialPacketType::CHARACTER_STATS_REQUEST:
case SerialPacketType::CHARACTER_STATS_RESPONSE:
case SerialPacketType::CHARACTER_REJECTION:
deserializeCharacter(buffer, static_cast<CharacterPacket*>(packet));
break;
case SerialPacketType::TEXT_BROADCAST:
case SerialPacketType::JOIN_REJECTION:
case SerialPacketType::SHUTDOWN_REJECTION:
case SerialPacketType::CHARACTER_REJECTION:
deserializeText(buffer, static_cast<TextPacket*>(packet));
break;
}
}
+1 -1
View File
@@ -26,7 +26,7 @@
#include <stdexcept>
//BUGFIX: memset() is used before sending a packet to remove old data; you don't want to send sensitive data over the network
//NOTE: memset() is used before sending a packet to remove old data; you don't want to send sensitive data over the network
//NOTE: don't confuse SerialPacketBase with UDPpacket
void UDPNetworkUtility::Open(int port) {
-1
View File
@@ -88,7 +88,6 @@ ConfigUtility::table_t ConfigUtility::Read(std::string fname) {
is.close();
//load in any subordinate config files
//TODO: Possibility of nesting config levels?
if (retTable.find("config.next") != retTable.end()) {
table_t subTable = Read(retTable["config.next"]);
retTable.insert(subTable.begin(), subTable.end());
+1 -1
View File
@@ -17,7 +17,7 @@ tiles = {
--custom generation systems here
function islandGenerator(region)
io.write("Generating (", Region.GetX(region), ", ", Region.GetY(region), ")\n")
-- io.write("Generating (", Region.GetX(region), ", ", Region.GetY(region), ")\n")
for i = 1, Region.GetWidth(region) do
for j = 1, Region.GetHeight(region) do
local dist = math.dist(0, 0, i + Region.GetX(region) -1, j + Region.GetY(region) -1)
+4 -4
View File
@@ -157,7 +157,7 @@ int CharacterManager::LoadCharacter(int owner, std::string handle, std::string a
newChar.baseStats.evasion = sqlite3_column_double(statement, 20);
newChar.baseStats.luck = sqlite3_column_double(statement, 21);
//TODO: gameplay components: equipment, items, buffs, debuffs
//gameplay components: equipment, items, buffs, debuffs...
//finish the routine
sqlite3_finalize(statement);
@@ -214,7 +214,7 @@ int CharacterManager::SaveCharacter(int uid) {
ret |= sqlite3_bind_double(statement, 17, character.baseStats.evasion) != SQLITE_OK;
ret |= sqlite3_bind_double(statement, 18, character.baseStats.luck) != SQLITE_OK;
//TODO: gameplay components: equipment, items, buffs, debuffs
//gameplay components: equipment, items, buffs, debuffs...
//check for binding errors
if (ret) {
@@ -225,7 +225,7 @@ int CharacterManager::SaveCharacter(int uid) {
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than something went horribly wrong
sqlite3_finalize(statement);
throw( std::runtime_error(std::string() + "Unknown SQL error when saving an account: " + sqlite3_errmsg(database)) );
throw( std::runtime_error(std::string() + "Unknown SQL error when saving a character: " + sqlite3_errmsg(database)) );
}
sqlite3_finalize(statement);
@@ -258,7 +258,7 @@ void CharacterManager::DeleteCharacter(int uid) {
if (sqlite3_step(statement) != SQLITE_DONE) {
//if this fails, than something went horribly wrong
sqlite3_finalize(statement);
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting an account: " + sqlite3_errmsg(database)) );
throw( std::runtime_error(std::string() + "Unknown SQL error when deleting a character: " + sqlite3_errmsg(database)) );
}
//finish the routine
+4 -1
View File
@@ -110,6 +110,7 @@ void ServerApplication::Init(int argc, char** argv) {
std::cout << "Internal sizes:" << std::endl;
DEBUG_OUTPUT_VAR(NETWORK_VERSION);
DEBUG_OUTPUT_VAR(sizeof(Region::type_t));
DEBUG_OUTPUT_VAR(sizeof(Region));
DEBUG_OUTPUT_VAR(REGION_WIDTH);
@@ -117,8 +118,10 @@ void ServerApplication::Init(int argc, char** argv) {
DEBUG_OUTPUT_VAR(REGION_DEPTH);
DEBUG_OUTPUT_VAR(REGION_TILE_FOOTPRINT);
DEBUG_OUTPUT_VAR(REGION_SOLID_FOOTPRINT);
DEBUG_OUTPUT_VAR(PACKET_STRING_SIZE);
DEBUG_OUTPUT_VAR(PACKET_BUFFER_SIZE);
DEBUG_OUTPUT_VAR(MAX_PACKET_SIZE);
DEBUG_OUTPUT_VAR(static_cast<int>(SerialPacketType::LAST));
#undef DEBUG_OUTPUT_VAR
@@ -148,7 +151,7 @@ void ServerApplication::Proc() {
//TODO: This could be checked only every few seconds
//Check connections
for (auto& it : clientMap) {
if (std::chrono::steady_clock::now() - it.second.GetLastBeat() > std::chrono::seconds(5)) {
if (std::chrono::steady_clock::now() - it.second.GetLastBeat() > std::chrono::seconds(3)) {
ServerPacket newPacket;
newPacket.type = SerialPacketType::PING;
network.SendTo(it.second.GetAddress(), &newPacket);
+43 -28
View File
@@ -35,8 +35,6 @@ void ServerApplication::HandlePing(ServerPacket* const argPacket) {
void ServerApplication::HandlePong(ServerPacket* const argPacket) {
//find and update the specified client
//BUGFIX: running multiple clients on one computer will result in matching host values; check the ports too
for (auto& it : clientMap) {
if (it.second.GetAddress().host == argPacket->srcAddress.host &&
it.second.GetAddress().port == argPacket->srcAddress.port
@@ -60,16 +58,18 @@ void ServerApplication::HandleBroadcastRequest(ServerPacket* const argPacket) {
}
void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
//create the new client
ClientData newClient;
newClient.SetAddress(argPacket->srcAddress);
//load the user account
//TODO: handle passwords
int accountIndex = accountMgr.LoadAccount(argPacket->username, clientIndex);
//Cannot load
if (accountIndex < 0) {
//TODO: send rejection packet
std::cerr << "Error: Account already loaded: " << accountIndex << std::endl;
TextPacket newPacket;
newPacket.type = SerialPacketType::JOIN_REJECTION;
std::string msg = std::string() + "Account already loaded: " + argPacket->username;
memset(newPacket.name, 0, PACKET_STRING_SIZE);
strncpy(newPacket.text, msg.c_str(), PACKET_STRING_SIZE); //BUG: If the name is too long this would truncate it
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
return;
}
@@ -79,10 +79,14 @@ void ServerApplication::HandleJoinRequest(ClientPacket* const argPacket) {
newPacket.clientIndex = clientIndex;
newPacket.accountIndex = accountIndex;
network.SendTo(newClient.GetAddress(), static_cast<SerialPacket*>(&newPacket));
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
//register the client
ClientData newClient;
newClient.SetAddress(argPacket->srcAddress);
clientMap[clientIndex++] = newClient;
//finished this routine
clientMap[clientIndex++] = newClient;
std::cout << "New connection, " << clientMap.size() << " clients and " << accountMgr.GetContainer()->size() << " accounts total" << std::endl;
}
@@ -105,9 +109,9 @@ void ServerApplication::HandleDisconnect(ClientPacket* const argPacket) {
);
//save and unload this account's characters
//pump the unload message to all remaining clients
characterMgr.UnloadCharacterIf([&](std::map<int, CharacterData>::iterator it) -> bool {
if (argPacket->accountIndex == it->second.GetOwner()) {
//pump the unload message to all remaining clients
PumpCharacterUnload(it->first);
return true;
}
@@ -167,23 +171,32 @@ void ServerApplication::HandleRegionRequest(RegionPacket* const argPacket) {
void ServerApplication::HandleCharacterNew(CharacterPacket* const argPacket) {
//BUG: #27 Characters can be created with an invalid account index
//TODO: Make sure that a character's owner's account is loaded before continuing
//NOTE: misnomer, try to load the character first
int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex == -1) {
//TODO: rejection packet
std::cerr << "Warning: Character already loaded" << std::endl;
//cannot load or create
if (characterIndex < 0) {
//build the error message
std::string msg;
if (characterIndex == -1) {
msg += "Character already loaded: ";
}
else if (characterIndex == -2) {
msg += "Character already exists: ";
}
msg += argPacket->handle;
//create, fill and send the packet
TextPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_REJECTION;
memset(newPacket.name, 0, PACKET_STRING_SIZE);
strncpy(newPacket.text, msg.c_str(), PACKET_STRING_SIZE);
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
return;
}
if (characterIndex == -2) {
//TODO: rejection packet
std::cerr << "Warning: Character already exists" << std::endl;
return;
}
//TODO: Make sure that a character's owner's account is loaded before continuing
//send this new character to all clients
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_NEW;
@@ -198,9 +211,13 @@ void ServerApplication::HandleCharacterDelete(CharacterPacket* const argPacket)
int characterIndex = characterMgr.LoadCharacter(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
//if this is not your character
if (characterIndex == -2) {
//TODO: rejection packet
std::cerr << "Warning: Character cannot be deleted" << std::endl;
if (characterIndex < 0 && characterMgr.GetCharacter(characterIndex)->GetOwner() != argPacket->accountIndex) {
//send the rejection packet
TextPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_REJECTION;
memset(newPacket.name, 0, PACKET_STRING_SIZE);
strncpy(newPacket.text, "Character cannot be deleted", PACKET_STRING_SIZE);
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
//unload an unneeded character
if (characterIndex != -1) {
@@ -223,8 +240,6 @@ void ServerApplication::HandleCharacterUpdate(CharacterPacket* const argPacket)
//make a new character if this one doesn't exist
if (!character) {
//this isn't normal
std::cerr << "Warning: HandleCharacterUpdate() is passing to HandleCharacterNew()" << std::endl;
HandleCharacterNew(argPacket);
return;
}
@@ -257,7 +272,6 @@ void ServerApplication::HandleSynchronize(ClientPacket* const argPacket) {
newPacket.type = SerialPacketType::CHARACTER_UPDATE;
for (auto& it : *characterMgr.GetContainer()) {
newPacket.characterIndex = it.first;
CopyCharacterToPacket(&newPacket, it.first);
network.SendTo(client.GetAddress(), static_cast<SerialPacket*>(&newPacket));
}
@@ -320,6 +334,7 @@ void ServerApplication::PumpPacket(SerialPacket* const argPacket) {
void ServerApplication::PumpCharacterUnload(int uid) {
//delete the client-side character(s)
//NOTE: This is a strange function
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_DELETE;
newPacket.characterIndex = uid;
+6 -3
View File
@@ -1,9 +1,12 @@
TODO: Rejection messages
TODO: The error handling is terrible
TODO: Move the statistics into their own SQL table, instead of duplicating the structure a dozen times
TODO: Config switch for the debug output
TODO: A better way of handling the disconnection message
TODO: LobbyMenu::HandleJoinRejection()
TODO: Get the rooms working, even if only via hotkeys
TODO: Fix shoddy movement
TODO: Move the statistics into their own SQL table, instead of duplicating the structure a dozen times
TODO: Remove the big "Shut Down" button
TODO: Make a way for the server owner to control the server directly
TODO: Move the map system into it's own namespace?
TODO: The TileSheet class should implement the surface itself
TODO: make the whole thing more fault tolerant