diff --git a/dCommon/BinaryIO.cpp b/dCommon/BinaryIO.cpp index 22e4de60..b64fb3ba 100644 --- a/dCommon/BinaryIO.cpp +++ b/dCommon/BinaryIO.cpp @@ -1,14 +1,6 @@ #include "BinaryIO.h" #include -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 std::string BinaryIO::ReadString(std::istream& instream) { std::string toReturn; @@ -23,36 +15,3 @@ std::string BinaryIO::ReadString(std::istream& instream) { 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; -} diff --git a/dCommon/BinaryIO.h b/dCommon/BinaryIO.h index a117ad0d..d1e728ca 100644 --- a/dCommon/BinaryIO.h +++ b/dCommon/BinaryIO.h @@ -1,8 +1,17 @@ #pragma once + +#ifndef __BINARYIO__H__ +#define __BINARYIO__H__ + #include #include +#include + +#include "Game.h" +#include "Logger.h" namespace BinaryIO { + template std::ostream& BinaryWrite(std::ostream& stream, const T& value) { return stream.write(reinterpret_cast(&value), sizeof(T)); @@ -15,13 +24,51 @@ namespace BinaryIO { return stream.read(reinterpret_cast(&value), sizeof(T)); } - void WriteString(const std::string& stringToWrite, std::ofstream& outstream); + enum class ReadType : int8_t { + WideString = 0, + String = 1, + }; + + template + inline void ReadString(std::istream& stream, std::u16string& value) { + static_assert(std::is_integral::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(value.data()), size * sizeof(uint16_t)); + } + + template + inline void ReadString(std::istream& stream, std::string& value, ReadType readType) { + static_assert(std::is_integral::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(wideChar); + } + } else { + stream.read(value.data(), size); + } + } + 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) { std::ifstream f(name.c_str()); return f.good(); } } + +#endif //!__BINARYIO__H__ diff --git a/dCommon/dClient/PackIndex.cpp b/dCommon/dClient/PackIndex.cpp index 55c26b48..0d7a7fe9 100644 --- a/dCommon/dClient/PackIndex.cpp +++ b/dCommon/dClient/PackIndex.cpp @@ -8,21 +8,10 @@ PackIndex::PackIndex(const std::filesystem::path& filePath) { BinaryIO::BinaryRead(m_FileStream, m_Version); BinaryIO::BinaryRead(m_FileStream, m_PackPathCount); - - for (int i = 0; i < m_PackPathCount; i++) { - uint32_t stringLen = 0; - BinaryIO::BinaryRead(m_FileStream, stringLen); - - std::string path; - - for (int j = 0; j < stringLen; j++) { - char inChar; - BinaryIO::BinaryRead(m_FileStream, inChar); - - path += inChar; - } - - m_PackPaths.push_back(path); + + m_PackPaths.resize(m_PackPathCount); + for (auto& item : m_PackPaths) { + BinaryIO::ReadString(m_FileStream, item, BinaryIO::ReadType::String); } BinaryIO::BinaryRead(m_FileStream, m_PackFileIndexCount); diff --git a/dZoneManager/Level.cpp b/dZoneManager/Level.cpp index 4c6ff93c..25c0d4a7 100644 --- a/dZoneManager/Level.cpp +++ b/dZoneManager/Level.cpp @@ -16,12 +16,6 @@ #include "AssetManager.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) { m_ParentZone = parentZone; @@ -38,14 +32,7 @@ Level::Level(Zone* parentZone, const std::string& filepath) { buffer.close(); } -Level::~Level() { - 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){ +void Level::MakeSpawner(SceneObject obj) { SpawnerInfo spawnInfo = SpawnerInfo(); SpawnerNode* node = new SpawnerNode(); spawnInfo.templateID = obj.lot; @@ -56,7 +43,7 @@ void Level::MakeSpawner(SceneObject obj){ node->config = obj.settings; spawnInfo.nodes.push_back(node); for (LDFBaseData* data : obj.settings) { - if (data) { + if (!data) continue; if (data->GetKey() == u"spawntemplate") { spawnInfo.templateID = std::stoi(data->GetValueAsString()); } @@ -111,16 +98,8 @@ void Level::MakeSpawner(SceneObject obj){ spawnInfo.spawnActivator = static_cast*>(data)->GetValue(); } } - } - Game::zoneManager->MakeSpawner(spawnInfo); -} -const void Level::PrintAllObjects() { - for (std::map::iterator it = m_ChunkHeaders.begin(); it != m_ChunkHeaders.end(); ++it) { - if (it->second.id == Level::ChunkTypeID::SceneObjectData) { - it->second.sceneObjects->PrintAllObjects(); - } - } + Game::zoneManager->MakeSpawner(spawnInfo); } void Level::ReadChunks(std::istream& file) { @@ -155,11 +134,10 @@ void Level::ReadChunks(std::istream& file) { file.seekg(0); Header header; header.id = ChunkTypeID::FileInfo; //I guess? - FileInfoChunk* fileInfo = new FileInfoChunk(); BinaryIO::BinaryRead(file, header.chunkVersion); BinaryIO::BinaryRead(file, header.chunkType); file.ignore(1); - BinaryIO::BinaryRead(file, fileInfo->revision); + BinaryIO::BinaryRead(file, header.fileInfo.revision); if (header.chunkVersion >= 45) file.ignore(4); file.ignore(4 * (4 * 3)); @@ -172,9 +150,7 @@ void Level::ReadChunks(std::istream& file) { uint32_t s = 0; BinaryIO::BinaryRead(file, s); for (uint32_t i = 0; i < s; ++i) { - file.ignore(4); //a uint - file.ignore(4); //two floats - file.ignore(4); + file.ignore(4 * 3); //a uint and two floats } } } else { @@ -208,7 +184,6 @@ void Level::ReadChunks(std::istream& file) { BinaryIO::BinaryRead(file, count); file.ignore(count * 12); - header.fileInfo = fileInfo; m_ChunkHeaders.insert(std::make_pair(header.id, header)); //Now pretend to be a normal file and read Objects chunk: @@ -222,20 +197,17 @@ void Level::ReadChunks(std::istream& file) { } void Level::ReadFileInfoChunk(std::istream& file, Header& header) { - FileInfoChunk* fi = new FileInfoChunk; - BinaryIO::BinaryRead(file, fi->version); - BinaryIO::BinaryRead(file, fi->revision); - BinaryIO::BinaryRead(file, fi->enviromentChunkStart); - BinaryIO::BinaryRead(file, fi->objectChunkStart); - BinaryIO::BinaryRead(file, fi->particleChunkStart); - header.fileInfo = fi; + BinaryIO::BinaryRead(file, header.fileInfo.version); + BinaryIO::BinaryRead(file, header.fileInfo.revision); + BinaryIO::BinaryRead(file, header.fileInfo.enviromentChunkStart); + BinaryIO::BinaryRead(file, header.fileInfo.objectChunkStart); + BinaryIO::BinaryRead(file, header.fileInfo.particleChunkStart); //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) { - SceneObjectDataChunk* chunk = new SceneObjectDataChunk; uint32_t objectsCount = 0; BinaryIO::BinaryRead(file, objectsCount); @@ -249,17 +221,22 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { GeneralUtils::TryParse(Game::config->GetValue("version_current"), gating.current); GeneralUtils::TryParse(Game::config->GetValue("version_minor"), gating.minor); + const auto zoneControlObject = Game::zoneManager->GetZoneControlObject(); + DluAssert(zoneControlObject != nullptr); for (uint32_t i = 0; i < objectsCount; ++i) { + std::u16string ldfString; SceneObject obj; BinaryIO::BinaryRead(file, obj.id); BinaryIO::BinaryRead(file, obj.lot); - /*if (header.fileInfo->version >= 0x26)*/ BinaryIO::BinaryRead(file, obj.nodeType); - /*if (header.fileInfo->version >= 0x20)*/ BinaryIO::BinaryRead(file, obj.glomId); + /*if (header.fileInfo.version >= 0x26)*/ BinaryIO::BinaryRead(file, obj.nodeType); + /*if (header.fileInfo.version >= 0x20)*/ BinaryIO::BinaryRead(file, obj.glomId); BinaryIO::BinaryRead(file, obj.position); BinaryIO::BinaryRead(file, obj.rotation); BinaryIO::BinaryRead(file, obj.scale); + BinaryIO::ReadString(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 //spawn position / rotation like the later versions do, we need to check the LOT for the spawn pos & set it. @@ -268,16 +245,6 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { 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::stringstream ssData(sData); std::string token; @@ -288,35 +255,40 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { obj.settings.push_back(ldfData); } - BinaryIO::BinaryRead(file, obj.value3); - // Feature gating - bool gated = false; + // We should never have more than 1 zone control object + bool skipLoadingObject = obj.lot == zoneControlObject->GetLOT(); for (LDFBaseData* data : obj.settings) { + if (!data) continue; if (data->GetKey() == u"gatingOnFeature") { gating.featureName = data->GetValueAsString(); - if (gating.featureName == Game::config->GetValue("event_1")) break; - else if (gating.featureName == Game::config->GetValue("event_2")) break; - else if (gating.featureName == Game::config->GetValue("event_3")) break; - else if (gating.featureName == Game::config->GetValue("event_4")) break; - else if (gating.featureName == Game::config->GetValue("event_5")) break; - else if (gating.featureName == Game::config->GetValue("event_6")) break; - else if (gating.featureName == Game::config->GetValue("event_7")) break; - else if (gating.featureName == Game::config->GetValue("event_8")) break; + if (gating.featureName == Game::config->GetValue("event_1")) continue; + else if (gating.featureName == Game::config->GetValue("event_2")) continue; + else if (gating.featureName == Game::config->GetValue("event_3")) continue; + else if (gating.featureName == Game::config->GetValue("event_4")) continue; + else if (gating.featureName == Game::config->GetValue("event_5")) continue; + else if (gating.featureName == Game::config->GetValue("event_6")) continue; + else if (gating.featureName == Game::config->GetValue("event_7")) continue; + else if (gating.featureName == Game::config->GetValue("event_8")) continue; else if (!featureGatingTable->FeatureUnlocked(gating)) { - gated = true; + // The feature is not unlocked, so we can skip loading this object + skipLoadingObject = true; break; } } + // If this is a client only object, we can skip loading it + if (data->GetKey() == u"loadOnClientOnly") { + skipLoadingObject = static_cast(std::stoi(data->GetValueAsString())); + break; + } } - if (gated) { + if (skipLoadingObject) { for (auto* setting : obj.settings) { delete setting; + setting = nullptr; } - obj.settings.clear(); - continue; } @@ -331,45 +303,7 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { info.rot = obj.rotation; info.settings = obj.settings; info.scale = obj.scale; - - //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(); - } + Game::entityManager->CreateEntity(info); } } - - header.sceneObjects = chunk; } diff --git a/dZoneManager/Level.h b/dZoneManager/Level.h index 6f56e073..1f0b4f2e 100644 --- a/dZoneManager/Level.h +++ b/dZoneManager/Level.h @@ -27,33 +27,21 @@ public: uint32_t particleChunkStart; }; - struct SceneObjectDataChunk { - std::map objects; - - void PrintAllObjects() const; - - uint32_t GetObjectCount() { return objects.size(); } - }; - struct Header { uint32_t id; uint16_t chunkVersion; ChunkTypeID chunkType; uint32_t size; uint32_t startPosition; - FileInfoChunk* fileInfo; - SceneObjectDataChunk* sceneObjects; + FileInfoChunk fileInfo; LWOSCENEID lwoSceneID; }; public: Level(Zone* parentZone, const std::string& filepath); - ~Level(); static void MakeSpawner(SceneObject obj); - const void PrintAllObjects(); - std::map m_ChunkHeaders; private: Zone* m_ParentZone; diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 18de939c..56abb743 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -20,7 +20,6 @@ Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) : m_ZoneID(mapID, instanceID, cloneID) { - m_NumberOfScenesLoaded = 0; m_NumberOfObjectsLoaded = 0; m_NumberOfSceneTransitionsLoaded = 0; m_CheckSum = 0; @@ -81,18 +80,10 @@ void Zone::LoadZoneIntoMemory() { } //Read generic zone info: - uint8_t stringLength; - BinaryIO::BinaryRead(file, stringLength); - m_ZonePath = BinaryIO::ReadString(file, stringLength); - - 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); + BinaryIO::ReadString(file, m_ZonePath, BinaryIO::ReadType::String); + BinaryIO::ReadString(file, m_ZoneRawPath, BinaryIO::ReadType::String); + BinaryIO::ReadString(file, m_ZoneName, BinaryIO::ReadType::String); + BinaryIO::ReadString(file, m_ZoneDesc, BinaryIO::ReadType::String); if (m_FileFormatVersion >= Zone::FileFormatVersion::PreAlpha) { BinaryIO::BinaryRead(file, m_NumberOfSceneTransitionsLoaded); @@ -108,51 +99,50 @@ void Zone::LoadZoneIntoMemory() { uint32_t pathCount; BinaryIO::BinaryRead(file, pathCount); + m_Paths.reserve(pathCount); for (uint32_t i = 0; i < pathCount; ++i) LoadPath(file); for (Path path : m_Paths) { - if (path.pathType == PathType::Spawner) { - SpawnerInfo info = SpawnerInfo(); - for (PathWaypoint waypoint : path.pathWaypoints) { - SpawnerNode* node = new SpawnerNode(); - node->position = waypoint.position; - node->rotation = waypoint.rotation; - node->nodeID = 0; - node->config = waypoint.config; + if (path.pathType != PathType::Spawner) continue; + SpawnerInfo info = SpawnerInfo(); + for (PathWaypoint waypoint : path.pathWaypoints) { + SpawnerNode* node = new SpawnerNode(); + node->position = waypoint.position; + node->rotation = waypoint.rotation; + node->nodeID = 0; + node->config = waypoint.config; - for (LDFBaseData* data : waypoint.config) { - if (data) { - if (data->GetKey() == u"spawner_node_id") { - node->nodeID = std::stoi(data->GetValueAsString()); - } else if (data->GetKey() == u"spawner_max_per_node") { - node->nodeMax = std::stoi(data->GetValueAsString()); - } else if (data->GetKey() == u"groupID") { // Load object group - std::string groupStr = data->GetValueAsString(); - info.groups = GeneralUtils::SplitString(groupStr, ';'); - info.groups.erase(info.groups.end() - 1); - } else if (data->GetKey() == u"grpNameQBShowBricks") { - if (data->GetValueAsString() == "") continue; - /*std::string groupStr = data->GetValueAsString(); - info.groups.push_back(groupStr);*/ - info.grpNameQBShowBricks = data->GetValueAsString(); - } else if (data->GetKey() == u"spawner_name") { - info.name = data->GetValueAsString(); - } - } + for (LDFBaseData* data : waypoint.config) { + if (!data) continue; + + if (data->GetKey() == u"spawner_node_id") { + node->nodeID = std::stoi(data->GetValueAsString()); + } else if (data->GetKey() == u"spawner_max_per_node") { + node->nodeMax = std::stoi(data->GetValueAsString()); + } else if (data->GetKey() == u"groupID") { // Load object group + std::string groupStr = data->GetValueAsString(); + info.groups = GeneralUtils::SplitString(groupStr, ';'); + info.groups.erase(info.groups.end() - 1); + } else if (data->GetKey() == u"grpNameQBShowBricks") { + if (data->GetValueAsString() == "") continue; + /*std::string groupStr = data->GetValueAsString(); + info.groups.push_back(groupStr);*/ + info.grpNameQBShowBricks = data->GetValueAsString(); + } else if (data->GetKey() == u"spawner_name") { + info.name = data->GetValueAsString(); } - info.nodes.push_back(node); } - 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); + info.nodes.push_back(node); } - + 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 { @@ -180,16 +170,16 @@ std::string Zone::GetFilePathForZoneID() { uint32_t Zone::CalculateChecksum() { uint32_t sum1 = 0xffff, sum2 = 0xffff; - for (std::map::const_iterator it = m_MapRevisions.cbegin(); it != m_MapRevisions.cend(); ++it) { - uint32_t sceneID = it->first.GetSceneID(); + for (const auto& [scene, sceneRevision] : m_MapRevisions) { + uint32_t sceneID = scene.GetSceneID(); sum2 += sum1 += (sceneID >> 16); sum2 += sum1 += (sceneID & 0xffff); - uint32_t layerID = it->first.GetLayerID(); + uint32_t layerID = scene.GetLayerID(); sum2 += sum1 += (layerID >> 16); sum2 += sum1 += (layerID & 0xffff); - uint32_t revision = it->second; + uint32_t revision = sceneRevision; sum2 += sum1 += (revision >> 16); sum2 += sum1 += (revision & 0xffff); } @@ -201,30 +191,20 @@ uint32_t Zone::CalculateChecksum() { } void Zone::LoadLevelsIntoMemory() { - for (std::map::iterator it = m_Scenes.begin(); it != m_Scenes.end(); ++it) { - if (it->second.level == nullptr) { - it->second.level = new Level(this, m_ZonePath + it->second.filename); + for (auto& [sceneID, scene] : m_Scenes) { + if (scene.level) continue; + scene.level = new Level(this, m_ZonePath + scene.filename); - if (it->second.level->m_ChunkHeaders.size() > 0) { - 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); - } - } + if (scene.level->m_ChunkHeaders.empty()) continue; + + 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) { - for (std::pair item : m_MapRevisions) { - if (item.first == sceneID) return; - } - - m_MapRevisions[LWOSCENEID(sceneID)] = revision; -} - -const void Zone::PrintAllGameObjects() { - for (std::pair scene : m_Scenes) { - LOG("In sceneID: %i", scene.first.GetSceneID()); - scene.second.level->PrintAllObjects(); + if (m_MapRevisions.find(sceneID) == m_MapRevisions.end()) { + m_MapRevisions.insert(std::make_pair(sceneID, revision)); } } @@ -233,17 +213,10 @@ void Zone::LoadScene(std::istream& file) { scene.level = nullptr; LWOSCENEID lwoSceneID(LWOZONEID_INVALID, 0); - uint8_t sceneFilenameLength; - BinaryIO::BinaryRead(file, sceneFilenameLength); - scene.filename = BinaryIO::ReadString(file, sceneFilenameLength); + BinaryIO::ReadString(file, scene.filename, BinaryIO::ReadType::String); std::string luTriggersPath = scene.filename.substr(0, scene.filename.size() - 4) + ".lutriggers"; - std::vector triggers; - 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 (Game::assetManager->HasFile((m_ZonePath + luTriggersPath).c_str())) LoadLUTriggers(luTriggersPath, scene); if (m_FileFormatVersion >= Zone::FileFormatVersion::LatePreAlpha || m_FileFormatVersion < Zone::FileFormatVersion::PrePreAlpha) { BinaryIO::BinaryRead(file, scene.id); @@ -253,12 +226,10 @@ void Zone::LoadScene(std::istream& file) { BinaryIO::BinaryRead(file, scene.sceneType); lwoSceneID.SetLayerID(scene.sceneType); - uint8_t sceneNameLength; - BinaryIO::BinaryRead(file, sceneNameLength); - scene.name = BinaryIO::ReadString(file, sceneNameLength); + BinaryIO::ReadString(file, scene.name, BinaryIO::ReadType::String); } - if (m_FileFormatVersion == Zone::FileFormatVersion::LatePreAlpha){ + if (m_FileFormatVersion == Zone::FileFormatVersion::LatePreAlpha) { BinaryIO::BinaryRead(file, scene.unknown1); BinaryIO::BinaryRead(file, scene.unknown2); } @@ -270,17 +241,14 @@ void Zone::LoadScene(std::istream& file) { } m_Scenes.insert(std::make_pair(lwoSceneID, scene)); - m_NumberOfScenesLoaded++; } -std::vector Zone::LoadLUTriggers(std::string triggerFile, LWOSCENEID sceneID) { - std::vector lvlTriggers; - +void Zone::LoadLUTriggers(std::string triggerFile, SceneRef& scene) { 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; + return; } std::istream file(&buffer); @@ -289,42 +257,43 @@ std::vector Zone::LoadLUTriggers(std::string triggerFile, buffer.close(); - if (data.str().size() == 0) return lvlTriggers; + data.seekg(0, std::ios::end); + int32_t size = data.tellg(); + data.seekg(0, std::ios::beg); - tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument(); - if (!doc) return lvlTriggers; + if (size == 0) return; - if (doc->Parse(data.str().c_str(), data.str().size()) == 0) { - //LOG("Loaded LUTriggers from file %s!", triggerFile.c_str()); - } else { + tinyxml2::XMLDocument doc; + + if (doc.Parse(data.str().c_str(), size) != tinyxml2::XML_SUCCESS) { LOG("Failed to load LUTriggers from file %s", triggerFile.c_str()); - return lvlTriggers; + return; } - tinyxml2::XMLElement* triggers = doc->FirstChildElement("triggers"); - if (!triggers) return lvlTriggers; + auto* triggers = doc.FirstChildElement("triggers"); + if (!triggers) return; - auto currentTrigger = triggers->FirstChildElement("trigger"); + auto* currentTrigger = triggers->FirstChildElement("trigger"); while (currentTrigger) { LUTriggers::Trigger* newTrigger = new LUTriggers::Trigger(); currentTrigger->QueryAttribute("enabled", &newTrigger->enabled); currentTrigger->QueryAttribute("id", &newTrigger->id); - auto currentEvent = currentTrigger->FirstChildElement("event"); + auto* currentEvent = currentTrigger->FirstChildElement("event"); while (currentEvent) { LUTriggers::Event* newEvent = new LUTriggers::Event(); newEvent->id = TriggerEventType::StringToTriggerEventType(currentEvent->Attribute("id")); - auto currentCommand = currentEvent->FirstChildElement("command"); + auto* currentCommand = currentEvent->FirstChildElement("command"); while (currentCommand) { LUTriggers::Command* newCommand = new LUTriggers::Command(); newCommand->id = TriggerCommandType::StringToTriggerCommandType(currentCommand->Attribute("id")); newCommand->target = currentCommand->Attribute("target"); - if (currentCommand->Attribute("targetName") != NULL) { + if (currentCommand->Attribute("targetName")) { newCommand->targetName = currentCommand->Attribute("targetName"); - } - if (currentCommand->Attribute("args") != NULL) { + } else if (currentCommand->Attribute("args")) { newCommand->args = currentCommand->Attribute("args"); } + newEvent->commands.push_back(newCommand); currentCommand = currentCommand->NextSiblingElement("command"); } @@ -332,19 +301,18 @@ std::vector Zone::LoadLUTriggers(std::string triggerFile, currentEvent = currentEvent->NextSiblingElement("event"); } 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) { - if (m_Scenes.find(sceneID) == m_Scenes.end()) return nullptr; - if (m_Scenes[sceneID].triggers.find(triggerID) == m_Scenes[sceneID].triggers.end()) return nullptr; + auto scene = m_Scenes.find(sceneID); + 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 { @@ -360,15 +328,14 @@ const Path* Zone::GetPath(std::string name) const { void Zone::LoadSceneTransition(std::istream& file) { SceneTransition sceneTrans; if (m_FileFormatVersion < Zone::FileFormatVersion::Auramar) { - uint8_t length; - BinaryIO::BinaryRead(file, length); - sceneTrans.name = BinaryIO::ReadString(file, length); + BinaryIO::ReadString(file, sceneTrans.name, BinaryIO::ReadType::String); BinaryIO::BinaryRead(file, sceneTrans.width); } //BR�THER MAY I HAVE SOME L��PS? 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) { sceneTrans.points.push_back(LoadSceneTransitionInfo(file)); } @@ -388,13 +355,7 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, path.pathVersion); - uint8_t stringLength; - 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::ReadString(file, path.pathName, BinaryIO::ReadType::WideString); BinaryIO::BinaryRead(file, path.pathType); BinaryIO::BinaryRead(file, path.flags); @@ -404,13 +365,7 @@ void Zone::LoadPath(std::istream& file) { if (path.pathVersion >= 18) { BinaryIO::BinaryRead(file, path.movingPlatform.timeBasedMovement); } else if (path.pathVersion >= 13) { - uint8_t count; - 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); - } + BinaryIO::ReadString(file, path.movingPlatform.platformTravelSound, BinaryIO::ReadType::WideString); } } else if (path.pathType == PathType::Property) { BinaryIO::BinaryRead(file, path.property.pathType); @@ -419,20 +374,8 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, path.property.associatedZone); if (path.pathVersion >= 5) { - uint8_t count1; - BinaryIO::BinaryRead(file, count1); - 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); - } + BinaryIO::ReadString(file, path.property.displayName, BinaryIO::ReadType::WideString); + BinaryIO::ReadString(file, path.property.displayDesc, BinaryIO::ReadType::WideString); } if (path.pathVersion >= 6) BinaryIO::BinaryRead(file, path.property.type); @@ -449,13 +392,7 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, path.property.maxBuildHeight); } } else if (path.pathType == PathType::Camera) { - uint8_t count; - 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); - } + BinaryIO::ReadString(file, path.camera.nextPath, BinaryIO::ReadType::WideString); if (path.pathVersion >= 14) { BinaryIO::BinaryRead(file, path.camera.rotatePlayer); @@ -472,7 +409,7 @@ void Zone::LoadPath(std::istream& file) { // Read waypoints BinaryIO::BinaryRead(file, path.waypointCount); - + path.pathWaypoints.reserve(path.waypointCount); for (uint32_t i = 0; i < path.waypointCount; ++i) { PathWaypoint waypoint = PathWaypoint(); @@ -493,20 +430,8 @@ void Zone::LoadPath(std::istream& file) { BinaryIO::BinaryRead(file, waypoint.movingPlatform.speed); BinaryIO::BinaryRead(file, waypoint.movingPlatform.wait); if (path.pathVersion >= 13) { - uint8_t count1; - BinaryIO::BinaryRead(file, count1); - 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); - } + BinaryIO::ReadString(file, waypoint.movingPlatform.departSound, BinaryIO::ReadType::WideString); + BinaryIO::ReadString(file, waypoint.movingPlatform.arriveSound, BinaryIO::ReadType::WideString); } } else if (path.pathType == PathType::Camera) { BinaryIO::BinaryRead(file, waypoint.camera.time); @@ -529,22 +454,11 @@ void Zone::LoadPath(std::istream& file) { uint32_t count; BinaryIO::BinaryRead(file, count); for (uint32_t i = 0; i < count; ++i) { - uint8_t count1; std::string parameter; + BinaryIO::ReadString(file, parameter, BinaryIO::ReadType::WideString); + std::string value; - BinaryIO::BinaryRead(file, count1); - 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); - } + BinaryIO::ReadString(file, value, BinaryIO::ReadType::WideString); LDFBaseData* ldfConfig = nullptr; if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) { diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index ff931154..978671af 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -210,7 +210,6 @@ public: void AddRevision(LWOSCENEID sceneID, uint32_t revision); const LWOZONEID& GetZoneID() const { return m_ZoneID; } const uint32_t GetChecksum() const { return m_CheckSum; } - const void PrintAllGameObjects(); LUTriggers::Trigger* GetTrigger(uint32_t sceneID, uint32_t triggerID); const Path* GetPath(std::string name) const; @@ -228,7 +227,6 @@ public: private: LWOZONEID m_ZoneID; std::string m_ZoneFilePath; - uint32_t m_NumberOfScenesLoaded; uint32_t m_NumberOfObjectsLoaded; uint32_t m_NumberOfSceneTransitionsLoaded; FileFormatVersion m_FileFormatVersion; @@ -254,7 +252,7 @@ private: //private ("helper") functions: void LoadScene(std::istream& file); - std::vector LoadLUTriggers(std::string triggerFile, LWOSCENEID sceneID); + void LoadLUTriggers(std::string triggerFile, SceneRef& scene); void LoadSceneTransition(std::istream& file); SceneTransitionInfo LoadSceneTransitionInfo(std::istream& file); void LoadPath(std::istream& file); diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 137a9cab..1f68d084 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -96,33 +96,6 @@ void dZoneManager::LoadZone(const LWOZONEID& zoneID) { 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) { m_Spawners.insert_or_assign(id, spawner); } diff --git a/dZoneManager/dZoneManager.h b/dZoneManager/dZoneManager.h index b5db3f6e..4e512d22 100644 --- a/dZoneManager/dZoneManager.h +++ b/dZoneManager/dZoneManager.h @@ -14,7 +14,6 @@ public: ReloadZone, //Forces the server and all connects clients to reload the map UserJoined, UserMoved, - PrintAllGameObjects, //Using this is a BAD idea in production InvalidNotifier }; @@ -30,7 +29,6 @@ public: 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 NotifyZone(const dZoneNotifier& notifier, const LWOOBJID& objectID); //Notifies the zone of a certain event or command. void AddSpawner(LWOOBJID id, Spawner* spawner); LWOZONEID GetZoneID() const; LWOOBJID MakeSpawner(SpawnerInfo info);