Compare commits

...

14 Commits

Author SHA1 Message Date
David Markowitz
d77657782e Merge remote-tracking branch 'upstream/main' into speed 2023-12-17 21:32:49 -08:00
jadebenn
e2391665b9 imagination costs that equal your capacity no longer abort qbs (#1338) 2023-12-16 19:35:16 -06:00
David Markowitz
24c2361248 fix: achievements counting twice when accepted (#1337)
Tested that new achievements progress exactly once
Tested that already accepted achievements progress as expeected
Tested that tiered achievements only count the progress to the current tier and not the next one as well

Update MissionComponent.cpp
2023-12-16 12:27:14 -06:00
David Markowitz
511672c5cb fix: general crashes (#1336)
* Fix crashes

fix crash with chat filter
fix ldf_config being empty in database on windows debug

* WorldServer: Fix further crashes on windows

address multi threaded signal handling on worldservers
Remove iterator invalidation code in zone manager
2023-12-16 12:27:06 -06:00
Gie "Max" Vanommeslaeghe
c0b969e3f0 Merge pull request #1333 from DarkflameUniverse/chore-rename-zonecontrol-to-minigamecontrol
chore: rename zonecontrolcomp to minigamecontrolcomp
2023-12-06 14:39:21 +01:00
1f399a7277 chore: rename zonecontrolcomp to minigamecontrolcomp 2023-12-04 20:59:08 -06:00
David Markowitz
c3fee5a339 Update Level.cpp 2023-11-21 18:18:08 -08:00
David Markowitz
f820324282 Merge branch 'main' into speed 2023-11-21 18:16:03 -08:00
9314b6a562 dlu is moving to bitbucket again 2023-11-22 01:51:49 +00:00
David Markowitz
3f9d1a18f0 Update Zone.cpp 2023-11-21 17:49:55 -08:00
1ea65b3549 gaming 2023-11-22 01:40:09 +00:00
David Markowitz
f8a01dead3 Remove extraneous compare function
std::less<LWOSCENEID> already does this in a map.
2023-11-21 01:22:54 -08:00
David Markowitz
d8476b7325 working
End of optimizations for now

going faster
2023-11-21 01:10:06 -08:00
David Markowitz
2a40e37b07 Remove std::couts littered throughout the base 2023-11-20 05:55:07 -08:00
37 changed files with 324 additions and 550 deletions

View File

@@ -1,14 +1,6 @@
#include "BinaryIO.h" #include "BinaryIO.h"
#include <string> #include <string>
void BinaryIO::WriteString(const std::string& stringToWrite, std::ofstream& outstream) {
//BinaryWrite(outstream, uint32_t(stringToWrite.length()));
for (size_t i = 0; i < size_t(stringToWrite.length()); ++i) {
BinaryIO::BinaryWrite(outstream, stringToWrite[i]);
}
}
//For reading null-terminated strings //For reading null-terminated strings
std::string BinaryIO::ReadString(std::istream& instream) { std::string BinaryIO::ReadString(std::istream& instream) {
std::string toReturn; std::string toReturn;
@@ -23,36 +15,3 @@ std::string BinaryIO::ReadString(std::istream& instream) {
return toReturn; return toReturn;
} }
//For reading strings of a specific size
std::string BinaryIO::ReadString(std::istream& instream, size_t size) {
std::string toReturn;
char buffer;
for (size_t i = 0; i < size; ++i) {
BinaryIO::BinaryRead(instream, buffer);
toReturn += buffer;
}
return toReturn;
}
std::string BinaryIO::ReadWString(std::istream& instream) {
size_t size;
BinaryRead(instream, size);
//toReturn.resize(size);
std::string test;
unsigned char buf;
for (size_t i = 0; i < size; ++i) {
//instream.ignore(1);
BinaryRead(instream, buf);
test += buf;
}
//printf("%s\n", test.c_str());
//instream.read((char*)&toReturn[0], size * 2);
//std::string str(toReturn.begin(), toReturn.end());
return test;
}

View File

@@ -1,8 +1,17 @@
#pragma once #pragma once
#ifndef __BINARYIO__H__
#define __BINARYIO__H__
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string>
#include "Game.h"
#include "Logger.h"
namespace BinaryIO { namespace BinaryIO {
template<typename T> template<typename T>
std::ostream& BinaryWrite(std::ostream& stream, const T& value) { std::ostream& BinaryWrite(std::ostream& stream, const T& value) {
return stream.write(reinterpret_cast<const char*>(&value), sizeof(T)); return stream.write(reinterpret_cast<const char*>(&value), sizeof(T));
@@ -15,13 +24,51 @@ namespace BinaryIO {
return stream.read(reinterpret_cast<char*>(&value), sizeof(T)); return stream.read(reinterpret_cast<char*>(&value), sizeof(T));
} }
void WriteString(const std::string& stringToWrite, std::ofstream& outstream); enum class ReadType : int8_t {
WideString = 0,
String = 1,
};
template<typename SizeType>
inline void ReadString(std::istream& stream, std::u16string& value) {
static_assert(std::is_integral<SizeType>::value, "SizeType must be an integral type.");
SizeType size;
BinaryRead(stream, size);
if (!stream.good()) throw std::runtime_error("Failed to read from istream.");
value.resize(size);
stream.read(reinterpret_cast<char*>(value.data()), size * sizeof(uint16_t));
}
template<typename SizeType>
inline void ReadString(std::istream& stream, std::string& value, ReadType readType) {
static_assert(std::is_integral<SizeType>::value, "SizeType must be an integral type.");
SizeType size;
BinaryRead(stream, size);
if (!stream.good()) throw std::runtime_error("Failed to read from istream.");
value.resize(size);
if (readType == ReadType::WideString) {
uint16_t wideChar;
// Faster to do this than to read a u16string and convert it to a string since we only go through allocator once
for (SizeType i = 0; i < size; ++i) {
BinaryRead(stream, wideChar);
value[i] = static_cast<char>(wideChar);
}
} else {
stream.read(value.data(), size);
}
}
std::string ReadString(std::istream& instream); std::string ReadString(std::istream& instream);
std::string ReadString(std::istream& instream, size_t size);
std::string ReadWString(std::istream& instream);
inline bool DoesFileExist(const std::string& name) { inline bool DoesFileExist(const std::string& name) {
std::ifstream f(name.c_str()); std::ifstream f(name.c_str());
return f.good(); return f.good();
} }
} }
#endif //!__BINARYIO__H__

View File

@@ -28,19 +28,17 @@ FdbToSqlite::Convert::Convert(std::string binaryOutPath) {
this->m_BinaryOutPath = binaryOutPath; this->m_BinaryOutPath = binaryOutPath;
} }
bool FdbToSqlite::Convert::ConvertDatabase(AssetMemoryBuffer& buffer) { bool FdbToSqlite::Convert::ConvertDatabase(AssetStream& buffer) {
if (m_ConversionStarted) return false; if (m_ConversionStarted) return false;
std::istream cdClientBuffer(&buffer);
this->m_ConversionStarted = true; this->m_ConversionStarted = true;
try { try {
CDClientDatabase::Connect(m_BinaryOutPath + "/CDServer.sqlite"); CDClientDatabase::Connect(m_BinaryOutPath + "/CDServer.sqlite");
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;"); CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
int32_t numberOfTables = ReadInt32(cdClientBuffer); int32_t numberOfTables = ReadInt32(buffer);
ReadTables(numberOfTables, cdClientBuffer); ReadTables(numberOfTables, buffer);
CDClientDatabase::ExecuteQuery("COMMIT;"); CDClientDatabase::ExecuteQuery("COMMIT;");
} catch (CppSQLite3Exception& e) { } catch (CppSQLite3Exception& e) {

View File

@@ -7,7 +7,7 @@
#include <iosfwd> #include <iosfwd>
#include <map> #include <map>
class AssetMemoryBuffer; #include "AssetManager.h"
enum class eSqliteDataType : int32_t; enum class eSqliteDataType : int32_t;
@@ -27,7 +27,7 @@ namespace FdbToSqlite {
* *
* @return true if the database was converted properly, false otherwise. * @return true if the database was converted properly, false otherwise.
*/ */
bool ConvertDatabase(AssetMemoryBuffer& buffer); bool ConvertDatabase(AssetStream& buffer);
/** /**
* @brief Reads a 32 bit int from the fdb file. * @brief Reads a 32 bit int from the fdb file.

View File

@@ -152,13 +152,12 @@ bool AssetManager::GetFile(const char* name, char** data, uint32_t* len) {
return success; return success;
} }
AssetMemoryBuffer AssetManager::GetFileAsBuffer(const char* name) { AssetStream AssetManager::GetFile(const char* name) {
char* buf; char* buf; uint32_t len;
uint32_t len;
bool success = this->GetFile(name, &buf, &len); bool success = this->GetFile(name, &buf, &len);
return AssetMemoryBuffer(buf, len, success); return AssetStream(buf, len, success);
} }
uint32_t AssetManager::crc32b(uint32_t base, uint8_t* message, size_t l) { uint32_t AssetManager::crc32b(uint32_t base, uint8_t* message, size_t l) {

View File

@@ -25,6 +25,10 @@ struct AssetMemoryBuffer : std::streambuf {
this->setg(base, base, base + n); this->setg(base, base, base + n);
} }
~AssetMemoryBuffer() {
free(m_Base);
}
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override { pos_type seekpos(pos_type sp, std::ios_base::openmode which) override {
return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which); return seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
} }
@@ -40,9 +44,17 @@ struct AssetMemoryBuffer : std::streambuf {
setg(eback(), eback() + off, egptr()); setg(eback(), eback() + off, egptr());
return gptr() - eback(); return gptr() - eback();
} }
};
void close() { struct AssetStream : std::istream {
free(m_Base); AssetStream(char* base, std::ptrdiff_t n, bool success) : std::istream(new AssetMemoryBuffer(base, n, success)) {}
~AssetStream() {
delete rdbuf();
}
operator bool() {
return reinterpret_cast<AssetMemoryBuffer*>(rdbuf())->m_Success;
} }
}; };
@@ -56,7 +68,7 @@ public:
bool HasFile(const char* name); bool HasFile(const char* name);
bool GetFile(const char* name, char** data, uint32_t* len); bool GetFile(const char* name, char** data, uint32_t* len);
AssetMemoryBuffer GetFileAsBuffer(const char* name); AssetStream GetFile(const char* name);
private: private:
void LoadPackIndex(); void LoadPackIndex();

View File

@@ -8,21 +8,10 @@ PackIndex::PackIndex(const std::filesystem::path& filePath) {
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_Version); BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_Version);
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_PackPathCount); BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_PackPathCount);
for (int i = 0; i < m_PackPathCount; i++) { m_PackPaths.resize(m_PackPathCount);
uint32_t stringLen = 0; for (auto& item : m_PackPaths) {
BinaryIO::BinaryRead<uint32_t>(m_FileStream, stringLen); BinaryIO::ReadString<uint32_t>(m_FileStream, item, BinaryIO::ReadType::String);
std::string path;
for (int j = 0; j < stringLen; j++) {
char inChar;
BinaryIO::BinaryRead<char>(m_FileStream, inChar);
path += inChar;
}
m_PackPaths.push_back(path);
} }
BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_PackFileIndexCount); BinaryIO::BinaryRead<uint32_t>(m_FileStream, m_PackFileIndexCount);

View File

@@ -54,7 +54,7 @@ enum class eReplicaComponentType : uint32_t {
PHYSICS_SYSTEM, PHYSICS_SYSTEM,
QUICK_BUILD, QUICK_BUILD,
SWITCH, SWITCH,
ZONE_CONTROL, // Minigame MINI_GAME_CONTROL,
CHANGLING, CHANGLING,
CHOICE_BUILD, CHOICE_BUILD,
PACKAGE, PACKAGE,

View File

@@ -76,7 +76,7 @@
#include "eGameMasterLevel.h" #include "eGameMasterLevel.h"
#include "eReplicaComponentType.h" #include "eReplicaComponentType.h"
#include "eReplicaPacketType.h" #include "eReplicaPacketType.h"
#include "ZoneControlComponent.h" #include "MiniGameControlComponent.h"
#include "RacingStatsComponent.h" #include "RacingStatsComponent.h"
#include "CollectibleComponent.h" #include "CollectibleComponent.h"
#include "ItemComponent.h" #include "ItemComponent.h"
@@ -217,8 +217,8 @@ void Entity::Initialize() {
AddComponent<PetComponent>(petComponentId); AddComponent<PetComponent>(petComponentId);
} }
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ZONE_CONTROL) > 0) { if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL) > 0) {
AddComponent<ZoneControlComponent>(); AddComponent<MiniGameControlComponent>();
} }
uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE); uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
@@ -1197,9 +1197,9 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
} }
} }
ZoneControlComponent* zoneControlComponent; MiniGameControlComponent* miniGameControlComponent;
if (TryGetComponent(eReplicaComponentType::ZONE_CONTROL, zoneControlComponent)) { if (TryGetComponent(eReplicaComponentType::MINI_GAME_CONTROL, miniGameControlComponent)) {
zoneControlComponent->Serialize(outBitStream, bIsInitialUpdate); miniGameControlComponent->Serialize(outBitStream, bIsInitialUpdate);
} }
// BBB Component, unused currently // BBB Component, unused currently

View File

@@ -110,3 +110,7 @@ void User::UserOutOfSync() {
Game::server->Disconnect(this->m_SystemAddress, eServerDisconnectIdentifiers::PLAY_SCHEDULE_TIME_DONE); Game::server->Disconnect(this->m_SystemAddress, eServerDisconnectIdentifiers::PLAY_SCHEDULE_TIME_DONE);
} }
} }
void User::UpdateBestFriendValue(const std::string_view playerName, const bool newValue) {
m_IsBestFriendMap[playerName.data()] = newValue;
}

View File

@@ -43,8 +43,8 @@ public:
bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; } bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; }
void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; } void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; }
std::unordered_map<std::string, bool> GetIsBestFriendMap() { return m_IsBestFriendMap; } const std::unordered_map<std::string, bool>& GetIsBestFriendMap() { return m_IsBestFriendMap; }
void SetIsBestFriendMap(std::unordered_map<std::string, bool> mapToSet) { m_IsBestFriendMap = mapToSet; } void UpdateBestFriendValue(const std::string_view playerName, const bool newValue);
bool GetIsMuted() const; bool GetIsMuted() const;

View File

@@ -44,57 +44,53 @@ inline void StripCR(std::string& str) {
void UserManager::Initialize() { void UserManager::Initialize() {
std::string line; std::string line;
AssetMemoryBuffer fnBuff = Game::assetManager->GetFileAsBuffer("names/minifigname_first.txt"); auto fnStream = Game::assetManager->GetFile("names/minifigname_first.txt");
if (!fnBuff.m_Success) { if (!fnStream) {
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_first.txt").string().c_str()); LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_first.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing minifigure name file."); throw std::runtime_error("Aborting initialization due to missing minifigure name file.");
} }
std::istream fnStream = std::istream(&fnBuff);
while (std::getline(fnStream, line, '\n')) { while (std::getline(fnStream, line, '\n')) {
std::string name = line; std::string name = line;
StripCR(name); StripCR(name);
m_FirstNames.push_back(name); m_FirstNames.push_back(name);
} }
fnBuff.close();
AssetMemoryBuffer mnBuff = Game::assetManager->GetFileAsBuffer("names/minifigname_middle.txt"); auto mnStream = Game::assetManager->GetFile("names/minifigname_middle.txt");
if (!mnBuff.m_Success) { if (!mnStream) {
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_middle.txt").string().c_str()); LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_middle.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing minifigure name file."); throw std::runtime_error("Aborting initialization due to missing minifigure name file.");
} }
std::istream mnStream = std::istream(&mnBuff);
while (std::getline(mnStream, line, '\n')) { while (std::getline(mnStream, line, '\n')) {
std::string name = line; std::string name = line;
StripCR(name); StripCR(name);
m_MiddleNames.push_back(name); m_MiddleNames.push_back(name);
} }
mnBuff.close();
AssetMemoryBuffer lnBuff = Game::assetManager->GetFileAsBuffer("names/minifigname_last.txt"); auto lnStream = Game::assetManager->GetFile("names/minifigname_last.txt");
if (!lnBuff.m_Success) { if (!lnStream) {
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_last.txt").string().c_str()); LOG("Failed to load %s", (Game::assetManager->GetResPath() / "names/minifigname_last.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing minifigure name file."); throw std::runtime_error("Aborting initialization due to missing minifigure name file.");
} }
std::istream lnStream = std::istream(&lnBuff);
while (std::getline(lnStream, line, '\n')) { while (std::getline(lnStream, line, '\n')) {
std::string name = line; std::string name = line;
StripCR(name); StripCR(name);
m_LastNames.push_back(name); m_LastNames.push_back(name);
} }
lnBuff.close();
//Load our pre-approved names: // Load our pre-approved names:
AssetMemoryBuffer chatListBuff = Game::assetManager->GetFileAsBuffer("chatplus_en_us.txt"); auto chatListStream = Game::assetManager->GetFile("chatplus_en_us.txt");
if (!chatListBuff.m_Success) { if (!chatListStream) {
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "chatplus_en_us.txt").string().c_str()); LOG("Failed to load %s", (Game::assetManager->GetResPath() / "chatplus_en_us.txt").string().c_str());
throw std::runtime_error("Aborting initialization due to missing chat whitelist file."); throw std::runtime_error("Aborting initialization due to missing chat whitelist file.");
} }
std::istream chatListStream = std::istream(&chatListBuff);
while (std::getline(chatListStream, line, '\n')) { while (std::getline(chatListStream, line, '\n')) {
StripCR(line); StripCR(line);
m_PreapprovedNames.push_back(line); m_PreapprovedNames.push_back(line);
} }
chatListBuff.close();
} }
UserManager::~UserManager() { UserManager::~UserManager() {

View File

@@ -45,6 +45,6 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"TriggerComponent.cpp" "TriggerComponent.cpp"
"HavokVehiclePhysicsComponent.cpp" "HavokVehiclePhysicsComponent.cpp"
"VendorComponent.cpp" "VendorComponent.cpp"
"ZoneControlComponent.cpp" "MiniGameControlComponent.cpp"
PARENT_SCOPE PARENT_SCOPE
) )

View File

@@ -0,0 +1,5 @@
#include "MiniGameControlComponent.h"
void MiniGameControlComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
outBitStream->Write<uint32_t>(0x40000000);
}

View File

@@ -0,0 +1,15 @@
#ifndef __MINIGAMECONTROLCOMPONENT__H__
#define __MINIGAMECONTROLCOMPONENT__H__
#include "Component.h"
#include "eReplicaComponentType.h"
class MiniGameControlComponent final : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
MiniGameControlComponent(Entity* parent) : Component(parent) {}
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
};
#endif //!__MINIGAMECONTROLCOMPONENT__H__

View File

@@ -0,0 +1,5 @@
#include "MinigameComponent.h"
void MinigameComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
outBitStream->Write<uint32_t>(0x40000000);
}

View File

@@ -145,8 +145,13 @@ void MissionComponent::RemoveMission(uint32_t missionId) {
} }
void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) { void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
for (const auto& pair : m_Missions) { std::vector<uint32_t> acceptedAchievements;
auto* mission = pair.second; if (count > 0 && !ignoreAchievements) {
acceptedAchievements = LookForAchievements(type, value, true, associate, targets, count);
}
for (const auto& [id, mission] : m_Missions) {
if (!mission || std::find(acceptedAchievements.begin(), acceptedAchievements.end(), mission->GetMissionId()) != acceptedAchievements.end()) continue;
if (mission->IsAchievement() && ignoreAchievements) continue; if (mission->IsAchievement() && ignoreAchievements) continue;
@@ -154,10 +159,6 @@ void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID a
mission->Progress(type, value, associate, targets, count); mission->Progress(type, value, associate, targets, count);
} }
if (count > 0 && !ignoreAchievements) {
LookForAchievements(type, value, true, associate, targets, count);
}
} }
void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) { void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) {
@@ -282,12 +283,12 @@ bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) {
#define MISSION_NEW_METHOD #define MISSION_NEW_METHOD
bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) { const std::vector<uint32_t> MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) {
#ifdef MISSION_NEW_METHOD #ifdef MISSION_NEW_METHOD
// Query for achievments, using the cache // Query for achievments, using the cache
const auto& result = QueryAchievements(type, value, targets); const auto& result = QueryAchievements(type, value, targets);
bool any = false; std::vector<uint32_t> acceptedAchievements;
for (const uint32_t missionID : result) { for (const uint32_t missionID : result) {
// Check if we already have this achievement // Check if we already have this achievement
@@ -309,7 +310,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
instance->Accept(); instance->Accept();
any = true; acceptedAchievements.push_back(missionID);
if (progress) { if (progress) {
// Progress mission to bring it up to speed // Progress mission to bring it up to speed
@@ -317,7 +318,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
} }
} }
return any; return acceptedAchievements;
#else #else
auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>(); auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>();
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>(); auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
@@ -326,7 +327,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
return entry.taskType == static_cast<unsigned>(type); return entry.taskType == static_cast<unsigned>(type);
}); });
auto any = false; std::vector<uint32_t> acceptedAchievements;
for (const auto& task : tasks) { for (const auto& task : tasks) {
if (GetMission(task.id) != nullptr) { if (GetMission(task.id) != nullptr) {
@@ -380,14 +381,14 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
instance->Accept(); instance->Accept();
any = true; acceptedAchievements.push_back(mission.id);
if (progress) { if (progress) {
instance->Progress(type, value, associate, targets, count); instance->Progress(type, value, associate, targets, count);
} }
} }
return any; return acceptedAchievements;
#endif #endif
} }
@@ -499,7 +500,7 @@ bool MissionComponent::RequiresItem(const LOT lot) {
const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false); const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false);
return required; return !required.empty();
} }

View File

@@ -141,7 +141,7 @@ public:
* @param count the number of values to progress by (differs by task type) * @param count the number of values to progress by (differs by task type)
* @return true if a achievement was accepted, false otherwise * @return true if a achievement was accepted, false otherwise
*/ */
bool LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1); const std::vector<uint32_t> LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1);
/** /**
* Checks if there's a mission active that requires the collection of the specified LOT * Checks if there's a mission active that requires the collection of the specified LOT

View File

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

View File

@@ -285,7 +285,7 @@ private:
float m_CompleteTime = 0; float m_CompleteTime = 0;
/** /**
* The imagination that's deducted when compeleting the rebuild * The imagination that's deducted when completing the rebuild
*/ */
int m_TakeImagination = 0; int m_TakeImagination = 0;

View File

@@ -1,5 +0,0 @@
#include "ZoneControlComponent.h"
void ZoneControlComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
outBitStream->Write<uint32_t>(0x40000000);
}

View File

@@ -1,15 +0,0 @@
#ifndef __ZONECONTROLCOMPONENT__H__
#define __ZONECONTROLCOMPONENT__H__
#include "Component.h"
#include "eReplicaComponentType.h"
class ZoneControlComponent final : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ZONE_CONTROL;
ZoneControlComponent(Entity* parent) : Component(parent) {}
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
};
#endif //!__ZONECONTROLCOMPONENT__H__

View File

@@ -5578,7 +5578,7 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity*
std::unique_ptr<sql::PreparedStatement> stmt(Database::Get()->CreatePreppedStmt("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)")); std::unique_ptr<sql::PreparedStatement> stmt(Database::Get()->CreatePreppedStmt("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)"));
stmt->setUInt64(1, newIdBig); stmt->setUInt64(1, newIdBig);
stmt->setString(2, GeneralUtils::UTF16ToWTF8(modules)); stmt->setString(2, GeneralUtils::UTF16ToWTF8(modules).c_str());
auto* pCharacter = character->GetCharacter(); auto* pCharacter = character->GetCharacter();
pCharacter ? stmt->setUInt(3, pCharacter->GetID()) : stmt->setNull(3, sql::DataType::BIGINT); pCharacter ? stmt->setUInt(3, pCharacter->GetID()) : stmt->setNull(3, sql::DataType::BIGINT);
stmt->execute(); stmt->execute();

View File

@@ -423,25 +423,16 @@ void Item::DisassembleModel(uint32_t numToDismantle) {
if (renderAssetSplit.empty()) return; if (renderAssetSplit.empty()) return;
std::string lxfmlPath = "BrickModels" + lxfmlFolderName + "/" + GeneralUtils::SplitString(renderAssetSplit.back(), '.').at(0) + ".lxfml"; std::string lxfmlPath = "BrickModels" + lxfmlFolderName + "/" + GeneralUtils::SplitString(renderAssetSplit.back(), '.').at(0) + ".lxfml";
auto buffer = Game::assetManager->GetFileAsBuffer(lxfmlPath.c_str()); auto file = Game::assetManager->GetFile(lxfmlPath.c_str());
if (!buffer.m_Success) { if (!file) {
LOG("Failed to load %s to disassemble model into bricks, check that this file exists", lxfmlPath.c_str()); LOG("Failed to load %s to disassemble model into bricks, check that this file exists", lxfmlPath.c_str());
return; return;
} }
std::istream file(&buffer);
if (!file.good()) {
buffer.close();
return;
}
std::stringstream data; std::stringstream data;
data << file.rdbuf(); data << file.rdbuf();
buffer.close();
uint32_t fileSize; uint32_t fileSize;
file.seekg(0, std::ios::end); file.seekg(0, std::ios::end);
fileSize = static_cast<uint32_t>(file.tellg()); fileSize = static_cast<uint32_t>(file.tellg());

View File

@@ -324,14 +324,9 @@ void ControlBehaviors::ProcessCommand(Entity* modelEntity, const SystemAddress&
} }
ControlBehaviors::ControlBehaviors() { ControlBehaviors::ControlBehaviors() {
auto blocksDefStreamBuffer = Game::assetManager->GetFileAsBuffer("ui\\ingame\\blocksdef.xml"); auto blocksBuffer = Game::assetManager->GetFile("ui\\ingame\\blocksdef.xml");
if (!blocksDefStreamBuffer.m_Success) { if (!blocksBuffer) {
LOG("failed to open blocksdef"); LOG("Failed to open blocksdef.xml");
return;
}
std::istream blocksBuffer(&blocksDefStreamBuffer);
if (!blocksBuffer.good()) {
LOG("Blocks buffer is not good!");
return; return;
} }
@@ -342,7 +337,7 @@ ControlBehaviors::ControlBehaviors() {
std::string buffer{}; std::string buffer{};
bool commentBlockStart = false; bool commentBlockStart = false;
while (std::getline(blocksBuffer, read)) { while (std::getline(blocksBuffer, read)) {
// tinyxml2 should handle comment blocks but the client has one that fails the processing. // tinyxml2 should handle comment blocks but the client has one that fails the processing.
// This preprocessing just removes all comments from the read file out of an abundance of caution. // This preprocessing just removes all comments from the read file out of an abundance of caution.
if (read.find("<!--") != std::string::npos) { if (read.find("<!--") != std::string::npos) {
commentBlockStart = true; commentBlockStart = true;

View File

@@ -17,26 +17,18 @@ const BrickList& BrickDatabase::GetBricks(const LxfmlPath& lxfmlPath) {
return cached->second; return cached->second;
} }
AssetMemoryBuffer buffer = Game::assetManager->GetFileAsBuffer((lxfmlPath).c_str()); auto file = Game::assetManager->GetFile((lxfmlPath).c_str());
if (!buffer.m_Success) { if (!file) {
return emptyCache;
}
std::istream file(&buffer);
if (!file.good()) {
return emptyCache; return emptyCache;
} }
std::stringstream data; std::stringstream data;
data << file.rdbuf(); data << file.rdbuf();
if (data.str().empty()) { if (data.str().empty()) {
buffer.close();
return emptyCache; return emptyCache;
} }
buffer.close();
auto* doc = new tinyxml2::XMLDocument(); auto* doc = new tinyxml2::XMLDocument();
if (doc->Parse(data.str().c_str(), data.str().size()) != 0) { if (doc->Parse(data.str().c_str(), data.str().size()) != 0) {
delete doc; delete doc;

View File

@@ -608,15 +608,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (args[0].find("/") != std::string::npos) return; if (args[0].find("/") != std::string::npos) return;
if (args[0].find("\\") != std::string::npos) return; if (args[0].find("\\") != std::string::npos) return;
auto buf = Game::assetManager->GetFileAsBuffer(("macros/" + args[0] + ".scm").c_str()); auto infile = Game::assetManager->GetFile(("macros/" + args[0] + ".scm").c_str());
if (!buf.m_Success) { if (!infile) {
ChatPackets::SendSystemMessage(sysAddr, u"Unknown macro! Is the filename right?"); ChatPackets::SendSystemMessage(sysAddr, u"Unknown macro! Is the filename right?");
return; return;
} }
std::istream infile(&buf);
if (infile.good()) { if (infile.good()) {
std::string line; std::string line;
while (std::getline(infile, line)) { while (std::getline(infile, line)) {
@@ -626,8 +624,6 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
ChatPackets::SendSystemMessage(sysAddr, u"Unknown macro! Is the filename right?"); ChatPackets::SendSystemMessage(sysAddr, u"Unknown macro! Is the filename right?");
} }
buf.close();
return; return;
} }

View File

@@ -169,8 +169,8 @@ int main(int argc, char** argv) {
(BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite").c_str(), (BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite").c_str(),
(Game::assetManager->GetResPath() / "cdclient.fdb").c_str()); (Game::assetManager->GetResPath() / "cdclient.fdb").c_str());
AssetMemoryBuffer cdClientBuffer = Game::assetManager->GetFileAsBuffer("cdclient.fdb"); auto cdclientStream = Game::assetManager->GetFile("cdclient.fdb");
if (!cdClientBuffer.m_Success) { if (!cdclientStream) {
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "cdclient.fdb").c_str()); LOG("Failed to load %s", (Game::assetManager->GetResPath() / "cdclient.fdb").c_str());
throw std::runtime_error("Aborting initialization due to missing cdclient.fdb."); throw std::runtime_error("Aborting initialization due to missing cdclient.fdb.");
} }
@@ -178,11 +178,10 @@ int main(int argc, char** argv) {
LOG("Found %s. Converting to SQLite", (Game::assetManager->GetResPath() / "cdclient.fdb").c_str()); LOG("Found %s. Converting to SQLite", (Game::assetManager->GetResPath() / "cdclient.fdb").c_str());
Game::logger->Flush(); Game::logger->Flush();
if (FdbToSqlite::Convert((BinaryPathFinder::GetBinaryDir() / "resServer").string()).ConvertDatabase(cdClientBuffer) == false) { if (FdbToSqlite::Convert((BinaryPathFinder::GetBinaryDir() / "resServer").string()).ConvertDatabase(cdclientStream) == false) {
LOG("Failed to convert fdb to sqlite."); LOG("Failed to convert fdb to sqlite.");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
cdClientBuffer.close();
} }
} }

View File

@@ -359,8 +359,8 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
idOfReceiver = characterIdFetch->id; idOfReceiver = characterIdFetch->id;
} }
} }
const auto& bffMap = user->GetIsBestFriendMap();
if (user->GetIsBestFriendMap().find(receiver) == user->GetIsBestFriendMap().end() && idOfReceiver != LWOOBJID_EMPTY) { if (bffMap.find(receiver) == bffMap.end() && idOfReceiver != LWOOBJID_EMPTY) {
auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver); auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver);
if (bffInfo) { if (bffInfo) {
@@ -368,11 +368,9 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
} }
if (isBestFriend) { if (isBestFriend) {
auto tmpBestFriendMap = user->GetIsBestFriendMap(); user->UpdateBestFriendValue(receiver, true);
tmpBestFriendMap[receiver] = true;
user->SetIsBestFriendMap(tmpBestFriendMap);
} }
} else if (user->GetIsBestFriendMap().find(receiver) != user->GetIsBestFriendMap().end()) { } else if (bffMap.find(receiver) != bffMap.end()) {
isBestFriend = true; isBestFriend = true;
} }
} }

View File

@@ -18,6 +18,7 @@
#include "PerformanceManager.h" #include "PerformanceManager.h"
#include "Diagnostics.h" #include "Diagnostics.h"
#include "BinaryPathFinder.h" #include "BinaryPathFinder.h"
#include "dPlatforms.h"
//RakNet includes: //RakNet includes:
#include "RakNetDefines.h" #include "RakNetDefines.h"
@@ -1284,12 +1285,14 @@ void WorldShutdownProcess(uint32_t zoneId) {
} }
void WorldShutdownSequence() { void WorldShutdownSequence() {
if (Game::shouldShutdown || worldShutdownSequenceComplete) { Game::shouldShutdown = true;
#ifndef DARKFLAME_PLATFORM_WIN32
if (Game::shouldShutdown || worldShutdownSequenceComplete)
#endif
{
return; return;
} }
Game::shouldShutdown = true;
LOG("Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID); LOG("Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID);
WorldShutdownProcess(Game::server->GetZoneID()); WorldShutdownProcess(Game::server->GetZoneID());
FinalizeShutdown(); FinalizeShutdown();
@@ -1302,11 +1305,17 @@ void FinalizeShutdown() {
Metrics::Clear(); Metrics::Clear();
Database::Destroy("WorldServer"); Database::Destroy("WorldServer");
if (Game::chatFilter) delete Game::chatFilter; if (Game::chatFilter) delete Game::chatFilter;
Game::chatFilter = nullptr;
if (Game::zoneManager) delete Game::zoneManager; if (Game::zoneManager) delete Game::zoneManager;
Game::zoneManager = nullptr;
if (Game::server) delete Game::server; if (Game::server) delete Game::server;
Game::server = nullptr;
if (Game::config) delete Game::config; if (Game::config) delete Game::config;
Game::config = nullptr;
if (Game::entityManager) delete Game::entityManager; if (Game::entityManager) delete Game::entityManager;
Game::entityManager = nullptr;
if (Game::logger) delete Game::logger; if (Game::logger) delete Game::logger;
Game::logger = nullptr;
worldShutdownSequenceComplete = true; worldShutdownSequenceComplete = true;

View File

@@ -16,36 +16,20 @@
#include "AssetManager.h" #include "AssetManager.h"
#include "dConfig.h" #include "dConfig.h"
void Level::SceneObjectDataChunk::PrintAllObjects() const {
for (const auto& [id, sceneObj] : objects) {
LOG("ID: %d LOT: %d", id, sceneObj.lot);
}
}
Level::Level(Zone* parentZone, const std::string& filepath) { Level::Level(Zone* parentZone, const std::string& filepath) {
m_ParentZone = parentZone; m_ParentZone = parentZone;
auto buffer = Game::assetManager->GetFileAsBuffer(filepath.c_str()); auto stream = Game::assetManager->GetFile(filepath.c_str());
if (!buffer.m_Success) { if (!stream) {
LOG("Failed to load %s", filepath.c_str()); LOG("Failed to load %s", filepath.c_str());
return; return;
} }
std::istream file(&buffer); ReadChunks(stream);
ReadChunks(file);
buffer.close();
} }
Level::~Level() { void Level::MakeSpawner(SceneObject obj) {
for (auto& [id, header] : m_ChunkHeaders) {
if (header.id == Level::ChunkTypeID::FileInfo) delete header.fileInfo;
if (header.id == Level::ChunkTypeID::SceneObjectData) delete header.sceneObjects;
}
}
void Level::MakeSpawner(SceneObject obj){
SpawnerInfo spawnInfo = SpawnerInfo(); SpawnerInfo spawnInfo = SpawnerInfo();
SpawnerNode* node = new SpawnerNode(); SpawnerNode* node = new SpawnerNode();
spawnInfo.templateID = obj.lot; spawnInfo.templateID = obj.lot;
@@ -56,7 +40,7 @@ void Level::MakeSpawner(SceneObject obj){
node->config = obj.settings; node->config = obj.settings;
spawnInfo.nodes.push_back(node); spawnInfo.nodes.push_back(node);
for (LDFBaseData* data : obj.settings) { for (LDFBaseData* data : obj.settings) {
if (data) { if (!data) continue;
if (data->GetKey() == u"spawntemplate") { if (data->GetKey() == u"spawntemplate") {
spawnInfo.templateID = std::stoi(data->GetValueAsString()); spawnInfo.templateID = std::stoi(data->GetValueAsString());
} }
@@ -111,16 +95,8 @@ void Level::MakeSpawner(SceneObject obj){
spawnInfo.spawnActivator = static_cast<LDFData<bool>*>(data)->GetValue(); spawnInfo.spawnActivator = static_cast<LDFData<bool>*>(data)->GetValue();
} }
} }
}
Game::zoneManager->MakeSpawner(spawnInfo);
}
const void Level::PrintAllObjects() { Game::zoneManager->MakeSpawner(spawnInfo);
for (std::map<uint32_t, Header>::iterator it = m_ChunkHeaders.begin(); it != m_ChunkHeaders.end(); ++it) {
if (it->second.id == Level::ChunkTypeID::SceneObjectData) {
it->second.sceneObjects->PrintAllObjects();
}
}
} }
void Level::ReadChunks(std::istream& file) { void Level::ReadChunks(std::istream& file) {
@@ -155,11 +131,10 @@ void Level::ReadChunks(std::istream& file) {
file.seekg(0); file.seekg(0);
Header header; Header header;
header.id = ChunkTypeID::FileInfo; //I guess? header.id = ChunkTypeID::FileInfo; //I guess?
FileInfoChunk* fileInfo = new FileInfoChunk();
BinaryIO::BinaryRead(file, header.chunkVersion); BinaryIO::BinaryRead(file, header.chunkVersion);
BinaryIO::BinaryRead(file, header.chunkType); BinaryIO::BinaryRead(file, header.chunkType);
file.ignore(1); file.ignore(1);
BinaryIO::BinaryRead(file, fileInfo->revision); BinaryIO::BinaryRead(file, header.fileInfo.revision);
if (header.chunkVersion >= 45) file.ignore(4); if (header.chunkVersion >= 45) file.ignore(4);
file.ignore(4 * (4 * 3)); file.ignore(4 * (4 * 3));
@@ -172,9 +147,7 @@ void Level::ReadChunks(std::istream& file) {
uint32_t s = 0; uint32_t s = 0;
BinaryIO::BinaryRead(file, s); BinaryIO::BinaryRead(file, s);
for (uint32_t i = 0; i < s; ++i) { for (uint32_t i = 0; i < s; ++i) {
file.ignore(4); //a uint file.ignore(4 * 3); //a uint and two floats
file.ignore(4); //two floats
file.ignore(4);
} }
} }
} else { } else {
@@ -208,7 +181,6 @@ void Level::ReadChunks(std::istream& file) {
BinaryIO::BinaryRead(file, count); BinaryIO::BinaryRead(file, count);
file.ignore(count * 12); file.ignore(count * 12);
header.fileInfo = fileInfo;
m_ChunkHeaders.insert(std::make_pair(header.id, header)); m_ChunkHeaders.insert(std::make_pair(header.id, header));
//Now pretend to be a normal file and read Objects chunk: //Now pretend to be a normal file and read Objects chunk:
@@ -222,20 +194,17 @@ void Level::ReadChunks(std::istream& file) {
} }
void Level::ReadFileInfoChunk(std::istream& file, Header& header) { void Level::ReadFileInfoChunk(std::istream& file, Header& header) {
FileInfoChunk* fi = new FileInfoChunk; BinaryIO::BinaryRead(file, header.fileInfo.version);
BinaryIO::BinaryRead(file, fi->version); BinaryIO::BinaryRead(file, header.fileInfo.revision);
BinaryIO::BinaryRead(file, fi->revision); BinaryIO::BinaryRead(file, header.fileInfo.enviromentChunkStart);
BinaryIO::BinaryRead(file, fi->enviromentChunkStart); BinaryIO::BinaryRead(file, header.fileInfo.objectChunkStart);
BinaryIO::BinaryRead(file, fi->objectChunkStart); BinaryIO::BinaryRead(file, header.fileInfo.particleChunkStart);
BinaryIO::BinaryRead(file, fi->particleChunkStart);
header.fileInfo = fi;
//PATCH FOR AG: (messed up file?) //PATCH FOR AG: (messed up file?)
if (header.fileInfo->revision == 3452816845 && m_ParentZone->GetZoneID().GetMapID() == 1100) header.fileInfo->revision = 26; if (header.fileInfo.revision == 0xCDCDCDCD && m_ParentZone->GetZoneID().GetMapID() == 1100) header.fileInfo.revision = 26;
} }
void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
SceneObjectDataChunk* chunk = new SceneObjectDataChunk;
uint32_t objectsCount = 0; uint32_t objectsCount = 0;
BinaryIO::BinaryRead(file, objectsCount); BinaryIO::BinaryRead(file, objectsCount);
@@ -249,7 +218,10 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_current"), gating.current); GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_current"), gating.current);
GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_minor"), gating.minor); GeneralUtils::TryParse<int32_t>(Game::config->GetValue("version_minor"), gating.minor);
const auto zoneControlObject = Game::zoneManager->GetZoneControlObject();
DluAssert(zoneControlObject != nullptr);
for (uint32_t i = 0; i < objectsCount; ++i) { for (uint32_t i = 0; i < objectsCount; ++i) {
std::u16string ldfString;
SceneObject obj; SceneObject obj;
BinaryIO::BinaryRead(file, obj.id); BinaryIO::BinaryRead(file, obj.id);
BinaryIO::BinaryRead(file, obj.lot); BinaryIO::BinaryRead(file, obj.lot);
@@ -260,6 +232,8 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
BinaryIO::BinaryRead(file, obj.position); BinaryIO::BinaryRead(file, obj.position);
BinaryIO::BinaryRead(file, obj.rotation); BinaryIO::BinaryRead(file, obj.rotation);
BinaryIO::BinaryRead(file, obj.scale); BinaryIO::BinaryRead(file, obj.scale);
BinaryIO::ReadString<uint32_t>(file, ldfString);
BinaryIO::BinaryRead(file, obj.value3);
//This is a little bit of a bodge, but because the alpha client (HF) doesn't store the //This is a little bit of a bodge, but because the alpha client (HF) doesn't store the
//spawn position / rotation like the later versions do, we need to check the LOT for the spawn pos & set it. //spawn position / rotation like the later versions do, we need to check the LOT for the spawn pos & set it.
@@ -268,16 +242,6 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
Game::zoneManager->GetZone()->SetSpawnRot(obj.rotation); Game::zoneManager->GetZone()->SetSpawnRot(obj.rotation);
} }
std::u16string ldfString = u"";
uint32_t length = 0;
BinaryIO::BinaryRead(file, length);
for (uint32_t i = 0; i < length; ++i) {
uint16_t data;
BinaryIO::BinaryRead(file, data);
ldfString.push_back(data);
}
std::string sData = GeneralUtils::UTF16ToWTF8(ldfString); std::string sData = GeneralUtils::UTF16ToWTF8(ldfString);
std::stringstream ssData(sData); std::stringstream ssData(sData);
std::string token; std::string token;
@@ -288,35 +252,40 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
obj.settings.push_back(ldfData); obj.settings.push_back(ldfData);
} }
BinaryIO::BinaryRead(file, obj.value3);
// Feature gating // We should never have more than 1 zone control object
bool gated = false; bool skipLoadingObject = obj.lot == zoneControlObject->GetLOT();
for (LDFBaseData* data : obj.settings) { for (LDFBaseData* data : obj.settings) {
if (!data) continue;
if (data->GetKey() == u"gatingOnFeature") { if (data->GetKey() == u"gatingOnFeature") {
gating.featureName = data->GetValueAsString(); gating.featureName = data->GetValueAsString();
if (gating.featureName == Game::config->GetValue("event_1")) break; if (gating.featureName == Game::config->GetValue("event_1")) continue;
else if (gating.featureName == Game::config->GetValue("event_2")) break; else if (gating.featureName == Game::config->GetValue("event_2")) continue;
else if (gating.featureName == Game::config->GetValue("event_3")) break; else if (gating.featureName == Game::config->GetValue("event_3")) continue;
else if (gating.featureName == Game::config->GetValue("event_4")) break; else if (gating.featureName == Game::config->GetValue("event_4")) continue;
else if (gating.featureName == Game::config->GetValue("event_5")) break; else if (gating.featureName == Game::config->GetValue("event_5")) continue;
else if (gating.featureName == Game::config->GetValue("event_6")) break; else if (gating.featureName == Game::config->GetValue("event_6")) continue;
else if (gating.featureName == Game::config->GetValue("event_7")) break; else if (gating.featureName == Game::config->GetValue("event_7")) continue;
else if (gating.featureName == Game::config->GetValue("event_8")) break; else if (gating.featureName == Game::config->GetValue("event_8")) continue;
else if (!featureGatingTable->FeatureUnlocked(gating)) { else if (!featureGatingTable->FeatureUnlocked(gating)) {
gated = true; // The feature is not unlocked, so we can skip loading this object
skipLoadingObject = true;
break; break;
} }
} }
// If this is a client only object, we can skip loading it
if (data->GetKey() == u"loadOnClientOnly") {
skipLoadingObject = static_cast<bool>(std::stoi(data->GetValueAsString()));
break;
}
} }
if (gated) { if (skipLoadingObject) {
for (auto* setting : obj.settings) { for (auto* setting : obj.settings) {
delete setting; delete setting;
setting = nullptr;
} }
obj.settings.clear();
continue; continue;
} }
@@ -331,45 +300,7 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) {
info.rot = obj.rotation; info.rot = obj.rotation;
info.settings = obj.settings; info.settings = obj.settings;
info.scale = obj.scale; info.scale = obj.scale;
Game::entityManager->CreateEntity(info);
//Check to see if we shouldn't be loading this:
bool clientOnly = false;
bool serverOnly = false;
std::string featureGate = "";
for (LDFBaseData* data : obj.settings) {
if (data) {
if (data->GetKey() == u"loadOnClientOnly") {
clientOnly = (bool)std::stoi(data->GetValueAsString());
break;
}
if (data->GetKey() == u"loadSrvrOnly") {
serverOnly = (bool)std::stoi(data->GetValueAsString());
break;
}
}
}
if (!clientOnly) {
// We should never have more than 1 zone control object
const auto zoneControlObject = Game::zoneManager->GetZoneControlObject();
if (zoneControlObject != nullptr && info.lot == zoneControlObject->GetLOT())
goto deleteSettings;
Game::entityManager->CreateEntity(info, nullptr);
} else {
deleteSettings:
for (auto* setting : info.settings) {
delete setting;
setting = nullptr;
}
info.settings.clear();
obj.settings.clear();
}
} }
} }
header.sceneObjects = chunk;
} }

View File

@@ -27,33 +27,21 @@ public:
uint32_t particleChunkStart; uint32_t particleChunkStart;
}; };
struct SceneObjectDataChunk {
std::map<LWOOBJID, SceneObject> objects;
void PrintAllObjects() const;
uint32_t GetObjectCount() { return objects.size(); }
};
struct Header { struct Header {
uint32_t id; uint32_t id;
uint16_t chunkVersion; uint16_t chunkVersion;
ChunkTypeID chunkType; ChunkTypeID chunkType;
uint32_t size; uint32_t size;
uint32_t startPosition; uint32_t startPosition;
FileInfoChunk* fileInfo; FileInfoChunk fileInfo;
SceneObjectDataChunk* sceneObjects;
LWOSCENEID lwoSceneID; LWOSCENEID lwoSceneID;
}; };
public: public:
Level(Zone* parentZone, const std::string& filepath); Level(Zone* parentZone, const std::string& filepath);
~Level();
static void MakeSpawner(SceneObject obj); static void MakeSpawner(SceneObject obj);
const void PrintAllObjects();
std::map<uint32_t, Header> m_ChunkHeaders; std::map<uint32_t, Header> m_ChunkHeaders;
private: private:
Zone* m_ParentZone; Zone* m_ParentZone;

View File

@@ -20,7 +20,6 @@
Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) : Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) :
m_ZoneID(mapID, instanceID, cloneID) { m_ZoneID(mapID, instanceID, cloneID) {
m_NumberOfScenesLoaded = 0;
m_NumberOfObjectsLoaded = 0; m_NumberOfObjectsLoaded = 0;
m_NumberOfSceneTransitionsLoaded = 0; m_NumberOfSceneTransitionsLoaded = 0;
m_CheckSum = 0; m_CheckSum = 0;
@@ -46,14 +45,13 @@ void Zone::LoadZoneIntoMemory() {
m_ZonePath = m_ZoneFilePath.substr(0, m_ZoneFilePath.rfind('/') + 1); m_ZonePath = m_ZoneFilePath.substr(0, m_ZoneFilePath.rfind('/') + 1);
if (m_ZoneFilePath == "ERR") return; if (m_ZoneFilePath == "ERR") return;
AssetMemoryBuffer buffer = Game::assetManager->GetFileAsBuffer(m_ZoneFilePath.c_str()); auto file = Game::assetManager->GetFile(m_ZoneFilePath.c_str());
if (!buffer.m_Success) { if (!file) {
LOG("Failed to load %s", m_ZoneFilePath.c_str()); LOG("Failed to load %s", m_ZoneFilePath.c_str());
throw std::runtime_error("Aborting Zone loading due to no Zone File."); throw std::runtime_error("Aborting Zone loading due to no Zone File.");
} }
std::istream file(&buffer);
if (file) { if (file) {
BinaryIO::BinaryRead(file, m_FileFormatVersion); BinaryIO::BinaryRead(file, m_FileFormatVersion);
@@ -81,18 +79,10 @@ void Zone::LoadZoneIntoMemory() {
} }
//Read generic zone info: //Read generic zone info:
uint8_t stringLength; BinaryIO::ReadString<uint8_t>(file, m_ZonePath, BinaryIO::ReadType::String);
BinaryIO::BinaryRead(file, stringLength); BinaryIO::ReadString<uint8_t>(file, m_ZoneRawPath, BinaryIO::ReadType::String);
m_ZonePath = BinaryIO::ReadString(file, stringLength); BinaryIO::ReadString<uint8_t>(file, m_ZoneName, BinaryIO::ReadType::String);
BinaryIO::ReadString<uint8_t>(file, m_ZoneDesc, BinaryIO::ReadType::String);
BinaryIO::BinaryRead(file, stringLength);
m_ZoneRawPath = BinaryIO::ReadString(file, stringLength);
BinaryIO::BinaryRead(file, stringLength);
m_ZoneName = BinaryIO::ReadString(file, stringLength);
BinaryIO::BinaryRead(file, stringLength);
m_ZoneDesc = BinaryIO::ReadString(file, stringLength);
if (m_FileFormatVersion >= Zone::FileFormatVersion::PreAlpha) { if (m_FileFormatVersion >= Zone::FileFormatVersion::PreAlpha) {
BinaryIO::BinaryRead(file, m_NumberOfSceneTransitionsLoaded); BinaryIO::BinaryRead(file, m_NumberOfSceneTransitionsLoaded);
@@ -108,59 +98,57 @@ void Zone::LoadZoneIntoMemory() {
uint32_t pathCount; uint32_t pathCount;
BinaryIO::BinaryRead(file, pathCount); BinaryIO::BinaryRead(file, pathCount);
m_Paths.reserve(pathCount);
for (uint32_t i = 0; i < pathCount; ++i) LoadPath(file); for (uint32_t i = 0; i < pathCount; ++i) LoadPath(file);
for (Path path : m_Paths) { for (Path path : m_Paths) {
if (path.pathType == PathType::Spawner) { if (path.pathType != PathType::Spawner) continue;
SpawnerInfo info = SpawnerInfo(); SpawnerInfo info = SpawnerInfo();
for (PathWaypoint waypoint : path.pathWaypoints) { for (PathWaypoint waypoint : path.pathWaypoints) {
SpawnerNode* node = new SpawnerNode(); SpawnerNode* node = new SpawnerNode();
node->position = waypoint.position; node->position = waypoint.position;
node->rotation = waypoint.rotation; node->rotation = waypoint.rotation;
node->nodeID = 0; node->nodeID = 0;
node->config = waypoint.config; node->config = waypoint.config;
for (LDFBaseData* data : waypoint.config) { for (LDFBaseData* data : waypoint.config) {
if (data) { if (!data) continue;
if (data->GetKey() == u"spawner_node_id") {
node->nodeID = std::stoi(data->GetValueAsString()); if (data->GetKey() == u"spawner_node_id") {
} else if (data->GetKey() == u"spawner_max_per_node") { node->nodeID = std::stoi(data->GetValueAsString());
node->nodeMax = std::stoi(data->GetValueAsString()); } else if (data->GetKey() == u"spawner_max_per_node") {
} else if (data->GetKey() == u"groupID") { // Load object group node->nodeMax = std::stoi(data->GetValueAsString());
std::string groupStr = data->GetValueAsString(); } else if (data->GetKey() == u"groupID") { // Load object group
info.groups = GeneralUtils::SplitString(groupStr, ';'); std::string groupStr = data->GetValueAsString();
info.groups.erase(info.groups.end() - 1); info.groups = GeneralUtils::SplitString(groupStr, ';');
} else if (data->GetKey() == u"grpNameQBShowBricks") { info.groups.erase(info.groups.end() - 1);
if (data->GetValueAsString() == "") continue; } else if (data->GetKey() == u"grpNameQBShowBricks") {
/*std::string groupStr = data->GetValueAsString(); if (data->GetValueAsString() == "") continue;
info.groups.push_back(groupStr);*/ /*std::string groupStr = data->GetValueAsString();
info.grpNameQBShowBricks = data->GetValueAsString(); info.groups.push_back(groupStr);*/
} else if (data->GetKey() == u"spawner_name") { info.grpNameQBShowBricks = data->GetValueAsString();
info.name = data->GetValueAsString(); } else if (data->GetKey() == u"spawner_name") {
} info.name = data->GetValueAsString();
}
} }
info.nodes.push_back(node);
} }
info.templateID = path.spawner.spawnedLOT; info.nodes.push_back(node);
info.spawnerID = path.spawner.spawnerObjID;
info.respawnTime = path.spawner.respawnTime;
info.amountMaintained = path.spawner.amountMaintained;
info.maxToSpawn = path.spawner.maxToSpawn;
info.activeOnLoad = path.spawner.spawnerNetActive;
info.isNetwork = true;
Spawner* spawner = new Spawner(info);
Game::zoneManager->AddSpawner(info.spawnerID, spawner);
} }
info.templateID = path.spawner.spawnedLOT;
info.spawnerID = path.spawner.spawnerObjID;
info.respawnTime = path.spawner.respawnTime;
info.amountMaintained = path.spawner.amountMaintained;
info.maxToSpawn = path.spawner.maxToSpawn;
info.activeOnLoad = path.spawner.spawnerNetActive;
info.isNetwork = true;
Spawner* spawner = new Spawner(info);
Game::zoneManager->AddSpawner(info.spawnerID, spawner);
} }
} }
} else { } else {
LOG("Failed to open: %s", m_ZoneFilePath.c_str()); LOG("Failed to open: %s", m_ZoneFilePath.c_str());
} }
m_ZonePath = m_ZoneFilePath.substr(0, m_ZoneFilePath.rfind('/') + 1); m_ZonePath = m_ZoneFilePath.substr(0, m_ZoneFilePath.rfind('/') + 1);
buffer.close();
} }
std::string Zone::GetFilePathForZoneID() { std::string Zone::GetFilePathForZoneID() {
@@ -180,16 +168,16 @@ std::string Zone::GetFilePathForZoneID() {
uint32_t Zone::CalculateChecksum() { uint32_t Zone::CalculateChecksum() {
uint32_t sum1 = 0xffff, sum2 = 0xffff; uint32_t sum1 = 0xffff, sum2 = 0xffff;
for (std::map<LWOSCENEID, uint32_t>::const_iterator it = m_MapRevisions.cbegin(); it != m_MapRevisions.cend(); ++it) { for (const auto& [scene, sceneRevision] : m_MapRevisions) {
uint32_t sceneID = it->first.GetSceneID(); uint32_t sceneID = scene.GetSceneID();
sum2 += sum1 += (sceneID >> 16); sum2 += sum1 += (sceneID >> 16);
sum2 += sum1 += (sceneID & 0xffff); sum2 += sum1 += (sceneID & 0xffff);
uint32_t layerID = it->first.GetLayerID(); uint32_t layerID = scene.GetLayerID();
sum2 += sum1 += (layerID >> 16); sum2 += sum1 += (layerID >> 16);
sum2 += sum1 += (layerID & 0xffff); sum2 += sum1 += (layerID & 0xffff);
uint32_t revision = it->second; uint32_t revision = sceneRevision;
sum2 += sum1 += (revision >> 16); sum2 += sum1 += (revision >> 16);
sum2 += sum1 += (revision & 0xffff); sum2 += sum1 += (revision & 0xffff);
} }
@@ -201,30 +189,20 @@ uint32_t Zone::CalculateChecksum() {
} }
void Zone::LoadLevelsIntoMemory() { void Zone::LoadLevelsIntoMemory() {
for (std::map<LWOSCENEID, SceneRef>::iterator it = m_Scenes.begin(); it != m_Scenes.end(); ++it) { for (auto& [sceneID, scene] : m_Scenes) {
if (it->second.level == nullptr) { if (scene.level) continue;
it->second.level = new Level(this, m_ZonePath + it->second.filename); scene.level = new Level(this, m_ZonePath + scene.filename);
if (it->second.level->m_ChunkHeaders.size() > 0) { if (scene.level->m_ChunkHeaders.empty()) continue;
it->second.level->m_ChunkHeaders.begin()->second.lwoSceneID = it->first;
AddRevision(it->second.level->m_ChunkHeaders.begin()->second.lwoSceneID, it->second.level->m_ChunkHeaders.begin()->second.fileInfo->revision); scene.level->m_ChunkHeaders.begin()->second.lwoSceneID = sceneID;
} AddRevision(scene.level->m_ChunkHeaders.begin()->second.lwoSceneID, scene.level->m_ChunkHeaders.begin()->second.fileInfo.revision);
}
} }
} }
void Zone::AddRevision(LWOSCENEID sceneID, uint32_t revision) { void Zone::AddRevision(LWOSCENEID sceneID, uint32_t revision) {
for (std::pair<LWOSCENEID, uint32_t> item : m_MapRevisions) { if (m_MapRevisions.find(sceneID) == m_MapRevisions.end()) {
if (item.first == sceneID) return; m_MapRevisions.insert(std::make_pair(sceneID, revision));
}
m_MapRevisions[LWOSCENEID(sceneID)] = revision;
}
const void Zone::PrintAllGameObjects() {
for (std::pair<LWOSCENEID, SceneRef> scene : m_Scenes) {
LOG("In sceneID: %i", scene.first.GetSceneID());
scene.second.level->PrintAllObjects();
} }
} }
@@ -233,17 +211,10 @@ void Zone::LoadScene(std::istream& file) {
scene.level = nullptr; scene.level = nullptr;
LWOSCENEID lwoSceneID(LWOZONEID_INVALID, 0); LWOSCENEID lwoSceneID(LWOZONEID_INVALID, 0);
uint8_t sceneFilenameLength; BinaryIO::ReadString<uint8_t>(file, scene.filename, BinaryIO::ReadType::String);
BinaryIO::BinaryRead(file, sceneFilenameLength);
scene.filename = BinaryIO::ReadString(file, sceneFilenameLength);
std::string luTriggersPath = scene.filename.substr(0, scene.filename.size() - 4) + ".lutriggers"; std::string luTriggersPath = scene.filename.substr(0, scene.filename.size() - 4) + ".lutriggers";
std::vector<LUTriggers::Trigger*> triggers; if (Game::assetManager->HasFile((m_ZonePath + luTriggersPath).c_str())) LoadLUTriggers(luTriggersPath, scene);
if(Game::assetManager->HasFile((m_ZonePath + luTriggersPath).c_str())) triggers = LoadLUTriggers(luTriggersPath, scene.id);
for (LUTriggers::Trigger* trigger : triggers) {
scene.triggers.insert({ trigger->id, trigger });
}
if (m_FileFormatVersion >= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion < Zone::FileFormatVersion::PrePreAlpha) { if (m_FileFormatVersion >= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion < Zone::FileFormatVersion::PrePreAlpha) {
BinaryIO::BinaryRead(file, scene.id); BinaryIO::BinaryRead(file, scene.id);
@@ -253,12 +224,10 @@ void Zone::LoadScene(std::istream& file) {
BinaryIO::BinaryRead(file, scene.sceneType); BinaryIO::BinaryRead(file, scene.sceneType);
lwoSceneID.SetLayerID(scene.sceneType); lwoSceneID.SetLayerID(scene.sceneType);
uint8_t sceneNameLength; BinaryIO::ReadString<uint8_t>(file, scene.name, BinaryIO::ReadType::String);
BinaryIO::BinaryRead(file, sceneNameLength);
scene.name = BinaryIO::ReadString(file, sceneNameLength);
} }
if (m_FileFormatVersion == Zone::FileFormatVersion::LatePreAlpha){ if (m_FileFormatVersion == Zone::FileFormatVersion::LatePreAlpha) {
BinaryIO::BinaryRead(file, scene.unknown1); BinaryIO::BinaryRead(file, scene.unknown1);
BinaryIO::BinaryRead(file, scene.unknown2); BinaryIO::BinaryRead(file, scene.unknown2);
} }
@@ -270,61 +239,51 @@ void Zone::LoadScene(std::istream& file) {
} }
m_Scenes.insert(std::make_pair(lwoSceneID, scene)); m_Scenes.insert(std::make_pair(lwoSceneID, scene));
m_NumberOfScenesLoaded++;
} }
std::vector<LUTriggers::Trigger*> Zone::LoadLUTriggers(std::string triggerFile, LWOSCENEID sceneID) { void Zone::LoadLUTriggers(std::string triggerFile, SceneRef& scene) {
std::vector<LUTriggers::Trigger*> lvlTriggers; auto file = Game::assetManager->GetFile((m_ZonePath + triggerFile).c_str());
auto buffer = Game::assetManager->GetFileAsBuffer((m_ZonePath + triggerFile).c_str());
if (!buffer.m_Success) {
LOG("Failed to load %s from disk. Skipping loading triggers", (m_ZonePath + triggerFile).c_str());
return lvlTriggers;
}
std::istream file(&buffer);
std::stringstream data; std::stringstream data;
data << file.rdbuf(); data << file.rdbuf();
buffer.close(); data.seekg(0, std::ios::end);
int32_t size = data.tellg();
data.seekg(0, std::ios::beg);
if (data.str().size() == 0) return lvlTriggers; if (size == 0) return;
tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument(); tinyxml2::XMLDocument doc;
if (!doc) return lvlTriggers;
if (doc->Parse(data.str().c_str(), data.str().size()) == 0) { if (doc.Parse(data.str().c_str(), size) != tinyxml2::XML_SUCCESS) {
//LOG("Loaded LUTriggers from file %s!", triggerFile.c_str());
} else {
LOG("Failed to load LUTriggers from file %s", triggerFile.c_str()); LOG("Failed to load LUTriggers from file %s", triggerFile.c_str());
return lvlTriggers; return;
} }
tinyxml2::XMLElement* triggers = doc->FirstChildElement("triggers"); auto* triggers = doc.FirstChildElement("triggers");
if (!triggers) return lvlTriggers; if (!triggers) return;
auto currentTrigger = triggers->FirstChildElement("trigger"); auto* currentTrigger = triggers->FirstChildElement("trigger");
while (currentTrigger) { while (currentTrigger) {
LUTriggers::Trigger* newTrigger = new LUTriggers::Trigger(); LUTriggers::Trigger* newTrigger = new LUTriggers::Trigger();
currentTrigger->QueryAttribute("enabled", &newTrigger->enabled); currentTrigger->QueryAttribute("enabled", &newTrigger->enabled);
currentTrigger->QueryAttribute("id", &newTrigger->id); currentTrigger->QueryAttribute("id", &newTrigger->id);
auto currentEvent = currentTrigger->FirstChildElement("event"); auto* currentEvent = currentTrigger->FirstChildElement("event");
while (currentEvent) { while (currentEvent) {
LUTriggers::Event* newEvent = new LUTriggers::Event(); LUTriggers::Event* newEvent = new LUTriggers::Event();
newEvent->id = TriggerEventType::StringToTriggerEventType(currentEvent->Attribute("id")); newEvent->id = TriggerEventType::StringToTriggerEventType(currentEvent->Attribute("id"));
auto currentCommand = currentEvent->FirstChildElement("command"); auto* currentCommand = currentEvent->FirstChildElement("command");
while (currentCommand) { while (currentCommand) {
LUTriggers::Command* newCommand = new LUTriggers::Command(); LUTriggers::Command* newCommand = new LUTriggers::Command();
newCommand->id = TriggerCommandType::StringToTriggerCommandType(currentCommand->Attribute("id")); newCommand->id = TriggerCommandType::StringToTriggerCommandType(currentCommand->Attribute("id"));
newCommand->target = currentCommand->Attribute("target"); newCommand->target = currentCommand->Attribute("target");
if (currentCommand->Attribute("targetName") != NULL) { if (currentCommand->Attribute("targetName")) {
newCommand->targetName = currentCommand->Attribute("targetName"); newCommand->targetName = currentCommand->Attribute("targetName");
} } else if (currentCommand->Attribute("args")) {
if (currentCommand->Attribute("args") != NULL) {
newCommand->args = currentCommand->Attribute("args"); newCommand->args = currentCommand->Attribute("args");
} }
newEvent->commands.push_back(newCommand); newEvent->commands.push_back(newCommand);
currentCommand = currentCommand->NextSiblingElement("command"); currentCommand = currentCommand->NextSiblingElement("command");
} }
@@ -332,19 +291,18 @@ std::vector<LUTriggers::Trigger*> Zone::LoadLUTriggers(std::string triggerFile,
currentEvent = currentEvent->NextSiblingElement("event"); currentEvent = currentEvent->NextSiblingElement("event");
} }
currentTrigger = currentTrigger->NextSiblingElement("trigger"); currentTrigger = currentTrigger->NextSiblingElement("trigger");
lvlTriggers.push_back(newTrigger); scene.triggers.insert(std::make_pair(newTrigger->id, newTrigger));
} }
delete doc;
return lvlTriggers;
} }
LUTriggers::Trigger* Zone::GetTrigger(uint32_t sceneID, uint32_t triggerID) { LUTriggers::Trigger* Zone::GetTrigger(uint32_t sceneID, uint32_t triggerID) {
if (m_Scenes.find(sceneID) == m_Scenes.end()) return nullptr; auto scene = m_Scenes.find(sceneID);
if (m_Scenes[sceneID].triggers.find(triggerID) == m_Scenes[sceneID].triggers.end()) return nullptr; if (scene == m_Scenes.end()) return nullptr;
return m_Scenes[sceneID].triggers[triggerID]; auto trigger = scene->second.triggers.find(triggerID);
if (trigger == scene->second.triggers.end()) return nullptr;
return trigger->second;
} }
const Path* Zone::GetPath(std::string name) const { const Path* Zone::GetPath(std::string name) const {
@@ -360,15 +318,14 @@ const Path* Zone::GetPath(std::string name) const {
void Zone::LoadSceneTransition(std::istream& file) { void Zone::LoadSceneTransition(std::istream& file) {
SceneTransition sceneTrans; SceneTransition sceneTrans;
if (m_FileFormatVersion < Zone::FileFormatVersion::Auramar) { if (m_FileFormatVersion < Zone::FileFormatVersion::Auramar) {
uint8_t length; BinaryIO::ReadString<uint8_t>(file, sceneTrans.name, BinaryIO::ReadType::String);
BinaryIO::BinaryRead(file, length);
sceneTrans.name = BinaryIO::ReadString(file, length);
BinaryIO::BinaryRead(file, sceneTrans.width); BinaryIO::BinaryRead(file, sceneTrans.width);
} }
//BR<42>THER MAY I HAVE SOME L<><4C>PS? //BR<42>THER MAY I HAVE SOME L<><4C>PS?
uint8_t loops = (m_FileFormatVersion <= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion >= Zone::FileFormatVersion::Launch) ? 2 : 5; uint8_t loops = (m_FileFormatVersion <= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion >= Zone::FileFormatVersion::Launch) ? 2 : 5;
sceneTrans.points.reserve(loops);
for (uint8_t i = 0; i < loops; ++i) { for (uint8_t i = 0; i < loops; ++i) {
sceneTrans.points.push_back(LoadSceneTransitionInfo(file)); sceneTrans.points.push_back(LoadSceneTransitionInfo(file));
} }
@@ -388,13 +345,7 @@ void Zone::LoadPath(std::istream& file) {
BinaryIO::BinaryRead(file, path.pathVersion); BinaryIO::BinaryRead(file, path.pathVersion);
uint8_t stringLength; BinaryIO::ReadString<uint8_t>(file, path.pathName, BinaryIO::ReadType::WideString);
BinaryIO::BinaryRead(file, stringLength);
for (uint8_t i = 0; i < stringLength; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
path.pathName.push_back(character);
}
BinaryIO::BinaryRead(file, path.pathType); BinaryIO::BinaryRead(file, path.pathType);
BinaryIO::BinaryRead(file, path.flags); BinaryIO::BinaryRead(file, path.flags);
@@ -404,13 +355,7 @@ void Zone::LoadPath(std::istream& file) {
if (path.pathVersion >= 18) { if (path.pathVersion >= 18) {
BinaryIO::BinaryRead(file, path.movingPlatform.timeBasedMovement); BinaryIO::BinaryRead(file, path.movingPlatform.timeBasedMovement);
} else if (path.pathVersion >= 13) { } else if (path.pathVersion >= 13) {
uint8_t count; BinaryIO::ReadString<uint8_t>(file, path.movingPlatform.platformTravelSound, BinaryIO::ReadType::WideString);
BinaryIO::BinaryRead(file, count);
for (uint8_t i = 0; i < count; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
path.movingPlatform.platformTravelSound.push_back(character);
}
} }
} else if (path.pathType == PathType::Property) { } else if (path.pathType == PathType::Property) {
BinaryIO::BinaryRead(file, path.property.pathType); BinaryIO::BinaryRead(file, path.property.pathType);
@@ -419,20 +364,8 @@ void Zone::LoadPath(std::istream& file) {
BinaryIO::BinaryRead(file, path.property.associatedZone); BinaryIO::BinaryRead(file, path.property.associatedZone);
if (path.pathVersion >= 5) { if (path.pathVersion >= 5) {
uint8_t count1; BinaryIO::ReadString<uint8_t>(file, path.property.displayName, BinaryIO::ReadType::WideString);
BinaryIO::BinaryRead(file, count1); BinaryIO::ReadString<uint32_t>(file, path.property.displayDesc, BinaryIO::ReadType::WideString);
for (uint8_t i = 0; i < count1; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
path.property.displayName.push_back(character);
}
uint32_t count2;
BinaryIO::BinaryRead(file, count2);
for (uint8_t i = 0; i < count2; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
path.property.displayDesc.push_back(character);
}
} }
if (path.pathVersion >= 6) BinaryIO::BinaryRead(file, path.property.type); if (path.pathVersion >= 6) BinaryIO::BinaryRead(file, path.property.type);
@@ -449,13 +382,7 @@ void Zone::LoadPath(std::istream& file) {
BinaryIO::BinaryRead(file, path.property.maxBuildHeight); BinaryIO::BinaryRead(file, path.property.maxBuildHeight);
} }
} else if (path.pathType == PathType::Camera) { } else if (path.pathType == PathType::Camera) {
uint8_t count; BinaryIO::ReadString<uint8_t>(file, path.camera.nextPath, BinaryIO::ReadType::WideString);
BinaryIO::BinaryRead(file, count);
for (uint8_t i = 0; i < count; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
path.camera.nextPath.push_back(character);
}
if (path.pathVersion >= 14) { if (path.pathVersion >= 14) {
BinaryIO::BinaryRead(file, path.camera.rotatePlayer); BinaryIO::BinaryRead(file, path.camera.rotatePlayer);
@@ -472,7 +399,7 @@ void Zone::LoadPath(std::istream& file) {
// Read waypoints // Read waypoints
BinaryIO::BinaryRead(file, path.waypointCount); BinaryIO::BinaryRead(file, path.waypointCount);
path.pathWaypoints.reserve(path.waypointCount);
for (uint32_t i = 0; i < path.waypointCount; ++i) { for (uint32_t i = 0; i < path.waypointCount; ++i) {
PathWaypoint waypoint = PathWaypoint(); PathWaypoint waypoint = PathWaypoint();
@@ -493,20 +420,8 @@ void Zone::LoadPath(std::istream& file) {
BinaryIO::BinaryRead(file, waypoint.movingPlatform.speed); BinaryIO::BinaryRead(file, waypoint.movingPlatform.speed);
BinaryIO::BinaryRead(file, waypoint.movingPlatform.wait); BinaryIO::BinaryRead(file, waypoint.movingPlatform.wait);
if (path.pathVersion >= 13) { if (path.pathVersion >= 13) {
uint8_t count1; BinaryIO::ReadString<uint8_t>(file, waypoint.movingPlatform.departSound, BinaryIO::ReadType::WideString);
BinaryIO::BinaryRead(file, count1); BinaryIO::ReadString<uint8_t>(file, waypoint.movingPlatform.arriveSound, BinaryIO::ReadType::WideString);
for (uint8_t i = 0; i < count1; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
waypoint.movingPlatform.departSound.push_back(character);
}
uint8_t count2;
BinaryIO::BinaryRead(file, count2);
for (uint8_t i = 0; i < count2; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
waypoint.movingPlatform.arriveSound.push_back(character);
}
} }
} else if (path.pathType == PathType::Camera) { } else if (path.pathType == PathType::Camera) {
BinaryIO::BinaryRead(file, waypoint.camera.time); BinaryIO::BinaryRead(file, waypoint.camera.time);
@@ -529,22 +444,11 @@ void Zone::LoadPath(std::istream& file) {
uint32_t count; uint32_t count;
BinaryIO::BinaryRead(file, count); BinaryIO::BinaryRead(file, count);
for (uint32_t i = 0; i < count; ++i) { for (uint32_t i = 0; i < count; ++i) {
uint8_t count1;
std::string parameter; std::string parameter;
BinaryIO::ReadString<uint8_t>(file, parameter, BinaryIO::ReadType::WideString);
std::string value; std::string value;
BinaryIO::BinaryRead(file, count1); BinaryIO::ReadString<uint8_t>(file, value, BinaryIO::ReadType::WideString);
for (uint8_t i = 0; i < count1; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
parameter.push_back(character);
}
uint8_t count2;
BinaryIO::BinaryRead(file, count2);
for (uint8_t i = 0; i < count2; ++i) {
uint16_t character;
BinaryIO::BinaryRead(file, character);
value.push_back(character);
}
LDFBaseData* ldfConfig = nullptr; LDFBaseData* ldfConfig = nullptr;
if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) { if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) {

View File

@@ -210,7 +210,6 @@ public:
void AddRevision(LWOSCENEID sceneID, uint32_t revision); void AddRevision(LWOSCENEID sceneID, uint32_t revision);
const LWOZONEID& GetZoneID() const { return m_ZoneID; } const LWOZONEID& GetZoneID() const { return m_ZoneID; }
const uint32_t GetChecksum() const { return m_CheckSum; } const uint32_t GetChecksum() const { return m_CheckSum; }
const void PrintAllGameObjects();
LUTriggers::Trigger* GetTrigger(uint32_t sceneID, uint32_t triggerID); LUTriggers::Trigger* GetTrigger(uint32_t sceneID, uint32_t triggerID);
const Path* GetPath(std::string name) const; const Path* GetPath(std::string name) const;
@@ -228,7 +227,6 @@ public:
private: private:
LWOZONEID m_ZoneID; LWOZONEID m_ZoneID;
std::string m_ZoneFilePath; std::string m_ZoneFilePath;
uint32_t m_NumberOfScenesLoaded;
uint32_t m_NumberOfObjectsLoaded; uint32_t m_NumberOfObjectsLoaded;
uint32_t m_NumberOfSceneTransitionsLoaded; uint32_t m_NumberOfSceneTransitionsLoaded;
FileFormatVersion m_FileFormatVersion; FileFormatVersion m_FileFormatVersion;
@@ -243,18 +241,17 @@ private:
std::string m_ZoneDesc; //Description of the zone by a level designer std::string m_ZoneDesc; //Description of the zone by a level designer
std::string m_ZoneRawPath; //Path to the .raw file of this zone. std::string m_ZoneRawPath; //Path to the .raw file of this zone.
std::map<LWOSCENEID, SceneRef, mapCompareLwoSceneIDs> m_Scenes; std::map<LWOSCENEID, SceneRef> m_Scenes;
std::vector<SceneTransition> m_SceneTransitions; std::vector<SceneTransition> m_SceneTransitions;
uint32_t m_PathDataLength; uint32_t m_PathDataLength;
uint32_t m_PathChunkVersion; uint32_t m_PathChunkVersion;
std::vector<Path> m_Paths; std::vector<Path> m_Paths;
std::map<LWOSCENEID, uint32_t, mapCompareLwoSceneIDs> m_MapRevisions; //rhs is the revision! std::map<LWOSCENEID, uint32_t> m_MapRevisions; //rhs is the revision!
//private ("helper") functions: //private ("helper") functions:
void LoadScene(std::istream& file); void LoadScene(std::istream& file);
std::vector<LUTriggers::Trigger*> LoadLUTriggers(std::string triggerFile, LWOSCENEID sceneID); void LoadLUTriggers(std::string triggerFile, SceneRef& scene);
void LoadSceneTransition(std::istream& file); void LoadSceneTransition(std::istream& file);
SceneTransitionInfo LoadSceneTransitionInfo(std::istream& file); SceneTransitionInfo LoadSceneTransitionInfo(std::istream& file);
void LoadPath(std::istream& file); void LoadPath(std::istream& file);

View File

@@ -5,10 +5,6 @@
#include "LDFFormat.h" #include "LDFFormat.h"
#include <vector> #include <vector>
struct mapCompareLwoSceneIDs {
bool operator()(const LWOSCENEID& lhs, const LWOSCENEID& rhs) const { return lhs < rhs; }
};
struct SceneObject { struct SceneObject {
LWOOBJID id; LWOOBJID id;
LOT lot; LOT lot;

View File

@@ -79,8 +79,6 @@ dZoneManager::~dZoneManager() {
delete p.second; delete p.second;
p.second = nullptr; p.second = nullptr;
} }
m_Spawners.erase(p.first);
} }
if (m_WorldConfig) delete m_WorldConfig; if (m_WorldConfig) delete m_WorldConfig;
} }
@@ -96,33 +94,6 @@ void dZoneManager::LoadZone(const LWOZONEID& zoneID) {
m_pZone = new Zone(zoneID.GetMapID(), zoneID.GetInstanceID(), zoneID.GetCloneID()); m_pZone = new Zone(zoneID.GetMapID(), zoneID.GetInstanceID(), zoneID.GetCloneID());
} }
void dZoneManager::NotifyZone(const dZoneNotifier& notifier, const LWOOBJID& objectID) {
switch (notifier) {
case dZoneNotifier::SpawnedObjectDestroyed:
break;
case dZoneNotifier::SpawnedChildObjectDestroyed:
break;
case dZoneNotifier::ReloadZone:
LOG("Forcing reload of zone %i", m_ZoneID.GetMapID());
LoadZone(m_ZoneID);
m_pZone->Initalize();
break;
case dZoneNotifier::UserJoined:
break;
case dZoneNotifier::UserMoved:
break;
case dZoneNotifier::PrintAllGameObjects:
m_pZone->PrintAllGameObjects();
break;
case dZoneNotifier::InvalidNotifier:
LOG("Got an invalid zone notifier.");
break;
default:
LOG("Unknown zone notifier: %i", int(notifier));
}
}
void dZoneManager::AddSpawner(LWOOBJID id, Spawner* spawner) { void dZoneManager::AddSpawner(LWOOBJID id, Spawner* spawner) {
m_Spawners.insert_or_assign(id, spawner); m_Spawners.insert_or_assign(id, spawner);
} }

View File

@@ -14,7 +14,6 @@ public:
ReloadZone, //Forces the server and all connects clients to reload the map ReloadZone, //Forces the server and all connects clients to reload the map
UserJoined, UserJoined,
UserMoved, UserMoved,
PrintAllGameObjects, //Using this is a BAD idea in production
InvalidNotifier InvalidNotifier
}; };
@@ -30,7 +29,6 @@ public:
Zone* GetZone(); //Gets a pointer to the currently loaded zone. Zone* GetZone(); //Gets a pointer to the currently loaded zone.
void LoadZone(const LWOZONEID& zoneID); //Discard the current zone (if any) and loads a new zone. void LoadZone(const LWOZONEID& zoneID); //Discard the current zone (if any) and loads a new zone.
void NotifyZone(const dZoneNotifier& notifier, const LWOOBJID& objectID); //Notifies the zone of a certain event or command.
void AddSpawner(LWOOBJID id, Spawner* spawner); void AddSpawner(LWOOBJID id, Spawner* spawner);
LWOZONEID GetZoneID() const; LWOZONEID GetZoneID() const;
LWOOBJID MakeSpawner(SpawnerInfo info); LWOOBJID MakeSpawner(SpawnerInfo info);