Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Move Player ghosting functionality to GhostComponent #1413

Merged
merged 10 commits into from
Jan 14, 2024
1 change: 1 addition & 0 deletions dGame/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ set(DGAME_SOURCES "Character.cpp"
"EntityManager.cpp"
"LeaderboardManager.cpp"
"Player.cpp"
"PlayerManager.cpp"
"TeamManager.cpp"
"TradingManager.cpp"
"User.cpp"
Expand Down
6 changes: 3 additions & 3 deletions dGame/Entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2125,9 +2125,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);
}
47 changes: 28 additions & 19 deletions dGame/EntityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "eGameMasterLevel.h"
#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 = {
Expand Down Expand Up @@ -187,8 +189,9 @@ void EntityManager::SerializeEntities() {
entity->WriteComponents(&stream, eReplicaPacketType::SERIALIZATION);

if (entity->GetIsGhostingCandidate()) {
for (auto* player : Player::GetAllPlayers()) {
if (player->IsObserved(toSerialize)) {
for (auto* player : PlayerManager::GetAllPlayers()) {
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (ghostComponent && ghostComponent->IsObserved(toSerialize)) {
Game::server->Send(&stream, player->GetSystemAddress(), false);
}
}
Expand Down Expand Up @@ -376,11 +379,12 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
if (skipChecks) {
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
} else {
for (auto* player : Player::GetAllPlayers()) {
for (auto* player : PlayerManager::GetAllPlayers()) {
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());
}
}
}
Expand All @@ -405,7 +409,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
}
}

UpdateGhosting(Player::GetPlayer(sysAddr));
UpdateGhosting(PlayerManager::GetPlayer(sysAddr));
}

void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
Expand All @@ -418,9 +422,10 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)

Game::server->Send(&stream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);

for (auto* player : Player::GetAllPlayers()) {
for (auto* player : PlayerManager::GetAllPlayers()) {
if (!player->GetPlayerReadyForUpdates()) {
player->RemoveLimboConstruction(entity->GetObjectID());
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->RemoveLimboConstruction(entity->GetObjectID());
}
}
}
Expand Down Expand Up @@ -465,7 +470,7 @@ void EntityManager::QueueGhostUpdate(LWOOBJID playerID) {

void EntityManager::UpdateGhosting() {
for (const auto playerID : m_PlayersToUpdateGhosting) {
auto* player = Player::GetPlayer(playerID);
auto* player = PlayerManager::GetPlayer(playerID);

if (player == nullptr) {
continue;
Expand All @@ -483,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;
Expand All @@ -498,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);

Expand All @@ -510,7 +516,7 @@ void EntityManager::UpdateGhosting(Player* player) {
}

if (observed && distance > ghostingDistanceMax && !isOverride) {
player->GhostEntity(id);
ghostComponent->GhostEntity(id);

DestructEntity(entity, player->GetSystemAddress());

Expand All @@ -527,7 +533,7 @@ void EntityManager::UpdateGhosting(Player* player) {
}
}

player->ObserveEntity(id);
ghostComponent->ObserveEntity(id);

ConstructEntity(entity, player->GetSystemAddress());

Expand All @@ -548,23 +554,26 @@ void EntityManager::CheckGhosting(Entity* entity) {

const auto isAudioEmitter = entity->GetLOT() == 6368;

for (auto* player : Player::GetAllPlayers()) {
const auto& entityPoint = player->GetGhostReferencePoint();
for (auto* player : PlayerManager::GetAllPlayers()) {
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());

Expand Down
134 changes: 6 additions & 128 deletions dGame/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,7 @@
#include "CppScripts.h"
#include "Loot.h"
#include "eReplicaComponentType.h"

namespace {
std::vector<Player*> m_Players;
};

const std::vector<Player*>& Player::GetAllPlayers() {
return m_Players;
}

void Player::SetGhostReferencePoint(const NiPoint3& value) {
m_GhostReferencePoint = value;
}

void Player::SetGhostOverridePoint(const NiPoint3& value) {
m_GhostOverridePoint = value;
}
#include "PlayerManager.h"

void Player::SetRespawnPos(const NiPoint3& position) {
if (!m_Character) return;
Expand All @@ -54,122 +39,17 @@ 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);

const auto& iter = std::find(m_Players.begin(), m_Players.end(), this);

if (iter == m_Players.end()) {
m_Players.push_back(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::GetPlayer(const SystemAddress& sysAddr) {
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();

return static_cast<Player*>(entity);
}

Player* Player::GetPlayer(const std::string& name) {
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);

Player* player = nullptr;
for (auto* character : characters) {
if (!character->IsPlayer()) continue;

if (GeneralUtils::CaseInsensitiveStringCompare(name, character->GetCharacter()->GetName())) {
player = dynamic_cast<Player*>(character);
}
}

return player;
}

Player* Player::GetPlayer(LWOOBJID playerID) {
Player* playerToReturn = nullptr;
for (auto* player : m_Players) {
if (player->GetObjectID() == playerID) {
playerToReturn = player;
}
}

return playerToReturn;
PlayerManager::AddPlayer(this);
}

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();

const auto iter = std::find(m_Players.begin(), m_Players.end(), this);

if (iter == m_Players.end()) {

// Make sure the player exists first. Remove afterwards to prevent the OnPlayerExist functions from not being able to find the player.
if (!PlayerManager::RemovePlayer(this)) {
LOG("Unable to find player to remove from manager.");
return;
}

Expand All @@ -188,6 +68,4 @@ Player::~Player() {
}
}
}

m_Players.erase(iter);
}
Loading
Loading