mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-06-15 11:14:22 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
306d959a83 | ||
|
|
e4c2eecbc7 | ||
|
|
1b3cdc6d9c | ||
|
|
d860552776 |
@@ -40,6 +40,7 @@ public:
|
|||||||
// AMFValue template class instantiations
|
// AMFValue template class instantiations
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
class AMFValue : public AMFBaseValue {
|
class AMFValue : public AMFBaseValue {
|
||||||
|
static_assert(!std::is_same_v<ValueType, std::string_view>, "AMFValue cannot be instantiated with std::string_view");
|
||||||
public:
|
public:
|
||||||
AMFValue() = default;
|
AMFValue() = default;
|
||||||
AMFValue(const ValueType value) : m_Data{ value } {}
|
AMFValue(const ValueType value) : m_Data{ value } {}
|
||||||
@@ -52,6 +53,15 @@ public:
|
|||||||
|
|
||||||
void SetValue(const ValueType value) { m_Data = value; }
|
void SetValue(const ValueType value) { m_Data = value; }
|
||||||
|
|
||||||
|
AMFValue<ValueType>& operator=(const AMFValue<ValueType>& other) {
|
||||||
|
return operator=(other.m_Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
AMFValue<ValueType>& operator=(const ValueType& other) {
|
||||||
|
m_Data = other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ValueType m_Data;
|
ValueType m_Data;
|
||||||
};
|
};
|
||||||
@@ -211,13 +221,17 @@ public:
|
|||||||
* @param key The key to associate with the value
|
* @param key The key to associate with the value
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
void Insert(const std::string_view key, std::unique_ptr<AMFBaseValue> value) {
|
template<typename AmfType>
|
||||||
|
AmfType& Insert(const std::string_view key, std::unique_ptr<AmfType> value) {
|
||||||
const auto element = m_Associative.find(key);
|
const auto element = m_Associative.find(key);
|
||||||
|
auto& toReturn = *value;
|
||||||
if (element != m_Associative.cend() && element->second) {
|
if (element != m_Associative.cend() && element->second) {
|
||||||
element->second = std::move(value);
|
element->second = std::move(value);
|
||||||
} else {
|
} else {
|
||||||
m_Associative.emplace(key, std::move(value));
|
m_Associative.emplace(key, std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -229,11 +243,15 @@ public:
|
|||||||
* @param key The key to associate with the value
|
* @param key The key to associate with the value
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
*/
|
*/
|
||||||
void Insert(const size_t index, std::unique_ptr<AMFBaseValue> value) {
|
template<typename AmfType>
|
||||||
|
AmfType& Insert(const size_t index, std::unique_ptr<AmfType> value) {
|
||||||
|
auto& toReturn = *value;
|
||||||
if (index >= m_Dense.size()) {
|
if (index >= m_Dense.size()) {
|
||||||
m_Dense.resize(index + 1);
|
m_Dense.resize(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Dense.at(index) = std::move(value);
|
m_Dense.at(index) = std::move(value);
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,6 +367,13 @@ public:
|
|||||||
m_Dense.clear();
|
m_Dense.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename AmfType = AMFArrayValue>
|
||||||
|
AmfType& PushDebug(const std::string_view name) {
|
||||||
|
auto* value = PushArray();
|
||||||
|
value->Insert("name", name.data());
|
||||||
|
return value->Insert<AmfType>("value", std::make_unique<AmfType>());
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The associative portion. These values are key'd with strings to an AMFValue.
|
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include "CDPlayerFlagsTable.h"
|
||||||
|
|
||||||
|
#include "CDClientDatabase.h"
|
||||||
|
|
||||||
|
namespace CDPlayerFlagsTable {
|
||||||
|
Table entries;
|
||||||
|
|
||||||
|
void ReadEntry(CppSQLite3Query& table) {
|
||||||
|
Entry entry;
|
||||||
|
entry.sessionOnly = table.getIntField("SessionOnly") == 1;
|
||||||
|
entry.onlySetByServer = table.getIntField("OnlySetByServer") == 1;
|
||||||
|
entry.sessionZoneOnly = table.getIntField("SessionZoneOnly") == 1;
|
||||||
|
entries[table.getIntField("id")] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadValuesFromDatabase() {
|
||||||
|
auto table = CDClientDatabase::ExecuteQuery("SELECT * FROM PlayerFlags;");
|
||||||
|
|
||||||
|
if (!table.eof()) {
|
||||||
|
do {
|
||||||
|
ReadEntry(table);
|
||||||
|
} while (!table.nextRow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::optional<Entry> GetEntry(const FlagId flagId) {
|
||||||
|
if (!entries.contains(flagId)) {
|
||||||
|
auto table = CDClientDatabase::CreatePreppedStmt("SELECT * FROM PlayerFlags WHERE id = ?;");
|
||||||
|
table.bind(1, static_cast<int>(flagId));
|
||||||
|
auto result = table.execQuery();
|
||||||
|
if (!result.eof()) {
|
||||||
|
ReadEntry(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries[flagId];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef CDPLAYERFLAGSTABLE_H
|
||||||
|
#define CDPLAYERFLAGSTABLE_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace CDPlayerFlagsTable {
|
||||||
|
struct Entry {
|
||||||
|
bool sessionOnly{};
|
||||||
|
bool onlySetByServer{};
|
||||||
|
bool sessionZoneOnly{};
|
||||||
|
};
|
||||||
|
|
||||||
|
using FlagId = uint32_t;
|
||||||
|
using Table = std::map<FlagId, std::optional<Entry>>;
|
||||||
|
|
||||||
|
void LoadValuesFromDatabase();
|
||||||
|
const std::optional<Entry> GetEntry(const FlagId flagId);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!CDPLAYERFLAGSTABLE_H
|
||||||
@@ -25,6 +25,7 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
|||||||
"CDObjectsTable.cpp"
|
"CDObjectsTable.cpp"
|
||||||
"CDPetComponentTable.cpp"
|
"CDPetComponentTable.cpp"
|
||||||
"CDPackageComponentTable.cpp"
|
"CDPackageComponentTable.cpp"
|
||||||
|
"CDPlayerFlagsTable.cpp"
|
||||||
"CDPhysicsComponentTable.cpp"
|
"CDPhysicsComponentTable.cpp"
|
||||||
"CDPropertyEntranceComponentTable.cpp"
|
"CDPropertyEntranceComponentTable.cpp"
|
||||||
"CDPropertyTemplateTable.cpp"
|
"CDPropertyTemplateTable.cpp"
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
|
#include "CDPlayerFlagsTable.h"
|
||||||
|
|
||||||
Character::Character(uint32_t id, User* parentUser) {
|
Character::Character(uint32_t id, User* parentUser) {
|
||||||
//First load the name, etc:
|
//First load the name, etc:
|
||||||
@@ -231,6 +232,12 @@ void Character::SetBuildMode(bool buildMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Character::SaveXMLToDatabase() {
|
void Character::SaveXMLToDatabase() {
|
||||||
|
// Check that we can actually _save_ before saving
|
||||||
|
if (!m_OurEntity) {
|
||||||
|
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//For metrics, we'll record the time it took to save:
|
//For metrics, we'll record the time it took to save:
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
@@ -277,39 +284,19 @@ void Character::SaveXMLToDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
|
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
|
||||||
for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) {
|
for (const auto& [index, flagBucket] : m_PlayerFlags) {
|
||||||
auto* f = m_Doc.NewElement("f");
|
auto* f = flags->InsertNewChildElement("f");
|
||||||
f->SetAttribute("id", flag.first);
|
f->SetAttribute("id", index);
|
||||||
|
f->SetAttribute("v", flagBucket);
|
||||||
//Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute.
|
|
||||||
//Only signed 64-bits ints would work.
|
|
||||||
std::string v = std::to_string(flag.second);
|
|
||||||
f->SetAttribute("v", v.c_str());
|
|
||||||
|
|
||||||
flags->LinkEndChild(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevents the news feed from showing up on world transfers
|
for (const auto& sessionFlag : m_SessionFlags) {
|
||||||
if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) {
|
auto* s = flags->InsertNewChildElement("s");
|
||||||
auto* s = m_Doc.NewElement("s");
|
s->SetAttribute("si", sessionFlag);
|
||||||
s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE);
|
|
||||||
flags->LinkEndChild(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR)) {
|
|
||||||
auto* s = m_Doc.NewElement("s");
|
|
||||||
s->SetAttribute("si", ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR);
|
|
||||||
flags->LinkEndChild(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveXmlRespawnCheckpoints();
|
SaveXmlRespawnCheckpoints();
|
||||||
|
|
||||||
//Call upon the entity to update our xmlDoc:
|
|
||||||
if (!m_OurEntity) {
|
|
||||||
LOG("%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_OurEntity->UpdateXMLDoc(m_Doc);
|
m_OurEntity->UpdateXMLDoc(m_Doc);
|
||||||
|
|
||||||
WriteToDatabase();
|
WriteToDatabase();
|
||||||
@@ -329,8 +316,8 @@ void Character::SetIsNewLogin() {
|
|||||||
while (currentChild) {
|
while (currentChild) {
|
||||||
auto* nextChild = currentChild->NextSiblingElement();
|
auto* nextChild = currentChild->NextSiblingElement();
|
||||||
if (currentChild->Attribute("si")) {
|
if (currentChild->Attribute("si")) {
|
||||||
|
LOG("Removed session flag (%s) from character %i:%s, saving character to database", currentChild->Attribute("si"), GetID(), GetName().c_str());
|
||||||
flags->DeleteChild(currentChild);
|
flags->DeleteChild(currentChild);
|
||||||
LOG("Removed isLoggedIn flag from character %i:%s, saving character to database", GetID(), GetName().c_str());
|
|
||||||
WriteToDatabase();
|
WriteToDatabase();
|
||||||
}
|
}
|
||||||
currentChild = nextChild;
|
currentChild = nextChild;
|
||||||
@@ -363,7 +350,9 @@ void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flagId == EQUPPED_TRIAL_FACTION_GEAR || flagId == IS_NEWS_SCREEN_VISIBLE) {
|
const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId);
|
||||||
|
|
||||||
|
if (flagEntry && flagEntry->sessionOnly) {
|
||||||
if (value) m_SessionFlags.insert(flagId);
|
if (value) m_SessionFlags.insert(flagId);
|
||||||
else m_SessionFlags.erase(flagId);
|
else m_SessionFlags.erase(flagId);
|
||||||
} else {
|
} else {
|
||||||
@@ -402,8 +391,8 @@ bool Character::GetPlayerFlag(const uint32_t flagId) const {
|
|||||||
|
|
||||||
bool toReturn = false; //by def, return false.
|
bool toReturn = false; //by def, return false.
|
||||||
|
|
||||||
// TODO make actual session flag checker using flags table in database.
|
const auto flagEntry = CDPlayerFlagsTable::GetEntry(flagId);
|
||||||
if (flagId == EQUPPED_TRIAL_FACTION_GEAR || flagId == IS_NEWS_SCREEN_VISIBLE) {
|
if (flagEntry && flagEntry->sessionOnly) {
|
||||||
toReturn = m_SessionFlags.contains(flagId);
|
toReturn = m_SessionFlags.contains(flagId);
|
||||||
} else {
|
} else {
|
||||||
// Calculate the index first
|
// Calculate the index first
|
||||||
|
|||||||
@@ -2216,3 +2216,17 @@ int32_t Entity::GetCollisionGroup() const {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Entity::HandleMsg(GameMessages::GameMsg& msg) const {
|
||||||
|
bool handled = false;
|
||||||
|
const auto [beg, end] = m_MsgHandlers.equal_range(msg.msgId);
|
||||||
|
for (auto it = beg; it != end; ++it) {
|
||||||
|
if (it->second) handled |= it->second(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
|
||||||
|
m_MsgHandlers.emplace(msgId, handler);
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,12 +14,17 @@
|
|||||||
#include "Observable.h"
|
#include "Observable.h"
|
||||||
|
|
||||||
namespace GameMessages {
|
namespace GameMessages {
|
||||||
|
struct GameMsg;
|
||||||
struct ActivityNotify;
|
struct ActivityNotify;
|
||||||
struct ShootingGalleryFire;
|
struct ShootingGalleryFire;
|
||||||
struct ChildLoaded;
|
struct ChildLoaded;
|
||||||
struct PlayerResurrectionFinished;
|
struct PlayerResurrectionFinished;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace MessageType {
|
||||||
|
enum class Game : uint16_t;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Loot {
|
namespace Loot {
|
||||||
class Info;
|
class Info;
|
||||||
};
|
};
|
||||||
@@ -316,6 +321,10 @@ public:
|
|||||||
// Scale will only be communicated to the client when the construction packet is sent
|
// Scale will only be communicated to the client when the construction packet is sent
|
||||||
void SetScale(const float scale) { m_Scale = scale; };
|
void SetScale(const float scale) { m_Scale = scale; };
|
||||||
|
|
||||||
|
void RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler);
|
||||||
|
|
||||||
|
bool HandleMsg(GameMessages::GameMsg& msg) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The observable for player entity position updates.
|
* @brief The observable for player entity position updates.
|
||||||
*/
|
*/
|
||||||
@@ -377,6 +386,8 @@ protected:
|
|||||||
|
|
||||||
// objectID of receiver and map of notification name to script
|
// objectID of receiver and map of notification name to script
|
||||||
std::map<LWOOBJID, std::map<std::string, CppScripts::Script*>> m_Subscriptions;
|
std::map<LWOOBJID, std::map<std::string, CppScripts::Script*>> m_Subscriptions;
|
||||||
|
|
||||||
|
std::multimap<MessageType::Game, std::function<bool(GameMessages::GameMsg&)>> m_MsgHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "Mail.h"
|
#include "Mail.h"
|
||||||
#include "ZoneInstanceManager.h"
|
#include "ZoneInstanceManager.h"
|
||||||
#include "WorldPackets.h"
|
#include "WorldPackets.h"
|
||||||
|
#include "MessageType/Game.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
|
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
|
||||||
@@ -47,6 +48,45 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character, con
|
|||||||
m_CountryCode = 0;
|
m_CountryCode = 0;
|
||||||
m_LastUpdateTimestamp = std::time(nullptr);
|
m_LastUpdateTimestamp = std::time(nullptr);
|
||||||
m_SystemAddress = systemAddress;
|
m_SystemAddress = systemAddress;
|
||||||
|
|
||||||
|
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &CharacterComponent::OnRequestServerObjectInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
||||||
|
auto& request = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
|
||||||
|
AMFArrayValue response;
|
||||||
|
|
||||||
|
response.Insert("visible", true);
|
||||||
|
response.Insert("objectID", std::to_string(request.targetForReport));
|
||||||
|
response.Insert("serverInfo", true);
|
||||||
|
|
||||||
|
auto& data = *response.InsertArray("data");
|
||||||
|
auto& cmptType = data.PushDebug("Character");
|
||||||
|
|
||||||
|
cmptType.PushDebug<AMFIntValue>("Component ID") = GeneralUtils::ToUnderlying(ComponentType);
|
||||||
|
cmptType.PushDebug<AMFIntValue>("Character's account ID") = m_Character->GetParentUser()->GetAccountID();
|
||||||
|
cmptType.PushDebug<AMFBoolValue>("Last log out time") = m_Character->GetLastLogin();
|
||||||
|
cmptType.PushDebug<AMFDoubleValue>("Seconds played this session") = 0;
|
||||||
|
cmptType.PushDebug<AMFBoolValue>("Editor enabled") = false;
|
||||||
|
cmptType.PushDebug<AMFDoubleValue>("Total number of seconds played") = m_TotalTimePlayed;
|
||||||
|
cmptType.PushDebug<AMFStringValue>("Total currency") = std::to_string(m_Character->GetCoins());
|
||||||
|
cmptType.PushDebug<AMFStringValue>("Currency able to be picked up") = std::to_string(m_DroppedCoins);
|
||||||
|
cmptType.PushDebug<AMFStringValue>("Tooltip flags value") = "0";
|
||||||
|
// visited locations
|
||||||
|
cmptType.PushDebug<AMFBoolValue>("is a GM") = m_GMLevel > eGameMasterLevel::CIVILIAN;
|
||||||
|
cmptType.PushDebug<AMFBoolValue>("Has PVP flag turned on") = m_PvpEnabled;
|
||||||
|
cmptType.PushDebug<AMFIntValue>("GM Level") = GeneralUtils::ToUnderlying(m_GMLevel);
|
||||||
|
cmptType.PushDebug<AMFIntValue>("Editor level") = GeneralUtils::ToUnderlying(m_EditorLevel);
|
||||||
|
cmptType.PushDebug<AMFStringValue>("Guild ID") = "0";
|
||||||
|
cmptType.PushDebug<AMFStringValue>("Guild Name") = "";
|
||||||
|
cmptType.PushDebug<AMFDoubleValue>("Reputation") = m_Reputation;
|
||||||
|
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
||||||
|
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
||||||
|
|
||||||
|
GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, m_Parent->GetSystemAddress());
|
||||||
|
|
||||||
|
LOG("Handled!");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
||||||
@@ -81,6 +121,8 @@ CharacterComponent::~CharacterComponent() {
|
|||||||
void CharacterComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
void CharacterComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||||
|
|
||||||
if (bIsInitialUpdate) {
|
if (bIsInitialUpdate) {
|
||||||
|
if (!m_Character || !m_Character->GetParentUser()) return;
|
||||||
|
|
||||||
outBitStream.Write(m_ClaimCodes[0] != 0);
|
outBitStream.Write(m_ClaimCodes[0] != 0);
|
||||||
if (m_ClaimCodes[0] != 0) outBitStream.Write(m_ClaimCodes[0]);
|
if (m_ClaimCodes[0] != 0) outBitStream.Write(m_ClaimCodes[0]);
|
||||||
outBitStream.Write(m_ClaimCodes[1] != 0);
|
outBitStream.Write(m_ClaimCodes[1] != 0);
|
||||||
@@ -100,7 +142,7 @@ void CharacterComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInit
|
|||||||
outBitStream.Write(m_Character->GetEyebrows());
|
outBitStream.Write(m_Character->GetEyebrows());
|
||||||
outBitStream.Write(m_Character->GetEyes());
|
outBitStream.Write(m_Character->GetEyes());
|
||||||
outBitStream.Write(m_Character->GetMouth());
|
outBitStream.Write(m_Character->GetMouth());
|
||||||
outBitStream.Write<uint64_t>(0); //AccountID, trying out if 0 works.
|
outBitStream.Write<uint64_t>(m_Character->GetParentUser()->GetAccountID());
|
||||||
outBitStream.Write(m_Character->GetLastLogin()); //Last login
|
outBitStream.Write(m_Character->GetLastLogin()); //Last login
|
||||||
outBitStream.Write<uint64_t>(0); //"prop mod last display time"
|
outBitStream.Write<uint64_t>(0); //"prop mod last display time"
|
||||||
outBitStream.Write<uint64_t>(m_Uscore); //u-score
|
outBitStream.Write<uint64_t>(m_Uscore); //u-score
|
||||||
|
|||||||
@@ -323,6 +323,8 @@ public:
|
|||||||
Character* m_Character;
|
Character* m_Character;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool OnRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map of active venture vision effects
|
* The map of active venture vision effects
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ namespace RakNet {
|
|||||||
class BitStream;
|
class BitStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace GameMessages {
|
||||||
|
struct GameMsg;
|
||||||
|
}
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,6 +56,10 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
|
||||||
|
m_Parent->RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity that owns this component
|
* The entity that owns this component
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,8 +37,19 @@
|
|||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "GhostComponent.h"
|
#include "GhostComponent.h"
|
||||||
|
#include "eGameMasterLevel.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using enum MessageType::Game;
|
||||||
|
using namespace GameMessages;
|
||||||
|
using MessageCreator = std::function<std::unique_ptr<GameMessages::GameMsg>()>;
|
||||||
|
std::map<MessageType::Game, MessageCreator> g_MessageHandlers = {
|
||||||
|
{ REQUEST_SERVER_OBJECT_INFO, []() { return std::make_unique<RequestServerObjectInfo>(); } },
|
||||||
|
{ SHOOTING_GALLERY_FIRE, []() { return std::make_unique<ShootingGalleryFire>(); } },
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID) {
|
void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const SystemAddress& sysAddr, LWOOBJID objectID, MessageType::Game messageID) {
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
@@ -55,6 +66,24 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
|||||||
|
|
||||||
if (messageID != MessageType::Game::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
if (messageID != MessageType::Game::READY_FOR_UPDATES) LOG_DEBUG("Received GM with ID and name: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
||||||
|
|
||||||
|
auto handler = g_MessageHandlers.find(messageID);
|
||||||
|
if (handler != g_MessageHandlers.end()) {
|
||||||
|
auto msg = handler->second();
|
||||||
|
|
||||||
|
// Verify that the system address user is able to use this message.
|
||||||
|
if (msg->requiredGmLevel > eGameMasterLevel::CIVILIAN) {
|
||||||
|
auto* usingEntity = Game::entityManager->GetEntity(usr->GetLoggedInChar());
|
||||||
|
if (!usingEntity || usingEntity->GetGMLevel() < msg->requiredGmLevel) {
|
||||||
|
LOG("User %s (%llu) does not have the required GM level to execute this command.", usingEntity->GetCharacter()->GetName().c_str(), usingEntity->GetObjectID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg->Deserialize(inStream);
|
||||||
|
msg->Handle(*entity, sysAddr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (messageID) {
|
switch (messageID) {
|
||||||
|
|
||||||
case MessageType::Game::UN_USE_BBB_MODEL: {
|
case MessageType::Game::UN_USE_BBB_MODEL: {
|
||||||
@@ -704,12 +733,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
|||||||
case MessageType::Game::UPDATE_INVENTORY_GROUP_CONTENTS:
|
case MessageType::Game::UPDATE_INVENTORY_GROUP_CONTENTS:
|
||||||
GameMessages::HandleUpdateInventoryGroupContents(inStream, entity, sysAddr);
|
GameMessages::HandleUpdateInventoryGroupContents(inStream, entity, sysAddr);
|
||||||
break;
|
break;
|
||||||
case MessageType::Game::SHOOTING_GALLERY_FIRE: {
|
|
||||||
GameMessages::ShootingGalleryFire fire{};
|
|
||||||
fire.Deserialize(inStream);
|
|
||||||
fire.Handle(*entity, sysAddr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_DEBUG("Received Unknown GM with ID: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
LOG_DEBUG("Received Unknown GM with ID: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
||||||
|
|||||||
@@ -6431,4 +6431,16 @@ namespace GameMessages {
|
|||||||
void ShootingGalleryFire::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
void ShootingGalleryFire::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||||
entity.OnShootingGalleryFire(*this);
|
entity.OnShootingGalleryFire(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RequestServerObjectInfo::Deserialize(RakNet::BitStream& bitStream) {
|
||||||
|
if (!bitStream.Read(bVerbose)) return false;
|
||||||
|
if (!bitStream.Read(clientId)) return false;
|
||||||
|
if (!bitStream.Read(targetForReport)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestServerObjectInfo::Handle(Entity& entity, const SystemAddress& sysAddr) {
|
||||||
|
auto* handlingEntity = Game::entityManager->GetEntity(targetForReport);
|
||||||
|
if (handlingEntity) handlingEntity->HandleMsg(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "eLootSourceType.h"
|
#include "eLootSourceType.h"
|
||||||
#include "Brick.h"
|
#include "Brick.h"
|
||||||
#include "MessageType/Game.h"
|
#include "MessageType/Game.h"
|
||||||
|
#include "eGameMasterLevel.h"
|
||||||
|
|
||||||
class AMFBaseValue;
|
class AMFBaseValue;
|
||||||
class Entity;
|
class Entity;
|
||||||
@@ -50,7 +51,8 @@ enum class eCameraTargetCyclingMode : int32_t {
|
|||||||
|
|
||||||
namespace GameMessages {
|
namespace GameMessages {
|
||||||
struct GameMsg {
|
struct GameMsg {
|
||||||
GameMsg(MessageType::Game gmId) : msgId{ gmId } {}
|
GameMsg(MessageType::Game gmId, eGameMasterLevel lvl) : msgId{ gmId }, requiredGmLevel{ lvl } {}
|
||||||
|
GameMsg(MessageType::Game gmId) : GameMsg(gmId, eGameMasterLevel::CIVILIAN) {}
|
||||||
virtual ~GameMsg() = default;
|
virtual ~GameMsg() = default;
|
||||||
void Send(const SystemAddress& sysAddr) const;
|
void Send(const SystemAddress& sysAddr) const;
|
||||||
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
||||||
@@ -58,6 +60,7 @@ namespace GameMessages {
|
|||||||
virtual void Handle(Entity& entity, const SystemAddress& sysAddr) {};
|
virtual void Handle(Entity& entity, const SystemAddress& sysAddr) {};
|
||||||
MessageType::Game msgId;
|
MessageType::Game msgId;
|
||||||
LWOOBJID target{ LWOOBJID_EMPTY };
|
LWOOBJID target{ LWOOBJID_EMPTY };
|
||||||
|
eGameMasterLevel requiredGmLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PropertyDataMessage;
|
class PropertyDataMessage;
|
||||||
@@ -769,6 +772,16 @@ namespace GameMessages {
|
|||||||
struct PlayerResurrectionFinished : public GameMsg {
|
struct PlayerResurrectionFinished : public GameMsg {
|
||||||
PlayerResurrectionFinished() : GameMsg(MessageType::Game::PLAYER_RESURRECTION_FINISHED) {}
|
PlayerResurrectionFinished() : GameMsg(MessageType::Game::PLAYER_RESURRECTION_FINISHED) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RequestServerObjectInfo : public GameMsg {
|
||||||
|
bool bVerbose{};
|
||||||
|
LWOOBJID clientId{};
|
||||||
|
LWOOBJID targetForReport{};
|
||||||
|
|
||||||
|
RequestServerObjectInfo() : GameMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, eGameMasterLevel::DEVELOPER) {}
|
||||||
|
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||||
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GAMEMESSAGES_H
|
#endif // GAMEMESSAGES_H
|
||||||
|
|||||||
@@ -246,7 +246,8 @@ int main(int argc, char** argv) {
|
|||||||
// Regenerate hash based on new password
|
// Regenerate hash based on new password
|
||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
assert(GenerateBCryptPassword(password, 12, salt, hash) == 0);
|
int res = GenerateBCryptPassword(password, 12, salt, hash);
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
Database::Get()->UpdateAccountPassword(accountId->id, std::string(hash, BCRYPT_HASHSIZE));
|
Database::Get()->UpdateAccountPassword(accountId->id, std::string(hash, BCRYPT_HASHSIZE));
|
||||||
|
|
||||||
@@ -284,7 +285,8 @@ int main(int argc, char** argv) {
|
|||||||
//Generate new hash for bcrypt
|
//Generate new hash for bcrypt
|
||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
assert(GenerateBCryptPassword(password, 12, salt, hash) == 0);
|
int res = GenerateBCryptPassword(password, 12, salt, hash);
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
//Create account
|
//Create account
|
||||||
try {
|
try {
|
||||||
@@ -323,7 +325,8 @@ int main(int argc, char** argv) {
|
|||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
const auto& cfgPassword = Game::config->GetValue("master_password");
|
const auto& cfgPassword = Game::config->GetValue("master_password");
|
||||||
GenerateBCryptPassword(!cfgPassword.empty() ? cfgPassword : "3.25DARKFLAME1", 13, salt, hash);
|
int res = GenerateBCryptPassword(!cfgPassword.empty() ? cfgPassword : "3.25DARKFLAME1", 13, salt, hash);
|
||||||
|
assert(res == 0);
|
||||||
|
|
||||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal, hash);
|
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal, hash);
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ TEST(dCommonTests, AMF3InsertionAssociativeTest) {
|
|||||||
array.Insert<int32_t>("Integer", 42U);
|
array.Insert<int32_t>("Integer", 42U);
|
||||||
array.Insert("Double", 42.0);
|
array.Insert("Double", 42.0);
|
||||||
array.InsertArray("Array");
|
array.InsertArray("Array");
|
||||||
array.Insert<std::vector<uint32_t>>("Undefined", {});
|
array.Insert<std::vector<uint32_t>>("Undefined", std::vector<uint32_t>{});
|
||||||
array.Insert("Null", nullptr);
|
array.Insert("Null", nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(array.Get<const char*>("CString")->GetValueType(), eAmf::String);
|
ASSERT_EQ(array.Get<const char*>("CString")->GetValueType(), eAmf::String);
|
||||||
|
|||||||
6
thirdparty/SQLite/CppSQLite3.cpp
vendored
6
thirdparty/SQLite/CppSQLite3.cpp
vendored
@@ -573,16 +573,18 @@ bool CppSQLite3Query::eof()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CppSQLite3Query::nextRow()
|
bool CppSQLite3Query::nextRow()
|
||||||
{
|
{
|
||||||
checkVM();
|
checkVM();
|
||||||
|
|
||||||
int nRet = sqlite3_step(mpVM);
|
int nRet = sqlite3_step(mpVM);
|
||||||
|
|
||||||
|
bool bRet = true;
|
||||||
if (nRet == SQLITE_DONE)
|
if (nRet == SQLITE_DONE)
|
||||||
{
|
{
|
||||||
// no rows
|
// no rows
|
||||||
mbEof = true;
|
mbEof = true;
|
||||||
|
bRet = false;
|
||||||
}
|
}
|
||||||
else if (nRet == SQLITE_ROW)
|
else if (nRet == SQLITE_ROW)
|
||||||
{
|
{
|
||||||
@@ -590,6 +592,7 @@ void CppSQLite3Query::nextRow()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
bRet = false;
|
||||||
nRet = sqlite3_finalize(mpVM);
|
nRet = sqlite3_finalize(mpVM);
|
||||||
mpVM = 0;
|
mpVM = 0;
|
||||||
const char* szError = sqlite3_errmsg(mpDB);
|
const char* szError = sqlite3_errmsg(mpDB);
|
||||||
@@ -597,6 +600,7 @@ void CppSQLite3Query::nextRow()
|
|||||||
(char*)szError,
|
(char*)szError,
|
||||||
DONT_DELETE_MSG);
|
DONT_DELETE_MSG);
|
||||||
}
|
}
|
||||||
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
10
thirdparty/SQLite/CppSQLite3.h
vendored
10
thirdparty/SQLite/CppSQLite3.h
vendored
@@ -165,7 +165,8 @@ public:
|
|||||||
|
|
||||||
bool eof();
|
bool eof();
|
||||||
|
|
||||||
void nextRow();
|
// Returns true if there is another row to read, false otherwise.
|
||||||
|
bool nextRow();
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
@@ -207,6 +208,9 @@ public:
|
|||||||
int getIntField(int nField, int nNullValue=0);
|
int getIntField(int nField, int nNullValue=0);
|
||||||
int getIntField(const char* szField, int nNullValue=0);
|
int getIntField(const char* szField, int nNullValue=0);
|
||||||
|
|
||||||
|
sqlite_int64 getInt64Field(int nField, sqlite_int64 nNullValue=0);
|
||||||
|
sqlite_int64 getInt64Field(const char* szField, sqlite_int64 nNullValue=0);
|
||||||
|
|
||||||
double getFloatField(int nField, double fNullValue=0.0);
|
double getFloatField(int nField, double fNullValue=0.0);
|
||||||
double getFloatField(const char* szField, double fNullValue=0.0);
|
double getFloatField(const char* szField, double fNullValue=0.0);
|
||||||
|
|
||||||
@@ -218,6 +222,9 @@ public:
|
|||||||
|
|
||||||
void setRow(int nRow);
|
void setRow(int nRow);
|
||||||
|
|
||||||
|
// Returns true if there is another row to read, false otherwise.
|
||||||
|
bool nextRow();
|
||||||
|
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -226,6 +233,7 @@ private:
|
|||||||
|
|
||||||
int mnCols;
|
int mnCols;
|
||||||
int mnRows;
|
int mnRows;
|
||||||
|
bool mbEof;
|
||||||
int mnCurrentRow;
|
int mnCurrentRow;
|
||||||
char** mpaszResults;
|
char** mpaszResults;
|
||||||
};
|
};
|
||||||
|
|||||||
2
thirdparty/raknet/CMakeLists.txt
vendored
2
thirdparty/raknet/CMakeLists.txt
vendored
@@ -59,7 +59,7 @@ Source/DS_List.h Source/NetworkIDObject.h S
|
|||||||
Source/DS_Map.h Source/PacketConsoleLogger.h Source/SingleProducerConsumer.h
|
Source/DS_Map.h Source/PacketConsoleLogger.h Source/SingleProducerConsumer.h
|
||||||
Source/DS_MemoryPool.h Source/PacketFileLogger.h Source/SocketLayer.h
|
Source/DS_MemoryPool.h Source/PacketFileLogger.h Source/SocketLayer.h
|
||||||
Source/DS_OrderedChannelHeap.h Source/PacketLogger.h Source/StringCompressor.h
|
Source/DS_OrderedChannelHeap.h Source/PacketLogger.h Source/StringCompressor.h
|
||||||
Source/DS_OrderedList.h Source/PacketPool.h Source/StringTable.h
|
Source/DS_OrderedList.h Source/StringTable.h
|
||||||
Source/DS_Queue.h Source/PacketPriority.h Source/SystemAddressList.h
|
Source/DS_Queue.h Source/PacketPriority.h Source/SystemAddressList.h
|
||||||
Source/DS_QueueLinkedList.h Source/PluginInterface.h Source/TableSerializer.h
|
Source/DS_QueueLinkedList.h Source/PluginInterface.h Source/TableSerializer.h
|
||||||
Source/DS_RangeList.h Source/RakAssert.h Source/TCPInterface.h
|
Source/DS_RangeList.h Source/RakAssert.h Source/TCPInterface.h
|
||||||
|
|||||||
1
thirdparty/raknet/Source/PacketPool.h
vendored
1
thirdparty/raknet/Source/PacketPool.h
vendored
@@ -1 +0,0 @@
|
|||||||
// REMOVEME
|
|
||||||
Reference in New Issue
Block a user