mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-11-24 10:18:16 +00:00
Another consistency pass
- change NotifyObject to use u16 string - move stuff to header that is inline - use u16strings instead of converting to u16 string - move entity to dEntity
This commit is contained in:
@@ -1,2 +1,5 @@
|
||||
set(DGAME_DENTITY_SOURCES "EntityCallbackTimer.cpp"
|
||||
"EntityTimer.cpp" PARENT_SCOPE)
|
||||
set(DGAME_DENTITY_SOURCES
|
||||
"Entity.cpp"
|
||||
"EntityCallbackTimer.cpp"
|
||||
"EntityTimer.cpp"
|
||||
PARENT_SCOPE)
|
||||
|
||||
1390
dGame/dEntity/Entity.cpp
Normal file
1390
dGame/dEntity/Entity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
368
dGame/dEntity/Entity.h
Normal file
368
dGame/dEntity/Entity.h
Normal file
@@ -0,0 +1,368 @@
|
||||
#ifndef __ENTITY__H__
|
||||
#define __ENTITY__H__
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
#include "NiPoint3.h"
|
||||
#include "NiQuaternion.h"
|
||||
#include "eKillType.h"
|
||||
|
||||
namespace Loot {
|
||||
class Info;
|
||||
};
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLDocument;
|
||||
};
|
||||
|
||||
class Player;
|
||||
class EntityInfo;
|
||||
class User;
|
||||
class Spawner;
|
||||
class ScriptComponent;
|
||||
class dpEntity;
|
||||
class EntityTimer;
|
||||
class Component;
|
||||
class Item;
|
||||
class Character;
|
||||
class EntityCallbackTimer;
|
||||
class LDFBaseData;
|
||||
enum class eTriggerEventType;
|
||||
enum class eGameMasterLevel : uint8_t;
|
||||
enum class eReplicaComponentType : uint32_t;
|
||||
enum class eReplicaPacketType : uint8_t;
|
||||
enum class eCinematicEvent : uint32_t;
|
||||
|
||||
namespace CppScripts {
|
||||
class Script;
|
||||
};
|
||||
|
||||
/**
|
||||
* An entity in the world.
|
||||
* Entities are composed of components which define their behavior.
|
||||
*/
|
||||
|
||||
using ComponentPtr = std::unique_ptr<Component>;
|
||||
using ComponentWhitelist = std::vector<eReplicaComponentType>;
|
||||
using TemplateComponents = std::vector<std::pair<eReplicaComponentType, uint32_t>>;
|
||||
|
||||
class Entity {
|
||||
public:
|
||||
explicit Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity = nullptr);
|
||||
virtual ~Entity();
|
||||
|
||||
void ApplyComponentWhitelist(TemplateComponents& components) const;
|
||||
static const std::vector<ComponentWhitelist>& GetComponentWhitelists() { return m_ComponentWhitelists; }
|
||||
|
||||
// There are some very very edge cases we need to take care of with what components
|
||||
// are kept and removed. Here is where we take care of those cases.
|
||||
void ApplyComponentBlacklist(TemplateComponents& components) const;
|
||||
|
||||
// For adding and removing components based on LDF keys
|
||||
void ApplyComponentConfig(TemplateComponents& components) const;
|
||||
|
||||
// Paths have several components they could add. This function will add them.
|
||||
void AddPathComponent(TemplateComponents& components) const;
|
||||
|
||||
void IsGhosted();
|
||||
virtual void Initialize();
|
||||
|
||||
bool operator==(const Entity& other) const;
|
||||
bool operator!=(const Entity& other) const;
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
Character* GetCharacter() const { return m_Character; }
|
||||
void SetCharacter(Character* value) { m_Character = value; }
|
||||
|
||||
const LWOOBJID GetObjectID() const { return m_ObjectID; }
|
||||
|
||||
const LOT GetLOT() const { return m_TemplateID; }
|
||||
|
||||
eGameMasterLevel GetGMLevel() const { return m_GMLevel; }
|
||||
void SetGMLevel(const eGameMasterLevel value);
|
||||
|
||||
Entity* GetParentEntity() const { return m_ParentEntity; }
|
||||
|
||||
const std::vector<std::string>& GetGroups() { return m_Groups; };
|
||||
void SetGroups(const std::vector<std::string>& value) { m_Groups = value; }
|
||||
|
||||
Spawner* GetSpawner() const { return m_Spawner; }
|
||||
|
||||
LWOOBJID GetSpawnerID() const { return m_SpawnerID; }
|
||||
|
||||
const std::vector<LDFBaseData*>& GetSettings() const { return m_Settings; }
|
||||
|
||||
const std::vector<LDFBaseData*>& GetNetworkSettings() const { return m_NetworkSettings; }
|
||||
|
||||
bool GetIsDead() const;
|
||||
|
||||
bool GetPlayerReadyForUpdates() const { return m_PlayerIsReadyForUpdates; }
|
||||
void SetPlayerReadyForUpdates() { m_PlayerIsReadyForUpdates = true; }
|
||||
|
||||
const bool GetIsGhostingCandidate() const { return m_IsGhostingCandidate; }
|
||||
|
||||
const int8_t GetObservers() const { return m_Observers; }
|
||||
void SetObservers(const int8_t value);
|
||||
|
||||
const uint16_t GetNetworkId() const { return m_NetworkID; }
|
||||
void SetNetworkId(const uint16_t id) { m_NetworkID = id; }
|
||||
|
||||
Entity* GetOwner() const;
|
||||
void SetOwnerOverride(const LWOOBJID& value) { m_OwnerOverride = value; };
|
||||
|
||||
const NiPoint3& GetDefaultPosition() const { return m_DefaultPosition; };
|
||||
|
||||
const NiQuaternion& GetDefaultRotation() const { return m_DefaultRotation; };
|
||||
|
||||
const float GetDefaultScale() const { return m_Scale; }
|
||||
|
||||
const NiPoint3& GetPosition() const;
|
||||
void SetPosition(const NiPoint3& position);
|
||||
|
||||
const NiQuaternion& GetRotation() const;
|
||||
void SetRotation(const NiQuaternion& rotation);
|
||||
|
||||
virtual User* GetParentUser() const;
|
||||
|
||||
virtual const SystemAddress GetSystemAddress() const { return UNASSIGNED_SYSTEM_ADDRESS; };
|
||||
|
||||
virtual void SetRespawnPos(const NiPoint3& position) {};
|
||||
|
||||
virtual void SetRespawnRot(const NiQuaternion& rotation) {};
|
||||
|
||||
virtual void SetSystemAddress(const SystemAddress& value) {};
|
||||
|
||||
/**
|
||||
* Component management
|
||||
*/
|
||||
bool HasComponent(const eReplicaComponentType componentId) const;
|
||||
|
||||
void Subscribe(const LWOOBJID& scriptObjId, CppScripts::Script* scriptToAdd, const std::string& notificationName);
|
||||
void Unsubscribe(const LWOOBJID& scriptObjId, const std::string& notificationName);
|
||||
|
||||
void SetProximityRadius(const float proxRadius, const std::string& name);
|
||||
void SetProximityRadius(dpEntity* entity, const std::string& name);
|
||||
|
||||
void AddChild(Entity* child);
|
||||
void RemoveChild(Entity* child);
|
||||
void RemoveParent();
|
||||
void AddTimer(const std::string& name, const float time);
|
||||
void AddCallbackTimer(const float time, const std::function<void()>& callback);
|
||||
bool HasTimer(const std::string& name);
|
||||
void CancelCallbackTimers();
|
||||
void CancelAllTimers();
|
||||
void CancelTimer(const std::string& name);
|
||||
|
||||
void AddToGroups(const std::string& group);
|
||||
bool IsPlayer() const;
|
||||
|
||||
void WriteBaseReplicaData(RakNet::BitStream* outBitStream, const eReplicaPacketType packetType);
|
||||
void WriteComponents(RakNet::BitStream* outBitStream, const eReplicaPacketType packetType);
|
||||
void ResetFlags();
|
||||
void UpdateXMLDoc(tinyxml2::XMLDocument* doc);
|
||||
void Update(float deltaTime);
|
||||
|
||||
// Events
|
||||
void OnCollisionProximity(const LWOOBJID otherEntity, const std::string& proxName, const std::string& status);
|
||||
void OnCollisionPhantom(const LWOOBJID otherEntity);
|
||||
void OnCollisionLeavePhantom(const LWOOBJID otherEntity);
|
||||
|
||||
void OnFireEventServerSide(Entity* sender, const std::string args, const int32_t param1 = -1, const int32_t param2 = -1, const int32_t param3 = -1);
|
||||
void OnActivityStateChangeRequest(const LWOOBJID senderID, const int32_t value1, const int32_t value2,
|
||||
const std::u16string& stringValue);
|
||||
void OnCinematicUpdate(Entity* self, Entity* sender, const eCinematicEvent event, const std::u16string& pathName,
|
||||
const float pathTime, const float totalTime, const int32_t waypoint);
|
||||
|
||||
void NotifyObject(Entity* sender, const std::u16string& name, const int32_t param1 = 0, const int32_t param2 = 0);
|
||||
void OnEmoteReceived(const int32_t emote, Entity* target);
|
||||
|
||||
void OnUse(Entity* originator);
|
||||
|
||||
void OnHitOrHealResult(Entity* attacker, const int32_t damage);
|
||||
void OnHit(Entity* attacker);
|
||||
|
||||
void OnZonePropertyEditBegin();
|
||||
void OnZonePropertyEditEnd();
|
||||
void OnZonePropertyModelEquipped();
|
||||
void OnZonePropertyModelPlaced(Entity* player);
|
||||
void OnZonePropertyModelPickedUp(Entity* player);
|
||||
void OnZonePropertyModelRemoved(Entity* player);
|
||||
void OnZonePropertyModelRemovedWhileEquipped(Entity* player);
|
||||
void OnZonePropertyModelRotated(Entity* player);
|
||||
|
||||
void OnMessageBoxResponse(Entity* sender, const int32_t button, const std::u16string& identifier, const std::u16string& userData);
|
||||
void OnChoiceBoxResponse(Entity* sender, const int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier);
|
||||
void RequestActivityExit(Entity* sender, const LWOOBJID& player, const bool canceled);
|
||||
|
||||
void Smash(const LWOOBJID source = LWOOBJID_EMPTY, const eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"");
|
||||
void Kill(Entity* murderer = nullptr);
|
||||
void AddRebuildCompleteCallback(const std::function<void(Entity* user)>& callback) const;
|
||||
void AddCollisionPhantomCallback(const std::function<void(Entity* target)>& callback) { m_PhantomCollisionCallbacks.push_back(callback); };
|
||||
void AddDieCallback(const std::function<void()>& callback) { m_DieCallbacks.push_back(callback); };
|
||||
void Resurrect();
|
||||
|
||||
void AddLootItem(const Loot::Info& info);
|
||||
void PickupItem(const LWOOBJID& objectID);
|
||||
|
||||
bool CanPickupCoins(const uint64_t& count) const;
|
||||
void PickupCoins(const uint64_t& count);
|
||||
void RegisterCoinDrop(const uint64_t& count);
|
||||
|
||||
void ScheduleKillAfterUpdate(Entity* murderer = nullptr);
|
||||
void TriggerEvent(const eTriggerEventType event, Entity* optionalTarget = nullptr);
|
||||
void ScheduleDestructionAfterUpdate() { m_ShouldDestroyAfterUpdate = true; }
|
||||
|
||||
virtual NiPoint3 GetRespawnPosition() const { return NiPoint3::ZERO; }
|
||||
virtual NiQuaternion GetRespawnRotation() const { return NiQuaternion::IDENTITY; }
|
||||
CppScripts::Script* GetScript() const;
|
||||
|
||||
void Sleep();
|
||||
void Wake();
|
||||
bool IsSleeping() const;
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
|
||||
//Retroactively corrects the model vault size due to incorrect initialization in a previous patch.
|
||||
void RetroactiveVaultSize();
|
||||
bool GetBoolean(const std::u16string& name) const { return GetVar<bool>(name); };
|
||||
int32_t GetI32(const std::u16string& name) const { return GetVar<int32_t>(name); };
|
||||
int64_t GetI64(const std::u16string& name) const { return GetVar<int64_t>(name); };
|
||||
|
||||
void SetBoolean(const std::u16string& name, bool value) { SetVar<bool>(name, value); }
|
||||
void SetI32(const std::u16string& name, int32_t value) { SetVar<int32_t>(name, value); };
|
||||
void SetI64(const std::u16string& name, int64_t value) { SetVar<int64_t>(name, value); };
|
||||
|
||||
bool HasVar(const std::u16string& name) const;
|
||||
|
||||
/**
|
||||
* Get the LDF data.
|
||||
*/
|
||||
LDFBaseData* GetVarData(const std::u16string& name) const;
|
||||
|
||||
/**
|
||||
* Get the LDF value and convert it to a string.
|
||||
*/
|
||||
std::string GetVarAsString(const std::u16string& name) const;
|
||||
|
||||
/*
|
||||
* Collision
|
||||
*/
|
||||
std::vector<LWOOBJID>& GetTargetsInPhantom();
|
||||
|
||||
Entity* GetScheduledKiller() { return m_ScheduleKiller; }
|
||||
|
||||
const std::unordered_map<eReplicaComponentType, ComponentPtr>& GetComponents() { return m_Components; }
|
||||
|
||||
// Template declarations
|
||||
template<typename T>
|
||||
const T& GetVar(const std::u16string& name) const;
|
||||
|
||||
template<typename T>
|
||||
T GetVarAs(const std::u16string& name) const;
|
||||
|
||||
template<typename T>
|
||||
void SetVar(const std::u16string& name, const T& value);
|
||||
|
||||
template<typename T>
|
||||
T GetNetworkVar(const std::u16string& name);
|
||||
|
||||
void SendNetworkVar(const std::string& data, const SystemAddress& sysAddr);
|
||||
|
||||
template<typename T>
|
||||
void SetNetworkVar(const std::u16string& name, const T& value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
template<typename T>
|
||||
void SetNetworkVar(const std::u16string& name, const std::vector<T>& value, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||
/**
|
||||
* @brief Get a non-owning reference to a component
|
||||
*
|
||||
* @tparam Cmpt The component to get a non-owning reference of
|
||||
* @return Cmpt* The non-owning pointer to the component
|
||||
*/
|
||||
template<typename Cmpt>
|
||||
Cmpt* GetComponent() const;
|
||||
|
||||
/**
|
||||
* @brief Adds a component to this Entity.
|
||||
*
|
||||
* @tparam Cmpt The component to create
|
||||
* @tparam ConstructorValues The constructor values to forward to the component
|
||||
* @param arguments The constructor values to forward to the component
|
||||
* @return Cmpt* A non-owning pointer to the created component,
|
||||
* or a non-owning pointer to the existing component if the component already existed.
|
||||
*/
|
||||
template<typename Cmpt, typename...ConstructorValues>
|
||||
Cmpt* AddComponent(ConstructorValues... arguments);
|
||||
|
||||
/**
|
||||
* @brief Removes a component from this Entity.
|
||||
*/
|
||||
template<typename Cmpt>
|
||||
void RemoveComponent();
|
||||
|
||||
protected:
|
||||
LWOOBJID m_ObjectID;
|
||||
|
||||
LOT m_TemplateID;
|
||||
|
||||
std::vector<LDFBaseData*> m_Settings;
|
||||
std::vector<LDFBaseData*> m_NetworkSettings;
|
||||
|
||||
NiPoint3 m_DefaultPosition;
|
||||
NiQuaternion m_DefaultRotation;
|
||||
float m_Scale;
|
||||
|
||||
Spawner* m_Spawner;
|
||||
LWOOBJID m_SpawnerID;
|
||||
|
||||
bool m_HasSpawnerNodeID;
|
||||
uint32_t m_SpawnerNodeID;
|
||||
|
||||
Character* m_Character;
|
||||
|
||||
Entity* m_ParentEntity; //For spawners and the like
|
||||
std::vector<Entity*> m_ChildEntities;
|
||||
eGameMasterLevel m_GMLevel;
|
||||
std::vector<std::string> m_Groups;
|
||||
uint16_t m_NetworkID;
|
||||
std::vector<std::function<void()>> m_DieCallbacks;
|
||||
std::vector<std::function<void(Entity*)>> m_PhantomCollisionCallbacks;
|
||||
|
||||
std::unordered_map<eReplicaComponentType, ComponentPtr> m_Components;
|
||||
std::vector<std::unique_ptr<EntityTimer>> m_Timers;
|
||||
std::vector<std::unique_ptr<EntityTimer>> m_PendingTimers;
|
||||
std::vector<std::unique_ptr<EntityCallbackTimer>> m_CallbackTimers;
|
||||
|
||||
bool m_ShouldDestroyAfterUpdate;
|
||||
|
||||
LWOOBJID m_OwnerOverride;
|
||||
|
||||
Entity* m_ScheduleKiller;
|
||||
|
||||
bool m_PlayerIsReadyForUpdates;
|
||||
|
||||
bool m_IsGhostingCandidate;
|
||||
|
||||
int8_t m_Observers;
|
||||
|
||||
bool m_IsParentChildDirty;
|
||||
|
||||
/*
|
||||
* Collision
|
||||
*/
|
||||
std::vector<LWOOBJID> m_TargetsInPhantom;
|
||||
|
||||
static const std::vector<ComponentWhitelist> m_ComponentWhitelists;
|
||||
};
|
||||
|
||||
#include "Entity.tcc"
|
||||
|
||||
#endif //!__ENTITY__H__
|
||||
161
dGame/dEntity/Entity.tcc
Normal file
161
dGame/dEntity/Entity.tcc
Normal file
@@ -0,0 +1,161 @@
|
||||
// Template definitions for Entity.
|
||||
|
||||
#ifndef __ENTITY__H__
|
||||
#error "Include Entity.h instead of Entity.tpp"
|
||||
#endif
|
||||
|
||||
#include "LDFFormat.h"
|
||||
|
||||
// Access definitions
|
||||
template <typename Cmpt>
|
||||
Cmpt* Entity::GetComponent() const {
|
||||
const auto& componentItr = this->m_Components.find(Cmpt::ComponentType);
|
||||
return componentItr == this->m_Components.end() ? nullptr : dynamic_cast<Cmpt*>(componentItr->second.get());
|
||||
}
|
||||
|
||||
template<typename Cmpt, typename...ConstructorValues>
|
||||
Cmpt* Entity::AddComponent(ConstructorValues...arguments) {
|
||||
auto* component = GetComponent<Cmpt>();
|
||||
if (component) return dynamic_cast<Cmpt*>(component);
|
||||
|
||||
auto& insertedComponent = m_Components.insert_or_assign(Cmpt::ComponentType,
|
||||
std::make_unique<Cmpt>(this, std::forward<ConstructorValues>(arguments)...)).first->second;
|
||||
return dynamic_cast<Cmpt*>(insertedComponent.get());
|
||||
}
|
||||
|
||||
template<typename Cmpt>
|
||||
void Entity::RemoveComponent() {
|
||||
m_Components.erase(Cmpt::ComponentType);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& Entity::GetVar(const std::u16string& name) const {
|
||||
auto* data = GetVarData(name);
|
||||
|
||||
if (data == nullptr) {
|
||||
return LDFData<T>::Default;
|
||||
}
|
||||
|
||||
auto* typed = dynamic_cast<LDFData<T>*>(data);
|
||||
|
||||
if (typed == nullptr) {
|
||||
return LDFData<T>::Default;
|
||||
}
|
||||
|
||||
return typed->GetValue();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Entity::GetVarAs(const std::u16string& name) const {
|
||||
const auto data = GetVarAsString(name);
|
||||
|
||||
T value;
|
||||
|
||||
if (!GeneralUtils::TryParse(data, value)) {
|
||||
return LDFData<T>::Default;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Entity::SetVar(const std::u16string& name, const T& value) {
|
||||
auto* data = GetVarData(name);
|
||||
|
||||
if (data == nullptr) {
|
||||
auto* data = new LDFData<T>(name, value);
|
||||
|
||||
m_Settings.push_back(data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto* typed = dynamic_cast<LDFData<T>*>(data);
|
||||
|
||||
if (typed == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
typed->SetValue(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Entity::SetNetworkVar(const std::u16string& name, const T& value, const SystemAddress& sysAddr) {
|
||||
LDFData<T>* newData = nullptr;
|
||||
|
||||
for (auto* data : m_NetworkSettings) {
|
||||
if (data->GetKey() != name)
|
||||
continue;
|
||||
|
||||
newData = dynamic_cast<LDFData<T>*>(data);
|
||||
if (newData != nullptr) {
|
||||
newData->SetValue(value);
|
||||
} else { // If we're changing types
|
||||
m_NetworkSettings.erase(
|
||||
std::remove(m_NetworkSettings.begin(), m_NetworkSettings.end(), data), m_NetworkSettings.end()
|
||||
);
|
||||
delete data;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (newData == nullptr) {
|
||||
newData = new LDFData<T>(name, value);
|
||||
}
|
||||
|
||||
m_NetworkSettings.push_back(newData);
|
||||
SendNetworkVar(newData->GetString(true), sysAddr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Entity::SetNetworkVar(const std::u16string& name, const std::vector<T>& values, const SystemAddress& sysAddr) {
|
||||
std::stringstream updates;
|
||||
auto index = 1;
|
||||
|
||||
for (const auto& value : values) {
|
||||
LDFData<T>* newData = nullptr;
|
||||
const auto& indexedName = name + u"." + GeneralUtils::to_u16string(index);
|
||||
|
||||
for (auto* data : m_NetworkSettings) {
|
||||
if (data->GetKey() != indexedName)
|
||||
continue;
|
||||
|
||||
newData = dynamic_cast<LDFData<T>*>(data);
|
||||
newData->SetValue(value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (newData == nullptr) {
|
||||
newData = new LDFData<T>(indexedName, value);
|
||||
}
|
||||
|
||||
m_NetworkSettings.push_back(newData);
|
||||
|
||||
if (index == values.size()) {
|
||||
updates << newData->GetString(true);
|
||||
} else {
|
||||
updates << newData->GetString(true) << "\n";
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
SendNetworkVar(updates.str(), sysAddr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T Entity::GetNetworkVar(const std::u16string& name) {
|
||||
for (auto* data : m_NetworkSettings) {
|
||||
if (data == nullptr || data->GetKey() != name)
|
||||
continue;
|
||||
|
||||
auto* typed = dynamic_cast<LDFData<T>*>(data);
|
||||
if (typed == nullptr)
|
||||
continue;
|
||||
|
||||
return typed->GetValue();
|
||||
}
|
||||
|
||||
return LDFData<T>::Default;
|
||||
}
|
||||
Reference in New Issue
Block a user