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_character_methods.cpp
T
Kayne Ruse 4630b7e403 PumpCharacterUpdate() works from lua to client, read more
There was a bug in the entity API, where getMotion() was pushing the
origin instead of the motion. This has been corrected. Since this is an
important bug, and because the features for this leg is finished, I'll
merge this to master.
2015-02-27 02:39:27 +11:00

251 lines
8.0 KiB
C++

/* Copyright: (c) Kayne Ruse 2013-2015
*
* 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 <iostream>
#include <sstream>
//-------------------------
//Character Management
//-------------------------
void ServerApplication::hCharacterCreate(CharacterPacket* const argPacket) {
int characterIndex = characterMgr.Create(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex < 0) {
//build the error message
std::ostringstream msg;
msg << "Character already exists: " << argPacket->handle;
//build & send the packet
TextPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_REJECTION;
strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE);
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
return;
}
//push to the rooms
CharacterData* characterData = characterMgr.Get(characterIndex);
roomMgr.PushCharacter(characterData);
//pump this character to all clients
CharacterPacket newPacket;
copyCharacterToPacket(&newPacket, characterIndex);
newPacket.type = SerialPacketType::CHARACTER_CREATE;
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
}
void ServerApplication::hCharacterDelete(CharacterPacket* const argPacket) {
//get the user's data
AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
if (!accountData) {
return;
}
ClientData* clientData = clientMgr.Get(accountData->GetClientIndex());
if (!clientData) {
return;
}
//check for fraud
if (clientData->GetAddress() != argPacket->srcAddress) {
std::cerr << "Falsified character deletion detected targeting: " << argPacket->handle << std::endl;
return;
}
//load the character into memory
int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex < 0) {
//build the error message
std::ostringstream msg;
msg << "Cannot delete this character";
//build & send the packet
TextPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_REJECTION;
strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE);
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
return;
}
//pop from the rooms
CharacterData* characterData = characterMgr.Get(characterIndex);
roomMgr.PopCharacter(characterData);
//pump character delete
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_DELETE;
newPacket.characterIndex = characterIndex;
pumpPacketProximity(static_cast<SerialPacket*>(&newPacket), characterData->GetRoomIndex());
//delete the character
characterMgr.Delete(characterIndex);
}
void ServerApplication::hCharacterLoad(CharacterPacket* const argPacket) {
int characterIndex = characterMgr.Load(argPacket->accountIndex, argPacket->handle, argPacket->avatar);
if (characterIndex < 0) {
//build the error message
std::ostringstream msg;
if (characterIndex == -1) {
msg << "Character already loaded: ";
}
if (characterIndex == -2) {
msg << "Character name is taken: ";
}
msg << argPacket->handle;
//build & send the packet
TextPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_REJECTION;
strncpy(newPacket.text, msg.str().c_str(), PACKET_STRING_SIZE);
network.SendTo(argPacket->srcAddress, static_cast<SerialPacket*>(&newPacket));
return;
}
//push to the rooms
CharacterData* characterData = characterMgr.Get(characterIndex);
roomMgr.PushCharacter(characterData);
//pump this character to all clients
CharacterPacket newPacket;
copyCharacterToPacket(&newPacket, characterIndex);
newPacket.type = SerialPacketType::CHARACTER_CREATE;
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
}
void ServerApplication::hCharacterUnload(CharacterPacket* const argPacket) {
//get the entries
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
if (!characterData) {
return;
}
AccountData* accountData = accountMgr.Get(characterData->GetOwner());
if (!accountData) {
return;
}
ClientData* clientData = clientMgr.Get(accountData->GetClientIndex());
if (!clientData) {
return;
}
//check for fraud
if (clientData->GetAddress() != argPacket->srcAddress) {
std::cerr << "Falsified character unload detected targeting: uid(" << argPacket->characterIndex << ")" << std::endl;
return;
}
//pop from the rooms
roomMgr.PopCharacter(characterData);
//pump character delete
CharacterPacket newPacket;
newPacket.type = SerialPacketType::CHARACTER_DELETE;
newPacket.characterIndex = argPacket->characterIndex;
pumpPacketProximity(static_cast<SerialPacket*>(&newPacket), characterData->GetRoomIndex());
//unload the character
characterMgr.Unload(argPacket->characterIndex);
}
//-------------------------
//character movement
//-------------------------
//TODO: (2) Could replace this verbosity with a "verify" method, taking a client, account and character ptr as arguments
void ServerApplication::hCharacterMovement(CharacterPacket* const argPacket) {
//get the specified objects
AccountData* accountData = accountMgr.Get(argPacket->accountIndex);
if (!accountData) {
throw(std::runtime_error("Failed to move a character, missing account"));
}
CharacterData* characterData = characterMgr.Get(argPacket->characterIndex);
if (!characterData) {
throw(std::runtime_error("Failed to move a character, missing character"));
}
//get this account's client
ClientData* clientData = clientMgr.Get(accountData->GetClientIndex());
//check for fraud
if (clientData->GetAddress() != argPacket->srcAddress) {
std::cerr << "Falsified set character motion targeting uid(" << argPacket->characterIndex << ")" << std::endl;
return;
}
//check if allowed
if (characterData->GetOwner() != argPacket->accountIndex && !accountData->GetModerator() && !accountData->GetAdministrator()) {
//TODO: (2) send to the client?
std::cerr << "Failed to set character motion due to lack of permissions targeting uid(" << argPacket->characterIndex << ")" << std::endl;
return;
}
//check if moving rooms
if (characterData->GetRoomIndex() != argPacket->roomIndex) {
//delete from the old room
CharacterPacket newPacket;
copyCharacterToPacket(&newPacket, argPacket->characterIndex);
newPacket.type = SerialPacketType::CHARACTER_DELETE;
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
//move the character between rooms
roomMgr.PopCharacter(characterData);
characterData->SetRoomIndex(argPacket->roomIndex);
roomMgr.PushCharacter(characterData);
//create in the new room
copyCharacterToPacket(&newPacket, argPacket->characterIndex);
newPacket.type = SerialPacketType::CHARACTER_CREATE;
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
}
//if not moving between rooms
else {
//set the character's origin and motion
characterData->SetOrigin(argPacket->origin);
characterData->SetMotion(argPacket->motion);
//update the clients
CharacterPacket newPacket;
copyCharacterToPacket(&newPacket, argPacket->characterIndex);
newPacket.type = SerialPacketType::CHARACTER_MOVEMENT;
pumpPacketProximity(&newPacket, characterData->GetRoomIndex());
}
}
void ServerApplication::hCharacterAttack(CharacterPacket* const argPacket) {
//TODO: (9) empty
}
void ServerApplication::hCharacterDamage(CharacterPacket* const argPacket) {
//TODO: (9) empty
}