mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
chore: Move Player ghosting functionality to GhostComponent (#1413)
* Moving and organizing Player code - Move code to CharacterComponent - Remove extraneous interfaces - Simplify some code greatly - Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.) - Update code to use CharacterComponent for sending to zone instead of Player*. * Moving and organizing Player code - Move code to CharacterComponent - Remove extraneous interfaces - Simplify some code greatly - Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.) - Update code to use CharacterComponent for sending to zone instead of Player*. - Remove static storage container (static containers can be destroyed before exit/terminate handler executes) * remove player cast * Remove extra includes * Add a player manager Used for the static Player functions. Further removes stuff from the Player class/file. * chore: Move ghosting functionality to component Tested that ghosting still works and players are still firing off the OnPlayerLeave and relevant handlers. * move to unordered_set
This commit is contained in:
parent
0a30430c4f
commit
c83ec8228c
@ -2135,9 +2135,9 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
|
||||
controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
|
||||
controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
|
||||
|
||||
auto* player = static_cast<Player*>(this);
|
||||
player->SetGhostReferencePoint(update.position);
|
||||
Game::entityManager->QueueGhostUpdate(player->GetObjectID());
|
||||
auto* ghostComponent = GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position);
|
||||
Game::entityManager->QueueGhostUpdate(GetObjectID());
|
||||
|
||||
if (updateChar) Game::entityManager->SerializeEntity(this);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eReplicaPacketType.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "GhostComponent.h"
|
||||
|
||||
// Configure which zones have ghosting disabled, mostly small worlds.
|
||||
std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = {
|
||||
@ -189,7 +190,8 @@ void EntityManager::SerializeEntities() {
|
||||
|
||||
if (entity->GetIsGhostingCandidate()) {
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
if (player->IsObserved(toSerialize)) {
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (ghostComponent && ghostComponent->IsObserved(toSerialize)) {
|
||||
Game::server->Send(&stream, player->GetSystemAddress(), false);
|
||||
}
|
||||
}
|
||||
@ -381,7 +383,8 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
||||
if (player->GetPlayerReadyForUpdates()) {
|
||||
Game::server->Send(&stream, player->GetSystemAddress(), false);
|
||||
} else {
|
||||
player->AddLimboConstruction(entity->GetObjectID());
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->AddLimboConstruction(entity->GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -421,7 +424,8 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
|
||||
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
if (!player->GetPlayerReadyForUpdates()) {
|
||||
player->RemoveLimboConstruction(entity->GetObjectID());
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->RemoveLimboConstruction(entity->GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -484,13 +488,14 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
}
|
||||
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
|
||||
if (missionComponent == nullptr) {
|
||||
if (missionComponent == nullptr || !ghostComponent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& referencePoint = player->GetGhostReferencePoint();
|
||||
const auto isOverride = player->GetGhostOverride();
|
||||
const auto& referencePoint = ghostComponent->GetGhostReferencePoint();
|
||||
const auto isOverride = ghostComponent->GetGhostOverride();
|
||||
|
||||
for (auto* entity : m_EntitiesToGhost) {
|
||||
const auto isAudioEmitter = entity->GetLOT() == 6368;
|
||||
@ -499,7 +504,7 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
|
||||
const int32_t id = entity->GetObjectID();
|
||||
|
||||
const auto observed = player->IsObserved(id);
|
||||
const auto observed = ghostComponent->IsObserved(id);
|
||||
|
||||
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
||||
|
||||
@ -511,7 +516,7 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
}
|
||||
|
||||
if (observed && distance > ghostingDistanceMax && !isOverride) {
|
||||
player->GhostEntity(id);
|
||||
ghostComponent->GhostEntity(id);
|
||||
|
||||
DestructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
@ -528,7 +533,7 @@ void EntityManager::UpdateGhosting(Player* player) {
|
||||
}
|
||||
}
|
||||
|
||||
player->ObserveEntity(id);
|
||||
ghostComponent->ObserveEntity(id);
|
||||
|
||||
ConstructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
@ -550,22 +555,25 @@ void EntityManager::CheckGhosting(Entity* entity) {
|
||||
const auto isAudioEmitter = entity->GetLOT() == 6368;
|
||||
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
const auto& entityPoint = player->GetGhostReferencePoint();
|
||||
auto* ghostComponent = player->GetComponent<GhostComponent>();
|
||||
if (!ghostComponent) continue;
|
||||
|
||||
const auto& entityPoint = ghostComponent->GetGhostReferencePoint();
|
||||
|
||||
const int32_t id = entity->GetObjectID();
|
||||
|
||||
const auto observed = player->IsObserved(id);
|
||||
const auto observed = ghostComponent->IsObserved(id);
|
||||
|
||||
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
|
||||
|
||||
if (observed && distance > ghostingDistanceMax) {
|
||||
player->GhostEntity(id);
|
||||
ghostComponent->GhostEntity(id);
|
||||
|
||||
DestructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
entity->SetObservers(entity->GetObservers() - 1);
|
||||
} else if (!observed && ghostingDistanceMin > distance) {
|
||||
player->ObserveEntity(id);
|
||||
ghostComponent->ObserveEntity(id);
|
||||
|
||||
ConstructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
|
@ -14,14 +14,6 @@
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
void Player::SetGhostReferencePoint(const NiPoint3& value) {
|
||||
m_GhostReferencePoint = value;
|
||||
}
|
||||
|
||||
void Player::SetGhostOverridePoint(const NiPoint3& value) {
|
||||
m_GhostOverridePoint = value;
|
||||
}
|
||||
|
||||
void Player::SetRespawnPos(const NiPoint3& position) {
|
||||
if (!m_Character) return;
|
||||
|
||||
@ -47,85 +39,16 @@ Player::Player(const LWOOBJID& objectID, const EntityInfo info, User* user, Enti
|
||||
m_SystemAddress = m_ParentUser->GetSystemAddress();
|
||||
m_DroppedCoins = 0;
|
||||
|
||||
m_GhostReferencePoint = NiPoint3::ZERO;
|
||||
m_GhostOverridePoint = NiPoint3::ZERO;
|
||||
m_GhostOverride = false;
|
||||
|
||||
int32_t initialObservedEntitiesCapacity = 256;
|
||||
m_ObservedEntities.resize(initialObservedEntitiesCapacity);
|
||||
|
||||
m_Character->SetEntity(this);
|
||||
|
||||
PlayerManager::AddPlayer(this);
|
||||
}
|
||||
|
||||
void Player::AddLimboConstruction(LWOOBJID objectId) {
|
||||
const auto iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
|
||||
if (iter == m_LimboConstructions.end()) {
|
||||
m_LimboConstructions.push_back(objectId);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::RemoveLimboConstruction(LWOOBJID objectId) {
|
||||
const auto iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
|
||||
if (iter != m_LimboConstructions.end()) {
|
||||
m_LimboConstructions.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ConstructLimboEntities() {
|
||||
for (const auto& objectId : m_LimboConstructions) {
|
||||
auto* entity = Game::entityManager->GetEntity(objectId);
|
||||
if (!entity) continue;
|
||||
|
||||
Game::entityManager->ConstructEntity(entity, m_SystemAddress);
|
||||
}
|
||||
|
||||
m_LimboConstructions.clear();
|
||||
}
|
||||
|
||||
void Player::ObserveEntity(int32_t id) {
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == 0 || observedEntity == id) {
|
||||
observedEntity = id;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_ObservedEntities.reserve(m_ObservedEntities.size() + 1);
|
||||
|
||||
m_ObservedEntities.push_back(id);
|
||||
}
|
||||
|
||||
bool Player::IsObserved(int32_t id) {
|
||||
return std::find(m_ObservedEntities.begin(), m_ObservedEntities.end(), id) != m_ObservedEntities.end();
|
||||
}
|
||||
|
||||
void Player::GhostEntity(int32_t id) {
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == id) {
|
||||
observedEntity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player::~Player() {
|
||||
LOG("Deleted player");
|
||||
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == 0) continue;
|
||||
|
||||
auto* entity = Game::entityManager->GetGhostCandidate(observedEntity);
|
||||
if (!entity) continue;
|
||||
|
||||
entity->SetObservers(entity->GetObservers() - 1);
|
||||
}
|
||||
|
||||
m_LimboConstructions.clear();
|
||||
|
||||
// Make sure the player exists first. Remove afterwards to prevent the OnPlayerExist functions from not being able to find the player.
|
||||
if (!PlayerManager::GetPlayer(GetObjectID())) {
|
||||
if (!PlayerManager::RemovePlayer(this)) {
|
||||
LOG("Unable to find player to remove from manager.");
|
||||
return;
|
||||
}
|
||||
@ -145,6 +68,4 @@ Player::~Player() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerManager::RemovePlayer(this);
|
||||
}
|
||||
|
@ -26,14 +26,6 @@ public:
|
||||
|
||||
const NiQuaternion& GetRespawnRotation() const override { return m_respawnRot; };
|
||||
|
||||
const NiPoint3& GetGhostReferencePoint() const { return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetOriginGhostReferencePoint() const { return m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetGhostOverridePoint() const { return m_GhostOverridePoint; };
|
||||
|
||||
bool GetGhostOverride() const { return m_GhostOverride; };
|
||||
|
||||
std::map<LWOOBJID, Loot::Info>& GetDroppedLoot() { return m_DroppedLoot; };
|
||||
|
||||
uint64_t GetDroppedCoins() const { return m_DroppedCoins; };
|
||||
@ -42,8 +34,6 @@ public:
|
||||
* Setters
|
||||
*/
|
||||
|
||||
void SetGhostOverride(bool value) { m_GhostOverride = value; };
|
||||
|
||||
void SetDroppedCoins(const uint64_t value) { m_DroppedCoins = value; };
|
||||
|
||||
void SetSystemAddress(const SystemAddress& value) override;
|
||||
@ -52,26 +42,10 @@ public:
|
||||
|
||||
void SetRespawnRot(const NiQuaternion& rotation) override;
|
||||
|
||||
void SetGhostReferencePoint(const NiPoint3& value);
|
||||
|
||||
void SetGhostOverridePoint(const NiPoint3& value);
|
||||
|
||||
/**
|
||||
* Ghosting
|
||||
*/
|
||||
|
||||
void AddLimboConstruction(LWOOBJID objectId);
|
||||
|
||||
void RemoveLimboConstruction(LWOOBJID objectId);
|
||||
|
||||
void ConstructLimboEntities();
|
||||
|
||||
void ObserveEntity(const int32_t id);
|
||||
|
||||
bool IsObserved(const int32_t id);
|
||||
|
||||
void GhostEntity(const int32_t id);
|
||||
|
||||
~Player() override;
|
||||
private:
|
||||
SystemAddress m_SystemAddress;
|
||||
@ -82,16 +56,6 @@ private:
|
||||
|
||||
User* m_ParentUser;
|
||||
|
||||
NiPoint3 m_GhostReferencePoint;
|
||||
|
||||
NiPoint3 m_GhostOverridePoint;
|
||||
|
||||
bool m_GhostOverride;
|
||||
|
||||
std::vector<int32_t> m_ObservedEntities;
|
||||
|
||||
std::vector<LWOOBJID> m_LimboConstructions;
|
||||
|
||||
std::map<LWOOBJID, Loot::Info> m_DroppedLoot;
|
||||
|
||||
uint64_t m_DroppedCoins;
|
||||
|
@ -22,12 +22,15 @@ void PlayerManager::AddPlayer(Player* player) {
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::RemovePlayer(Player* player) {
|
||||
bool PlayerManager::RemovePlayer(Player* player) {
|
||||
const auto iter = std::find(m_Players.begin(), m_Players.end(), player);
|
||||
|
||||
if (iter != m_Players.end()) {
|
||||
const bool toReturn = iter != m_Players.end();
|
||||
if (toReturn) {
|
||||
m_Players.erase(iter);
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
Player* PlayerManager::GetPlayer(const SystemAddress& sysAddr) {
|
||||
|
@ -11,7 +11,7 @@ struct SystemAddress;
|
||||
namespace PlayerManager {
|
||||
void AddPlayer(Player* player);
|
||||
|
||||
void RemovePlayer(Player* player);
|
||||
bool RemovePlayer(Player* player);
|
||||
|
||||
Player* GetPlayer(const SystemAddress& sysAddr);
|
||||
|
||||
|
@ -1,4 +1,57 @@
|
||||
#include "GhostComponent.h"
|
||||
|
||||
// TODO Move ghosting related code from Player to here
|
||||
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {}
|
||||
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {
|
||||
m_GhostReferencePoint = NiPoint3::ZERO;
|
||||
m_GhostOverridePoint = NiPoint3::ZERO;
|
||||
m_GhostOverride = false;
|
||||
}
|
||||
|
||||
GhostComponent::~GhostComponent() {
|
||||
for (auto& observedEntity : m_ObservedEntities) {
|
||||
if (observedEntity == 0) continue;
|
||||
|
||||
auto* entity = Game::entityManager->GetGhostCandidate(observedEntity);
|
||||
if (!entity) continue;
|
||||
|
||||
entity->SetObservers(entity->GetObservers() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GhostComponent::SetGhostReferencePoint(const NiPoint3& value) {
|
||||
m_GhostReferencePoint = value;
|
||||
}
|
||||
|
||||
void GhostComponent::SetGhostOverridePoint(const NiPoint3& value) {
|
||||
m_GhostOverridePoint = value;
|
||||
}
|
||||
|
||||
void GhostComponent::AddLimboConstruction(LWOOBJID objectId) {
|
||||
m_LimboConstructions.insert(objectId);
|
||||
}
|
||||
|
||||
void GhostComponent::RemoveLimboConstruction(LWOOBJID objectId) {
|
||||
m_LimboConstructions.erase(objectId);
|
||||
}
|
||||
|
||||
void GhostComponent::ConstructLimboEntities() {
|
||||
for (const auto& objectId : m_LimboConstructions) {
|
||||
auto* entity = Game::entityManager->GetEntity(objectId);
|
||||
if (!entity) continue;
|
||||
|
||||
Game::entityManager->ConstructEntity(entity, m_Parent->GetSystemAddress());
|
||||
}
|
||||
|
||||
m_LimboConstructions.clear();
|
||||
}
|
||||
|
||||
void GhostComponent::ObserveEntity(int32_t id) {
|
||||
m_ObservedEntities.insert(id);
|
||||
}
|
||||
|
||||
bool GhostComponent::IsObserved(int32_t id) {
|
||||
return m_ObservedEntities.contains(id);
|
||||
}
|
||||
|
||||
void GhostComponent::GhostEntity(int32_t id) {
|
||||
m_ObservedEntities.erase(id);
|
||||
}
|
||||
|
@ -3,11 +3,52 @@
|
||||
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <unordered_set>
|
||||
|
||||
class NiPoint3;
|
||||
|
||||
class GhostComponent : public Component {
|
||||
public:
|
||||
static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST;
|
||||
GhostComponent(Entity* parent);
|
||||
~GhostComponent() override;
|
||||
|
||||
void SetGhostOverride(bool value) { m_GhostOverride = value; };
|
||||
|
||||
const NiPoint3& GetGhostReferencePoint() const { return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetOriginGhostReferencePoint() const { return m_GhostReferencePoint; };
|
||||
|
||||
const NiPoint3& GetGhostOverridePoint() const { return m_GhostOverridePoint; };
|
||||
|
||||
bool GetGhostOverride() const { return m_GhostOverride; };
|
||||
|
||||
void SetGhostReferencePoint(const NiPoint3& value);
|
||||
|
||||
void SetGhostOverridePoint(const NiPoint3& value);
|
||||
|
||||
void AddLimboConstruction(const LWOOBJID objectId);
|
||||
|
||||
void RemoveLimboConstruction(const LWOOBJID objectId);
|
||||
|
||||
void ConstructLimboEntities();
|
||||
|
||||
void ObserveEntity(const int32_t id);
|
||||
|
||||
bool IsObserved(const int32_t id);
|
||||
|
||||
void GhostEntity(const int32_t id);
|
||||
|
||||
private:
|
||||
NiPoint3 m_GhostReferencePoint;
|
||||
|
||||
NiPoint3 m_GhostOverridePoint;
|
||||
|
||||
std::unordered_set<int32_t> m_ObservedEntities;
|
||||
|
||||
std::unordered_set<LWOOBJID> m_LimboConstructions;
|
||||
|
||||
bool m_GhostOverride;
|
||||
};
|
||||
|
||||
#endif //!__GHOSTCOMPONENT__H__
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "eGameMessageType.h"
|
||||
#include "ePlayerFlag.h"
|
||||
#include "dConfig.h"
|
||||
#include "GhostComponent.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const SystemAddress& sysAddr, LWOOBJID objectID, eGameMessageType messageID) {
|
||||
@ -108,9 +109,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
GameMessages::SendRestoreToPostLoadStats(entity, sysAddr);
|
||||
entity->SetPlayerReadyForUpdates();
|
||||
|
||||
auto* player = dynamic_cast<Player*>(entity);
|
||||
if (player != nullptr) {
|
||||
player->ConstructLimboEntities();
|
||||
auto* ghostComponent = entity->GetComponent<GhostComponent>();
|
||||
if (ghostComponent != nullptr) {
|
||||
ghostComponent->ConstructLimboEntities();
|
||||
}
|
||||
|
||||
InventoryComponent* inv = entity->GetComponent<InventoryComponent>();
|
||||
@ -137,14 +138,14 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
|
||||
|
||||
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
||||
script->OnPlayerLoaded(zoneControl, player);
|
||||
script->OnPlayerLoaded(zoneControl, entity);
|
||||
}
|
||||
|
||||
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT);
|
||||
for (Entity* scriptEntity : scriptedActs) {
|
||||
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
||||
script->OnPlayerLoaded(scriptEntity, player);
|
||||
script->OnPlayerLoaded(scriptEntity, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include "RailActivatorComponent.h"
|
||||
#include "LevelProgressionComponent.h"
|
||||
#include "DonationVendorComponent.h"
|
||||
#include "GhostComponent.h"
|
||||
|
||||
// Message includes:
|
||||
#include "dZoneManager.h"
|
||||
@ -4605,7 +4606,8 @@ void GameMessages::HandleToggleGhostReferenceOverride(RakNet::BitStream* inStrea
|
||||
auto* player = PlayerManager::GetPlayer(sysAddr);
|
||||
|
||||
if (player != nullptr) {
|
||||
player->SetGhostOverride(bOverride);
|
||||
auto* ghostComponent = entity->GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->SetGhostOverride(bOverride);
|
||||
|
||||
Game::entityManager->UpdateGhosting(player);
|
||||
}
|
||||
@ -4620,7 +4622,8 @@ void GameMessages::HandleSetGhostReferencePosition(RakNet::BitStream* inStream,
|
||||
auto* player = PlayerManager::GetPlayer(sysAddr);
|
||||
|
||||
if (player != nullptr) {
|
||||
player->SetGhostOverridePoint(position);
|
||||
auto* ghostComponent = entity->GetComponent<GhostComponent>();
|
||||
if (ghostComponent) ghostComponent->SetGhostOverridePoint(position);
|
||||
|
||||
Game::entityManager->UpdateGhosting(player);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user