From 2a40e37b070fd918bf31c6a5f46d94b526d8e8fa Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Mon, 20 Nov 2023 01:59:55 -0800 Subject: [PATCH 1/7] Remove std::couts littered throughout the base --- dGame/dComponents/PhantomPhysicsComponent.cpp | 4 +-- dGame/dGameMessages/GameMessageHandler.cpp | 12 ------- dGame/dUtilities/SlashCommandHandler.cpp | 8 ++--- dPhysics/dpEntity.cpp | 8 +---- dPhysics/dpGrid.cpp | 2 -- dPhysics/dpShapeBase.cpp | 4 +-- dPhysics/dpShapeBox.cpp | 5 +-- dPhysics/dpShapeSphere.cpp | 4 ++- dPhysics/main.cpp | 35 ------------------- dZoneManager/Level.cpp | 16 ++++++--- dZoneManager/Level.h | 6 +--- dZoneManager/Zone.h | 2 ++ dZoneManager/dZMCommon.h | 4 +-- tests/dCommonTests/Amf3Tests.cpp | 10 ------ 14 files changed, 29 insertions(+), 91 deletions(-) delete mode 100644 dPhysics/main.cpp diff --git a/dGame/dComponents/PhantomPhysicsComponent.cpp b/dGame/dComponents/PhantomPhysicsComponent.cpp index e0a76f67c..6248bfe99 100644 --- a/dGame/dComponents/PhantomPhysicsComponent.cpp +++ b/dGame/dComponents/PhantomPhysicsComponent.cpp @@ -402,10 +402,10 @@ void PhantomPhysicsComponent::SetDirection(const NiPoint3& pos) { void PhantomPhysicsComponent::SpawnVertices() { if (!m_dpEntity) return; - std::cout << m_Parent->GetObjectID() << std::endl; + LOG("%llu", m_Parent->GetObjectID()); auto box = static_cast(m_dpEntity->GetShape()); for (auto vert : box->GetVertices()) { - std::cout << vert.x << ", " << vert.y << ", " << vert.z << std::endl; + LOG("%f, %f, %f", vert.x, vert.y, vert.z); EntityInfo info; info.lot = 33; diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index 9a50a746f..40293fbec 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -244,13 +244,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System case eGameMessageType::REQUEST_RESURRECT: { GameMessages::SendResurrect(entity); - /*auto* dest = static_cast(entity->GetComponent(eReplicaComponentType::DESTROYABLE)); - if (dest) { - dest->SetHealth(4); - dest->SetArmor(0); - dest->SetImagination(6); - Game::entityManager->SerializeEntity(entity); - }*/ break; } case eGameMessageType::GET_HOT_PROPERTY_DATA: { @@ -339,11 +332,8 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System RakNet::BitStream bitStreamLocal; BitStreamUtils::WriteHeader(bitStreamLocal, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); bitStreamLocal.Write(entity->GetObjectID()); - //bitStreamLocal.Write((unsigned short)eGameMessageType::ECHO_SYNC_SKILL); - //bitStreamLocal.Write(inStream); SyncSkill sync = SyncSkill(inStream); // inStream replaced &bitStream - //sync.Serialize(&bitStreamLocal); ostringstream buffer; @@ -353,8 +343,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System buffer << setw(2) << hex << setfill('0') << (int)s << " "; } - //cout << buffer.str() << endl; - if (usr != nullptr) { RakNet::BitStream* bs = new RakNet::BitStream((unsigned char*)sync.sBitStream.c_str(), sync.sBitStream.size(), false); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 71f0e38b6..f4a21cabf 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1372,7 +1372,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"<" + (GeneralUtils::to_u16string(position.x)) + u", " + (GeneralUtils::to_u16string(position.y)) + u", " + (GeneralUtils::to_u16string(position.z)) + u">"); - std::cout << position.x << ", " << position.y << ", " << position.z << std::endl; + LOG("Position: %f, %f, %f", position.x, position.y, position.z); } if (chatCommand == "rot" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { @@ -1380,14 +1380,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"<" + (GeneralUtils::to_u16string(rotation.w)) + u", " + (GeneralUtils::to_u16string(rotation.x)) + u", " + (GeneralUtils::to_u16string(rotation.y)) + u", " + (GeneralUtils::to_u16string(rotation.z)) + u">"); - std::cout << rotation.w << ", " << rotation.x << ", " << rotation.y << ", " << rotation.z << std::endl; + LOG("Rotation: %f, %f, %f, %f", rotation.w, rotation.x, rotation.y, rotation.z); } if (chatCommand == "locrow" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { const auto position = entity->GetPosition(); const auto rotation = entity->GetRotation(); - std::cout << "" << std::endl; + LOG("", position.x, position.y, position.z, rotation.w, rotation.x, rotation.y, rotation.z); } if (chatCommand == "playlvlfx" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) { @@ -1652,7 +1652,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit auto sphere = static_cast(prox.second->GetShape()); auto pos = prox.second->GetPosition(); - std::cout << prox.first << ", r: " << sphere->GetRadius() << ", pos: " << pos.x << "," << pos.y << "," << pos.z << std::endl; + LOG("Proximity: %s, r: %f, pos: %f, %f, %f", prox.first.c_str(), sphere->GetRadius(), pos.x, pos.y, pos.z); } } } diff --git a/dPhysics/dpEntity.cpp b/dPhysics/dpEntity.cpp index c7ed56f85..70bddb40a 100644 --- a/dPhysics/dpEntity.cpp +++ b/dPhysics/dpEntity.cpp @@ -22,7 +22,7 @@ dpEntity::dpEntity(const LWOOBJID& objectID, dpShapeType shapeType, bool isStati break; default: - std::cout << "No shape for shapeType: " << (int)shapeType << std::endl; + LOG("No shape for shapeType: %d", static_cast(shapeType)); } } @@ -83,15 +83,9 @@ void dpEntity::CheckCollision(dpEntity* other) { if (isColliding && !wasFound) { m_CurrentlyCollidingObjects.emplace(other->GetObjectID(), other); m_NewObjects.push_back(other); - - //if (m_CollisionShape->GetShapeType() == dpShapeType::Sphere && other->GetShape()->GetShapeType() == dpShapeType::Sphere) - //std::cout << "started sphere col at: " << other->GetPosition().x << ", " << other->GetPosition().y << ", " << other->GetPosition().z << std::endl; } else if (!isColliding && wasFound) { m_CurrentlyCollidingObjects.erase(other->GetObjectID()); m_RemovedObjects.push_back(other); - - //if (m_CollisionShape->GetShapeType() == dpShapeType::Sphere && other->GetShape()->GetShapeType() == dpShapeType::Sphere) - // std::cout << "stopped sphere col at: " << other->GetPosition().x << ", " << other->GetPosition().y << ", " << other->GetPosition().z << std::endl; } } diff --git a/dPhysics/dpGrid.cpp b/dPhysics/dpGrid.cpp index c3259b51e..1704e068e 100644 --- a/dPhysics/dpGrid.cpp +++ b/dPhysics/dpGrid.cpp @@ -8,8 +8,6 @@ dpGrid::dpGrid(int numCells, int cellSize) { CELL_SIZE = cellSize; m_DeleteGrid = true; - //dumb method but i can't be bothered - //fill x for (int i = 0; i < NUM_CELLS; i++) { m_Cells.push_back(std::vector>()); diff --git a/dPhysics/dpShapeBase.cpp b/dPhysics/dpShapeBase.cpp index 545751594..29f5d7890 100644 --- a/dPhysics/dpShapeBase.cpp +++ b/dPhysics/dpShapeBase.cpp @@ -10,7 +10,7 @@ dpShapeBase::~dpShapeBase() { } bool dpShapeBase::IsColliding(dpShapeBase* other) { - std::cout << "Base shapes do not have any *shape* to them, and thus cannot be overlapping." << std::endl; - std::cout << "You should be using a shape class inherited from this base class." << std::endl; + LOG("Base shapes do not have any *shape* to them, and thus cannot be overlapping."); + LOG("You should be using a shape class inherited from this base class."); return false; } diff --git a/dPhysics/dpShapeBox.cpp b/dPhysics/dpShapeBox.cpp index b40be6af2..bfd72deac 100644 --- a/dPhysics/dpShapeBox.cpp +++ b/dPhysics/dpShapeBox.cpp @@ -34,7 +34,7 @@ bool dpShapeBox::IsColliding(dpShapeBase* other) { return dpCollisionChecks::CheckBoxes(m_ParentEntity, other->GetParentEntity()); default: - std::cout << "No collision detection for: " << (int)m_ShapeType << "-to-" << (int)other->GetShapeType() << " collision!" << std::endl; + LOG("No collision detection for: %i-to-%i collision!", static_cast(m_ShapeType), static_cast(other->GetShapeType())); } return false; @@ -72,10 +72,7 @@ void dpShapeBox::SetScale(float scale) { m_Height *= scale; m_Depth *= scale; - //fuuuckkk yoouu InitVertices(); - - //SetRotation(m_ParentEntity->GetRotation()); } void dpShapeBox::SetRotation(const NiQuaternion& rotation) { diff --git a/dPhysics/dpShapeSphere.cpp b/dPhysics/dpShapeSphere.cpp index 168a3b214..545d58ed1 100644 --- a/dPhysics/dpShapeSphere.cpp +++ b/dPhysics/dpShapeSphere.cpp @@ -1,5 +1,7 @@ #include "dpShapeSphere.h" #include "dpCollisionChecks.h" +#include "Game.h" +#include "Logger.h" #include dpShapeSphere::dpShapeSphere(dpEntity* parentEntity, float radius) : @@ -22,7 +24,7 @@ bool dpShapeSphere::IsColliding(dpShapeBase* other) { return dpCollisionChecks::CheckSphereBox(m_ParentEntity, other->GetParentEntity()); default: - std::cout << "No collision detection for: " << (int)m_ShapeType << "-to-" << (int)other->GetShapeType() << " collision!" << std::endl; + LOG("No collision detection for: %i-to-%i collision!", static_cast(m_ShapeType), static_cast(other->GetShapeType())); } return false; diff --git a/dPhysics/main.cpp b/dPhysics/main.cpp deleted file mode 100644 index 7de1555a7..000000000 --- a/dPhysics/main.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//This file included for reference only - -/*#include -#include -#include -#include "dpWorld.h" - -#include "NiQuaternion.hpp" -#include "NiPoint3.hpp" - -int main() { - std::cout << "dPhysics test engine" << std::endl; - - //Test rotation code: - NiPoint3 p(1.0f, 0.0f, 0.0f); - - float angle = 45.0f; - NiQuaternion q = NiQuaternion::CreateFromAxisAngle(NiPoint3(0.0f, 0.0f, 1.0f), angle); - - NiPoint3 rotated = p.RotateByQuaternion(q); - - std::cout << "OG: " << p.x << ", " << p.y << ", " << p.z << std::endl; - std::cout << "Quater: " << q.x << ", " << q.y << ", " << q.z << ", " << q.w << " angle: " << angle << std::endl; - std::cout << "Rotated: " << rotated.x << ", " << rotated.y << ", " << rotated.z << std::endl; - - //Test some collisions: - dpWorld::GetInstance().Initialize(1000); - - while (true) { - dpWorld::GetInstance().StepWorld(1.0f/60.0f); - std::this_thread::sleep_for(std::chrono::milliseconds(16)); - } - - return 0; -}*/ diff --git a/dZoneManager/Level.cpp b/dZoneManager/Level.cpp index 8202b7605..4c6ff93c6 100644 --- a/dZoneManager/Level.cpp +++ b/dZoneManager/Level.cpp @@ -16,6 +16,12 @@ #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; @@ -33,9 +39,9 @@ Level::Level(Zone* parentZone, const std::string& filepath) { } Level::~Level() { - for (std::map::iterator it = m_ChunkHeaders.begin(); it != m_ChunkHeaders.end(); ++it) { - if (it->second.id == Level::ChunkTypeID::FileInfo) delete it->second.fileInfo; - if (it->second.id == Level::ChunkTypeID::SceneObjectData) delete it->second.sceneObjects; + for (auto& [id, header] : m_ChunkHeaders) { + if (header.id == Level::ChunkTypeID::FileInfo) delete header.fileInfo; + if (header.id == Level::ChunkTypeID::SceneObjectData) delete header.sceneObjects; } } @@ -248,8 +254,8 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { BinaryIO::BinaryRead(file, obj.id); BinaryIO::BinaryRead(file, obj.lot); - /*if (header.fileInfo->version >= 0x26)*/ BinaryIO::BinaryRead(file, obj.value1); - /*if (header.fileInfo->version >= 0x20)*/ BinaryIO::BinaryRead(file, obj.value2); + /*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); diff --git a/dZoneManager/Level.h b/dZoneManager/Level.h index a27326a21..6f56e0731 100644 --- a/dZoneManager/Level.h +++ b/dZoneManager/Level.h @@ -30,11 +30,7 @@ class Level { struct SceneObjectDataChunk { std::map objects; - const void PrintAllObjects() { - for (std::map::iterator it = objects.begin(); it != objects.end(); ++it) { - std::cout << "\t ID: " << it->first << " LOT: " << it->second.lot << std::endl; - } - } + void PrintAllObjects() const; uint32_t GetObjectCount() { return objects.size(); } }; diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index af9f6b554..ff9311545 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -148,6 +148,8 @@ struct PropertyPath { float repMultiplier; PropertyRentalPeriod rentalPeriod; PropertyAchievmentRequired achievementRequired; + + // Player respawn coordinates in the main zone (not the property zone) NiPoint3 playerZoneCoords; float maxBuildHeight; }; diff --git a/dZoneManager/dZMCommon.h b/dZoneManager/dZMCommon.h index 635faaaee..738fc283e 100644 --- a/dZoneManager/dZMCommon.h +++ b/dZoneManager/dZMCommon.h @@ -12,8 +12,8 @@ struct mapCompareLwoSceneIDs { struct SceneObject { LWOOBJID id; LOT lot; - uint32_t value1; - uint32_t value2; + uint32_t nodeType; + uint32_t glomId; NiPoint3 position; NiQuaternion rotation; float scale = 1.0f; diff --git a/tests/dCommonTests/Amf3Tests.cpp b/tests/dCommonTests/Amf3Tests.cpp index a51fe4ba4..5b52cf277 100644 --- a/tests/dCommonTests/Amf3Tests.cpp +++ b/tests/dCommonTests/Amf3Tests.cpp @@ -71,25 +71,15 @@ TEST(dCommonTests, AMF3InsertionAssociativeTest) { array.Insert>("Undefined", {}); array.Insert("Null", nullptr); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("CString")->GetValueType(), eAmf::String); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("String")->GetValueType(), eAmf::String); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("False")->GetValueType(), eAmf::False); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("True")->GetValueType(), eAmf::True); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("Integer")->GetValueType(), eAmf::Integer); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("Double")->GetValueType(), eAmf::Double); - std::cout << "test" << std::endl; ASSERT_EQ(array.GetArray("Array")->GetValueType(), eAmf::Array); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get("Null")->GetValueType(), eAmf::Null); - std::cout << "test" << std::endl; ASSERT_EQ(array.Get>("Undefined")->GetValueType(), eAmf::Undefined); - std::cout << "test" << std::endl; } TEST(dCommonTests, AMF3InsertionDenseTest) { From d8476b732544086d7ff21dcfb20fa8af7b6b0161 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Tue, 21 Nov 2023 00:04:33 -0800 Subject: [PATCH 2/7] working End of optimizations for now going faster --- dCommon/BinaryIO.cpp | 41 ----- dCommon/BinaryIO.h | 53 ++++++- dCommon/dClient/PackIndex.cpp | 19 +-- dZoneManager/Level.cpp | 144 +++++------------ dZoneManager/Level.h | 14 +- dZoneManager/Zone.cpp | 280 ++++++++++++---------------------- dZoneManager/Zone.h | 4 +- dZoneManager/dZoneManager.cpp | 27 ---- dZoneManager/dZoneManager.h | 2 - 9 files changed, 192 insertions(+), 392 deletions(-) diff --git a/dCommon/BinaryIO.cpp b/dCommon/BinaryIO.cpp index 22e4de609..b64fb3bae 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 a117ad0db..d1e728caa 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 55c26b488..0d7a7fe98 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 4c6ff93c6..25c0d4a7e 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 6f56e0731..1f0b4f2e1 100644 --- a/dZoneManager/Level.h +++ b/dZoneManager/Level.h @@ -27,33 +27,21 @@ class Level { 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 18de939c3..56abb743a 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; - - 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(); - } - } + 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) 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; -void Zone::AddRevision(LWOSCENEID sceneID, uint32_t revision) { - for (std::pair item : m_MapRevisions) { - if (item.first == sceneID) return; + scene.level->m_ChunkHeaders.begin()->second.lwoSceneID = sceneID; + AddRevision(scene.level->m_ChunkHeaders.begin()->second.lwoSceneID, scene.level->m_ChunkHeaders.begin()->second.fileInfo.revision); } - - 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(); +void Zone::AddRevision(LWOSCENEID sceneID, uint32_t revision) { + 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; + + auto trigger = scene->second.triggers.find(triggerID); + if (trigger == scene->second.triggers.end()) return nullptr; - return m_Scenes[sceneID].triggers[triggerID]; + 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 ff9311545..978671af1 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -210,7 +210,6 @@ class Zone { 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 @@ class Zone { 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 @@ class Zone { //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 137a9cab2..1f68d0846 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 b5db3f6e0..4e512d228 100644 --- a/dZoneManager/dZoneManager.h +++ b/dZoneManager/dZoneManager.h @@ -14,7 +14,6 @@ class dZoneManager { 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 @@ class dZoneManager { 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); From f8a01dead33e24338c198018fd92ee5bfaa1e55d Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Tue, 21 Nov 2023 01:22:54 -0800 Subject: [PATCH 3/7] Remove extraneous compare function std::less already does this in a map. --- dZoneManager/Zone.h | 5 ++--- dZoneManager/dZMCommon.h | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index 978671af1..a62a81edc 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -241,15 +241,14 @@ class Zone { 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::map m_Scenes; + std::map m_Scenes; std::vector m_SceneTransitions; uint32_t m_PathDataLength; uint32_t m_PathChunkVersion; std::vector m_Paths; - std::map m_MapRevisions; //rhs is the revision! - + std::map m_MapRevisions; //rhs is the revision! //private ("helper") functions: void LoadScene(std::istream& file); void LoadLUTriggers(std::string triggerFile, SceneRef& scene); diff --git a/dZoneManager/dZMCommon.h b/dZoneManager/dZMCommon.h index 738fc283e..bee37e5ab 100644 --- a/dZoneManager/dZMCommon.h +++ b/dZoneManager/dZMCommon.h @@ -5,10 +5,6 @@ #include "LDFFormat.h" #include -struct mapCompareLwoSceneIDs { - bool operator()(const LWOSCENEID& lhs, const LWOSCENEID& rhs) const { return lhs < rhs; } -}; - struct SceneObject { LWOOBJID id; LOT lot; From 1ea65b3549626da714c4a6510a3b50e8c74a48cc Mon Sep 17 00:00:00 2001 From: Jettford Date: Wed, 22 Nov 2023 01:40:09 +0000 Subject: [PATCH 4/7] gaming --- dCommon/FdbToSqlite.cpp | 8 ++--- dCommon/FdbToSqlite.h | 4 +-- dCommon/dClient/AssetManager.cpp | 7 ++-- dCommon/dClient/AssetManager.h | 18 +++++++++-- dGame/UserManager.cpp | 32 ++++++++----------- dGame/dInventory/Item.cpp | 13 ++------ dGame/dPropertyBehaviors/ControlBehaviors.cpp | 13 +++----- dGame/dUtilities/BrickDatabase.cpp | 12 ++----- dGame/dUtilities/SlashCommandHandler.cpp | 8 ++--- dZoneManager/Level.cpp | 11 +++---- dZoneManager/Zone.cpp | 24 +++++++++----- 11 files changed, 67 insertions(+), 83 deletions(-) diff --git a/dCommon/FdbToSqlite.cpp b/dCommon/FdbToSqlite.cpp index 0b2c546c3..d8409cd5f 100644 --- a/dCommon/FdbToSqlite.cpp +++ b/dCommon/FdbToSqlite.cpp @@ -28,19 +28,17 @@ FdbToSqlite::Convert::Convert(std::string binaryOutPath) { this->m_BinaryOutPath = binaryOutPath; } -bool FdbToSqlite::Convert::ConvertDatabase(AssetMemoryBuffer& buffer) { +bool FdbToSqlite::Convert::ConvertDatabase(AssetStream& buffer) { if (m_ConversionStarted) return false; - std::istream cdClientBuffer(&buffer); - this->m_ConversionStarted = true; try { CDClientDatabase::Connect(m_BinaryOutPath + "/CDServer.sqlite"); CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;"); - int32_t numberOfTables = ReadInt32(cdClientBuffer); - ReadTables(numberOfTables, cdClientBuffer); + int32_t numberOfTables = ReadInt32(buffer); + ReadTables(numberOfTables, buffer); CDClientDatabase::ExecuteQuery("COMMIT;"); } catch (CppSQLite3Exception& e) { diff --git a/dCommon/FdbToSqlite.h b/dCommon/FdbToSqlite.h index 7aad27033..b0d20aee3 100644 --- a/dCommon/FdbToSqlite.h +++ b/dCommon/FdbToSqlite.h @@ -7,7 +7,7 @@ #include #include -class AssetMemoryBuffer; +#include "AssetManager.h" enum class eSqliteDataType : int32_t; @@ -27,7 +27,7 @@ namespace FdbToSqlite { * * @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. diff --git a/dCommon/dClient/AssetManager.cpp b/dCommon/dClient/AssetManager.cpp index c672b3350..00bae6ce0 100644 --- a/dCommon/dClient/AssetManager.cpp +++ b/dCommon/dClient/AssetManager.cpp @@ -152,13 +152,12 @@ bool AssetManager::GetFile(const char* name, char** data, uint32_t* len) { return success; } -AssetMemoryBuffer AssetManager::GetFileAsBuffer(const char* name) { - char* buf; - uint32_t len; +AssetStream AssetManager::GetFile(const char* name) { + char* buf; uint32_t 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) { diff --git a/dCommon/dClient/AssetManager.h b/dCommon/dClient/AssetManager.h index d25434892..7e36b4b57 100644 --- a/dCommon/dClient/AssetManager.h +++ b/dCommon/dClient/AssetManager.h @@ -25,6 +25,10 @@ struct AssetMemoryBuffer : std::streambuf { this->setg(base, base, base + n); } + ~AssetMemoryBuffer() { + free(m_Base); + } + 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); } @@ -40,9 +44,17 @@ struct AssetMemoryBuffer : std::streambuf { setg(eback(), eback() + off, egptr()); return gptr() - eback(); } +}; + +struct AssetStream : std::istream { + AssetStream(char* base, std::ptrdiff_t n, bool success) : std::istream(new AssetMemoryBuffer(base, n, success)) {} + + ~AssetStream() { + delete rdbuf(); + } - void close() { - free(m_Base); + operator bool() { + return reinterpret_cast(rdbuf())->m_Success; } }; @@ -56,7 +68,7 @@ class AssetManager { bool HasFile(const char* name); bool GetFile(const char* name, char** data, uint32_t* len); - AssetMemoryBuffer GetFileAsBuffer(const char* name); + AssetStream GetFile(const char* name); private: void LoadPackIndex(); diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 9820636af..f5fa9ce02 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -44,57 +44,53 @@ inline void StripCR(std::string& str) { void UserManager::Initialize() { std::string line; - AssetMemoryBuffer fnBuff = Game::assetManager->GetFileAsBuffer("names/minifigname_first.txt"); - if (!fnBuff.m_Success) { + auto fnStream = Game::assetManager->GetFile("names/minifigname_first.txt"); + if (!fnStream) { 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."); } - std::istream fnStream = std::istream(&fnBuff); + while (std::getline(fnStream, line, '\n')) { std::string name = line; StripCR(name); m_FirstNames.push_back(name); } - fnBuff.close(); - AssetMemoryBuffer mnBuff = Game::assetManager->GetFileAsBuffer("names/minifigname_middle.txt"); - if (!mnBuff.m_Success) { + auto mnStream = Game::assetManager->GetFile("names/minifigname_middle.txt"); + if (!mnStream) { 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."); } - std::istream mnStream = std::istream(&mnBuff); + while (std::getline(mnStream, line, '\n')) { std::string name = line; StripCR(name); m_MiddleNames.push_back(name); } - mnBuff.close(); - AssetMemoryBuffer lnBuff = Game::assetManager->GetFileAsBuffer("names/minifigname_last.txt"); - if (!lnBuff.m_Success) { + auto lnStream = Game::assetManager->GetFile("names/minifigname_last.txt"); + if (!lnStream) { 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."); } - std::istream lnStream = std::istream(&lnBuff); + while (std::getline(lnStream, line, '\n')) { std::string name = line; StripCR(name); m_LastNames.push_back(name); } - lnBuff.close(); - //Load our pre-approved names: - AssetMemoryBuffer chatListBuff = Game::assetManager->GetFileAsBuffer("chatplus_en_us.txt"); - if (!chatListBuff.m_Success) { + // Load our pre-approved names: + auto chatListStream = Game::assetManager->GetFile("chatplus_en_us.txt"); + if (!chatListStream) { 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."); } - std::istream chatListStream = std::istream(&chatListBuff); + while (std::getline(chatListStream, line, '\n')) { StripCR(line); m_PreapprovedNames.push_back(line); } - chatListBuff.close(); } UserManager::~UserManager() { @@ -207,7 +203,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) { chars[i]->SaveXMLToDatabase(); chars[i]->GetEntity()->SetCharacter(nullptr); - + delete chars[i]; } diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 438bec2f7..9e4b46f6d 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -423,25 +423,16 @@ void Item::DisassembleModel(uint32_t numToDismantle) { if (renderAssetSplit.empty()) return; 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()); return; } - std::istream file(&buffer); - - if (!file.good()) { - buffer.close(); - return; - } - std::stringstream data; data << file.rdbuf(); - buffer.close(); - uint32_t fileSize; file.seekg(0, std::ios::end); fileSize = static_cast(file.tellg()); diff --git a/dGame/dPropertyBehaviors/ControlBehaviors.cpp b/dGame/dPropertyBehaviors/ControlBehaviors.cpp index 3dbd777a7..b143cbc81 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviors.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviors.cpp @@ -324,14 +324,9 @@ void ControlBehaviors::ProcessCommand(Entity* modelEntity, const SystemAddress& } ControlBehaviors::ControlBehaviors() { - auto blocksDefStreamBuffer = Game::assetManager->GetFileAsBuffer("ui\\ingame\\blocksdef.xml"); - if (!blocksDefStreamBuffer.m_Success) { - LOG("failed to open blocksdef"); - return; - } - std::istream blocksBuffer(&blocksDefStreamBuffer); - if (!blocksBuffer.good()) { - LOG("Blocks buffer is not good!"); + auto blocksBuffer = Game::assetManager->GetFile("ui\\ingame\\blocksdef.xml"); + if (!blocksBuffer) { + LOG("Failed to open blocksdef.xml"); return; } @@ -342,7 +337,7 @@ ControlBehaviors::ControlBehaviors() { std::string buffer{}; bool commentBlockStart = false; 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. if (read.find("