Compare commits

...

8 Commits

Author SHA1 Message Date
0e8af24572 Make better 2023-05-09 22:37:57 -05:00
051395e4c9 fix: prevent negative imagination
And fail switch if we don't have enough imagination
2023-05-09 22:14:46 -05:00
4ff5afd9f7 Fix race exit dialogue always exiting (#1077)
Fixes #1048
Tested that closing the dialog via esc, the x in the top right, or the big red x doesn't exit the race
Tested that the green check button does exit the race
2023-05-09 00:40:00 -05:00
David Markowitz
ce931c2cfe Fix erroneous GM message ID (#1076) 2023-05-09 00:39:43 -05:00
David Markowitz
7aad6e4bc2 Make header skips more obvious (#1074)
* Make header skips more obvious

seeing inStream.Read(LWOOBJID) is much less clear than a macro which very clearly skips the header.

* Formatting pass
2023-05-08 06:31:10 -05:00
Gie "Max" Vanommeslaeghe
64a947e338 Merge pull request #1069 from EmosewaMC/NullChecks
Add more null checks and split out code
2023-05-08 12:10:58 +02:00
8ceabadcde Removed some hardcoded logic for racing (#1075)
Including return world and what activity ID to use for rewards
2023-05-08 04:38:08 -05:00
David Markowitz
df3265c82e Add more null checks and split out code
Makes crash logs more apparent for what stage they crashed in for the engine updating.
2023-05-05 23:31:30 -07:00
21 changed files with 175 additions and 164 deletions

View File

@@ -22,10 +22,9 @@ extern PlayerContainer playerContainer;
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Get from the packet which player we want to do something with:
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = 0;
inStream.Read(playerID);
inStream.Read(playerID);
auto player = playerContainer.GetPlayerData(playerID);
if (!player) return;
@@ -99,10 +98,9 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
auto maxNumberOfBestFriendsAsString = Game::config->GetValue("max_number_of_best_friends");
// If this config option doesn't exist, default to 5 which is what live used.
auto maxNumberOfBestFriends = maxNumberOfBestFriendsAsString != "" ? std::stoi(maxNumberOfBestFriendsAsString) : 5U;
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID requestorPlayerID;
inStream.Read(requestorPlayerID);
inStream.Read(requestorPlayerID);
uint32_t spacing{};
inStream.Read(spacing);
std::string playerName = "";
@@ -247,10 +245,9 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
}
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
inStream.Read(playerID);
eAddFriendResponseCode clientResponseCode = static_cast<eAddFriendResponseCode>(packet->data[0x14]);
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
@@ -323,10 +320,9 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
}
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
inStream.Read(playerID);
std::string friendName = PacketUtils::ReadString(0x14, packet, true);
//we'll have to query the db here to find the user, since you can delete them while they're offline.
@@ -381,10 +377,9 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
}
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
auto* sender = playerContainer.GetPlayerData(playerID);
@@ -501,10 +496,9 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
}
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
inStream.Read(playerID);
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
auto* player = playerContainer.GetPlayerData(playerID);
@@ -542,10 +536,9 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
}
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
uint32_t size = 0;
inStream.Read(size);
char declined = 0;
@@ -576,10 +569,9 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
}
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
uint32_t size = 0;
inStream.Read(size);
@@ -593,10 +585,9 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
}
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
@@ -624,10 +615,9 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
}
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
@@ -647,10 +637,9 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
}
void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
uint32_t size = 0;
inStream.Read(size);
@@ -671,10 +660,9 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
}
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
inStream.Read(playerID);
auto* team = playerContainer.GetTeam(playerID);
auto* data = playerContainer.GetPlayerData(playerID);

View File

@@ -19,9 +19,8 @@ PlayerContainer::~PlayerContainer() {
}
void PlayerContainer::InsertPlayer(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
PlayerData* data = new PlayerData();
inStream.SetReadOffset(inStream.GetReadOffset() + 64);
inStream.Read(data->playerID);
uint32_t len;
@@ -52,9 +51,8 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
}
void PlayerContainer::RemovePlayer(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
inStream.Read(playerID);
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
@@ -97,9 +95,8 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
}
void PlayerContainer::MuteUpdate(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
inStream.Read(playerID);
time_t expire = 0;
inStream.Read(expire);
@@ -118,9 +115,8 @@ void PlayerContainer::MuteUpdate(Packet* packet) {
}
void PlayerContainer::CreateTeamServer(Packet* packet) {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID); //skip header
inStream.Read(playerID);
size_t membersSize = 0;
inStream.Read(membersSize);

View File

@@ -28,8 +28,10 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
//========== MACROS ===========
#define HEADER_SIZE 8
#define CBITSTREAM RakNet::BitStream bitStream;
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);

View File

@@ -273,7 +273,7 @@ enum class eGameMessageType : uint16_t {
TEAM_SET_LEADER = 1557,
TEAM_INVITE_CONFIRM = 1558,
TEAM_GET_STATUS_RESPONSE = 1559,
TEAM_ADD_PLAYER = 1526,
TEAM_ADD_PLAYER = 1562,
TEAM_REMOVE_PLAYER = 1563,
START_CELEBRATION_EFFECT = 1618,
ADD_BUFF = 1647,

View File

@@ -161,9 +161,7 @@ void EntityManager::DestroyEntity(const LWOOBJID& objectID) {
}
void EntityManager::DestroyEntity(Entity* entity) {
if (entity == nullptr) {
return;
}
if (!entity) return;
entity->TriggerEvent(eTriggerEventType::DESTROY, entity);
@@ -182,15 +180,11 @@ void EntityManager::DestroyEntity(Entity* entity) {
ScheduleForDeletion(id);
}
void EntityManager::UpdateEntities(const float deltaTime) {
for (const auto& e : m_Entities) {
e.second->Update(deltaTime);
}
void EntityManager::SerializeEntities() {
for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) {
auto* entity = GetEntity(*entry);
if (entity == nullptr) continue;
if (!entity) continue;
m_SerializationCounter++;
@@ -212,11 +206,16 @@ void EntityManager::UpdateEntities(const float deltaTime) {
}
}
m_EntitiesToSerialize.clear();
}
void EntityManager::KillEntities() {
for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) {
auto* entity = GetEntity(*entry);
if (!entity) continue;
if (!entity) {
Game::logger->Log("EntityManager", "Attempting to kill null entity %llu", *entry);
continue;
}
if (entity->GetScheduledKiller()) {
entity->Smash(entity->GetScheduledKiller()->GetObjectID(), eKillType::SILENT);
@@ -225,32 +224,41 @@ void EntityManager::UpdateEntities(const float deltaTime) {
}
}
m_EntitiesToKill.clear();
}
void EntityManager::DeleteEntities() {
for (auto entry = m_EntitiesToDelete.begin(); entry != m_EntitiesToDelete.end(); entry++) {
// Get all this info first before we delete the player.
auto entityToDelete = GetEntity(*entry);
auto networkIdToErase = entityToDelete->GetNetworkId();
const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete);
if (entityToDelete) {
// If we are a player run through the player destructor.
if (entityToDelete->IsPlayer()) {
delete dynamic_cast<Player*>(entityToDelete);
} else {
delete entityToDelete;
}
// Get all this info first before we delete the player.
auto networkIdToErase = entityToDelete->GetNetworkId();
const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete);
delete entityToDelete;
entityToDelete = nullptr;
if (networkIdToErase != 0) m_LostNetworkIds.push(networkIdToErase);
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
} else {
Game::logger->Log("EntityManager", "Attempted to delete non-existent entity %llu", *entry);
}
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
m_Entities.erase(*entry);
}
m_EntitiesToDelete.clear();
}
void EntityManager::UpdateEntities(const float deltaTime) {
for (const auto& e : m_Entities) {
e.second->Update(deltaTime);
}
SerializeEntities();
KillEntities();
DeleteEntities();
}
Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const {
const auto& index = m_Entities.find(objectId);
@@ -316,6 +324,11 @@ const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEnt
}
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
if (!entity) {
Game::logger->Log("EntityManager", "Attempted to construct null entity");
return;
}
if (entity->GetNetworkId() == 0) {
uint16_t networkId;
@@ -395,9 +408,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
}
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
if (entity->GetNetworkId() == 0) {
return;
}
if (!entity || entity->GetNetworkId() == 0) return;
RakNet::BitStream stream;
@@ -414,9 +425,7 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
}
void EntityManager::SerializeEntity(Entity* entity) {
if (entity->GetNetworkId() == 0) {
return;
}
if (!entity || entity->GetNetworkId() == 0) return;
if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) {
m_EntitiesToSerialize.push_back(entity->GetObjectID());

View File

@@ -85,6 +85,10 @@ public:
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
private:
void SerializeEntities();
void KillEntities();
void DeleteEntities();
static EntityManager* m_Address; //For singleton method
static std::vector<LWOMAPID> m_GhostingExcludedZones;
static std::vector<LOT> m_GhostingExcludedLOTs;

View File

@@ -30,7 +30,7 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStre
Game::logger->LogDebug("SwitchBehavior", "[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
if (state || (entity->GetLOT() == 8092 && destroyableComponent->GetImagination() >= m_imagination)) {
if (state) {
this->m_actionTrue->Handle(context, bitStream, branch);
} else {
this->m_actionFalse->Handle(context, bitStream, branch);

View File

@@ -23,6 +23,8 @@
#include "dConfig.h"
#include "Loot.h"
#include "eMissionTaskType.h"
#include "dZoneManager.h"
#include "CDActivitiesTable.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
@@ -45,36 +47,14 @@ RacingControlComponent::RacingControlComponent(Entity* parent)
m_EmptyTimer = 0;
m_SoloRacing = Game::config->GetValue("solo_racing") == "1";
// Select the main world ID as fallback when a player fails to load.
m_MainWorld = 1200;
const auto worldID = Game::server->GetZoneID();
if (dZoneManager::Instance()->CheckIfAccessibleZone((worldID/10)*10)) m_MainWorld = (worldID/10)*10;
switch (worldID) {
case 1203:
m_ActivityID = 42;
m_MainWorld = 1200;
break;
case 1261:
m_ActivityID = 60;
m_MainWorld = 1260;
break;
case 1303:
m_ActivityID = 39;
m_MainWorld = 1300;
break;
case 1403:
m_ActivityID = 54;
m_MainWorld = 1400;
break;
default:
m_ActivityID = 42;
m_MainWorld = 1200;
break;
}
m_ActivityID = 42;
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.instanceMapID == worldID); });
for (CDActivities activity : activities) m_ActivityID = activity.ActivityID;
}
RacingControlComponent::~RacingControlComponent() {}
@@ -382,8 +362,7 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) {
}
}
void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
const std::string& id) {
void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t button, const std::string& id) {
auto* data = GetPlayerData(player->GetObjectID());
if (data == nullptr) {
@@ -425,7 +404,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::LAST_PLACE_FINISH); // Finished first place in specific world.
}
}
} else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") {
} else if (id == "ACT_RACE_EXIT_THE_RACE?" && button == m_ActivityExitConfirm) {
auto* vehicle = EntityManager::Instance()->GetEntity(data->vehicleID);
if (vehicle == nullptr) {

View File

@@ -144,7 +144,7 @@ public:
/**
* Invoked when the player responds to the GUI.
*/
void HandleMessageBoxResponse(Entity* player, const std::string& id);
void HandleMessageBoxResponse(Entity* player, int32_t button, const std::string& id);
/**
* Get the racing data from a player's LWOOBJID.
@@ -246,4 +246,9 @@ private:
float m_EmptyTimer;
bool m_SoloRacing;
/**
* Value for message box response to know if we are exiting the race via the activity dialogue
*/
const int32_t m_ActivityExitConfirm = 1;
};

View File

@@ -196,18 +196,18 @@ void RebuildComponent::Update(float deltaTime) {
DestroyableComponent* destComp = builder->GetComponent<DestroyableComponent>();
if (!destComp) break;
int newImagination = destComp->GetImagination() - 1;
int newImagination = destComp->GetImagination();
if (newImagination <= 0) {
CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true);
break;
}
++m_DrainedImagination;
--newImagination;
destComp->SetImagination(newImagination);
EntityManager::Instance()->SerializeEntity(builder);
++m_DrainedImagination;
if (newImagination == 0 && m_DrainedImagination < m_TakeImagination) {
CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true);
break;
}
}
if (m_Timer >= m_CompleteTime && m_DrainedImagination >= m_TakeImagination) {

View File

@@ -27,6 +27,7 @@
#include "CDCurrencyTableTable.h"
#include "CDActivityRewardsTable.h"
#include "CDActivitiesTable.h"
#include "LeaderboardManager.h"
ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activityID) : Component(parent) {
m_ActivityID = activityID;
@@ -35,10 +36,7 @@ ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activit
for (CDActivities activity : activities) {
m_ActivityInfo = activity;
const auto mapID = m_ActivityInfo.instanceMapID;
if ((mapID == 1203 || mapID == 1261 || mapID == 1303 || mapID == 1403) && Game::config->GetValue("solo_racing") == "1") {
if (static_cast<LeaderboardType>(activity.leaderboardType) == LeaderboardType::Racing && Game::config->GetValue("solo_racing") == "1") {
m_ActivityInfo.minTeamSize = 1;
m_ActivityInfo.minTeams = 1;
}

View File

@@ -3891,7 +3891,7 @@ void GameMessages::HandleMessageBoxResponse(RakNet::BitStream* inStream, Entity*
auto* racingControlComponent = entity->GetComponent<RacingControlComponent>();
if (racingControlComponent != nullptr) {
racingControlComponent->HandleMessageBoxResponse(userEntity, GeneralUtils::UTF16ToWTF8(identifier));
racingControlComponent->HandleMessageBoxResponse(userEntity, iButton, GeneralUtils::UTF16ToWTF8(identifier));
}
for (auto* shootingGallery : EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::SHOOTING_GALLERY)) {

View File

@@ -279,7 +279,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "leave-zone") {
const auto currentZone = dZoneManager::Instance()->GetZone()->GetZoneID().GetMapID();
auto newZone = 0;
LWOMAPID newZone = 0;
if (currentZone % 100 == 0) {
ChatPackets::SendSystemMessage(sysAddr, u"You are not in an instanced zone.");
return;
@@ -287,7 +287,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
newZone = (currentZone / 100) * 100;
}
// If new zone would be inaccessible, then default to Avant Gardens.
if (!CheckIfAccessibleZone(newZone)) newZone = 1100;
if (!dZoneManager::Instance()->CheckIfAccessibleZone(newZone)) newZone = 1100;
ChatPackets::SendSystemMessage(sysAddr, u"Leaving zone...");
@@ -1559,7 +1559,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
const auto objid = entity->GetObjectID();
if (force || CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery
if (force || dZoneManager::Instance()->CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, reqZone, cloneId, false, [objid](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
@@ -2021,17 +2021,6 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
}
}
bool SlashCommandHandler::CheckIfAccessibleZone(const unsigned int zoneID) {
//We're gonna go ahead and presume we've got the db loaded already:
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
const CDZoneTable* zone = zoneTable->Query(zoneID);
if (zone != nullptr) {
return Game::assetManager->HasFile(("maps/" + zone->zoneName).c_str());
} else {
return false;
}
}
void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::string& message) {
AMFArrayValue args;
auto* titleValue = new AMFStringValue();

View File

@@ -13,8 +13,6 @@ class Entity;
namespace SlashCommandHandler {
void HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr);
bool CheckIfAccessibleZone(const unsigned int zoneID);
void SendAnnouncement(const std::string& title, const std::string& message);
};

View File

@@ -46,9 +46,7 @@ void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* pack
return;
}
CINSTREAM;
uint64_t header;
inStream.Read(header);
CINSTREAM_SKIP_HEADER;
char chatChannel;
uint16_t unknown;
@@ -82,9 +80,7 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac
return;
}
CINSTREAM;
uint64_t header;
inStream.Read(header);
CINSTREAM_SKIP_HEADER;
Entity* entity = EntityManager::Instance()->GetEntity(user->GetLastUsedChar()->GetObjectID());
if (!entity) return;

View File

@@ -275,6 +275,11 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
toSpawn.spawnPaths.at(pathIndex)
);
if (!path) {
Game::logger->Log("SGCannon", "Path %s at index %i is null", toSpawn.spawnPaths.at(pathIndex).c_str(), pathIndex);
return;
}
auto info = EntityInfo{};
info.lot = toSpawn.lot;
info.spawnerID = self->GetObjectID();
@@ -294,32 +299,30 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self);
EntityManager::Instance()->ConstructEntity(enemy);
if (true) {
auto* movementAI = new MovementAIComponent(enemy, {});
auto* movementAI = new MovementAIComponent(enemy, {});
enemy->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAI);
enemy->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAI);
movementAI->SetSpeed(toSpawn.initialSpeed);
movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
movementAI->SetHaltDistance(0.0f);
movementAI->SetSpeed(toSpawn.initialSpeed);
movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
movementAI->SetHaltDistance(0.0f);
std::vector<NiPoint3> pathWaypoints;
std::vector<NiPoint3> pathWaypoints;
for (const auto& waypoint : path->pathWaypoints) {
pathWaypoints.push_back(waypoint.position);
}
if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) {
std::reverse(pathWaypoints.begin(), pathWaypoints.end());
}
movementAI->SetPath(pathWaypoints);
enemy->AddDieCallback([this, self, enemy, name]() {
RegisterHit(self, enemy, name);
});
for (const auto& waypoint : path->pathWaypoints) {
pathWaypoints.push_back(waypoint.position);
}
if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) {
std::reverse(pathWaypoints.begin(), pathWaypoints.end());
}
movementAI->SetPath(pathWaypoints);
enemy->AddDieCallback([this, self, enemy, name]() {
RegisterHit(self, enemy, name);
});
// Save the enemy and tell it to start pathing
if (enemy != nullptr) {
const_cast<std::vector<LWOOBJID>&>(self->GetVar<std::vector<LWOOBJID>>(SpawnedObjects)).push_back(enemy->GetObjectID());
@@ -577,7 +580,7 @@ void SGCannon::StopGame(Entity* self, bool cancel) {
self->SetNetworkVar<std::u16string>(u"UI_Rewards",
GeneralUtils::to_u16string(self->GetVar<uint32_t>(TotalScoreVariable)) + u"_0_0_0_0_0_0"
);
);
GameMessages::SendRequestActivitySummaryLeaderboardData(
player->GetObjectID(),

View File

@@ -554,10 +554,9 @@ void HandlePacketChat(Packet* packet) {
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
case eChatInternalMessageType::ROUTE_TO_PLAYER: {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
inStream.Read(playerID);
auto player = EntityManager::Instance()->GetEntity(playerID);
if (!player) return;
@@ -576,9 +575,7 @@ void HandlePacketChat(Packet* packet) {
}
case eChatInternalMessageType::ANNOUNCEMENT: {
CINSTREAM;
LWOOBJID header;
inStream.Read(header);
CINSTREAM_SKIP_HEADER;
std::string title;
std::string msg;
@@ -615,11 +612,10 @@ void HandlePacketChat(Packet* packet) {
}
case eChatInternalMessageType::MUTE_UPDATE: {
CINSTREAM;
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
time_t expire = 0;
inStream.Read(playerId);
inStream.Read(playerId);
inStream.Read(expire);
auto* entity = EntityManager::Instance()->GetEntity(playerId);
@@ -634,9 +630,7 @@ void HandlePacketChat(Packet* packet) {
}
case eChatInternalMessageType::TEAM_UPDATE: {
CINSTREAM;
LWOOBJID header;
inStream.Read(header);
CINSTREAM_SKIP_HEADER;
LWOOBJID teamID = 0;
char lootOption = 0;
@@ -1213,10 +1207,8 @@ void HandlePacket(Packet* packet) {
case eWorldMessageType::ROUTE_PACKET: {
//Yeet to chat
CINSTREAM;
uint64_t header = 0;
CINSTREAM_SKIP_HEADER;
uint32_t size = 0;
inStream.Read(header);
inStream.Read(size);
if (size > 20000) {

View File

@@ -12,6 +12,8 @@
#include "CDZoneTableTable.h"
#include <chrono>
#include "eObjectBits.h"
#include "CDZoneTableTable.h"
#include "AssetManager.h"
#include "../dWorldServer/ObjectIDManager.h"
@@ -227,6 +229,17 @@ uint32_t dZoneManager::GetUniqueMissionIdStartingValue() {
return m_UniqueMissionIdStart;
}
bool dZoneManager::CheckIfAccessibleZone(LWOMAPID zoneID) {
//We're gonna go ahead and presume we've got the db loaded already:
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
const CDZoneTable* zone = zoneTable->Query(zoneID);
if (zone != nullptr) {
return Game::assetManager->HasFile(("maps/" + zone->zoneName).c_str());
} else {
return false;
}
}
void dZoneManager::LoadWorldConfig() {
Game::logger->Log("dZoneManager", "Loading WorldConfig into memory");

View File

@@ -50,6 +50,7 @@ public:
Entity* GetZoneControlObject() { return m_ZoneControlObject; }
bool GetPlayerLoseCoinOnDeath() { return m_PlayerLoseCoinsOnDeath; }
uint32_t GetUniqueMissionIdStartingValue();
bool CheckIfAccessibleZone(LWOMAPID zoneID);
// The world config should not be modified by a caller.
const WorldConfig* GetWorldConfig() {

View File

@@ -1,5 +1,6 @@
set(DCOMMONTEST_SOURCES
"AMFDeserializeTests.cpp"
"HeaderSkipTest.cpp"
"TestLDFFormat.cpp"
"TestNiPoint3.cpp"
"TestEncoding.cpp"

View File

@@ -0,0 +1,37 @@
#include <gtest/gtest.h>
#include "dCommonDependencies.h"
#include "dCommonVars.h"
#include "BitStream.h"
#define PacketUniquePtr std::unique_ptr<Packet>
TEST(dCommonTests, HeaderSkipExcessTest) {
PacketUniquePtr packet = std::make_unique<Packet>();
unsigned char headerAndData[] = { 0x53, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 }; // positive
packet->data = headerAndData;
packet->length = sizeof(headerAndData);
CINSTREAM_SKIP_HEADER;
ASSERT_EQ(inStream.GetNumberOfUnreadBits(), 64);
ASSERT_EQ(inStream.GetNumberOfBitsAllocated(), 128);
}
TEST(dCommonTests, HeaderSkipExactDataTest) {
PacketUniquePtr packet = std::make_unique<Packet>();
unsigned char header[] = { 0x53, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00 }; // positive
packet->data = header;
packet->length = sizeof(header);
CINSTREAM_SKIP_HEADER;
ASSERT_EQ(inStream.GetNumberOfUnreadBits(), 0);
ASSERT_EQ(inStream.GetNumberOfBitsAllocated(), 64);
}
TEST(dCommonTests, HeaderSkipNotEnoughDataTest) {
PacketUniquePtr packet = std::make_unique<Packet>();
unsigned char notEnoughData[] = { 0x53, 0x02, 0x00, 0x07, 0x00, 0x00 }; // negative
packet->data = notEnoughData;
packet->length = sizeof(notEnoughData);
CINSTREAM_SKIP_HEADER;
ASSERT_EQ(inStream.GetNumberOfUnreadBits(), 0);
ASSERT_EQ(inStream.GetNumberOfBitsAllocated(), 48);
}