DarkflameServer/dGame/dUtilities/BrickDatabase.cpp
David Markowitz 1d5c71eb9b
Fix Pet Taming causing seg fault (#818)
* Fix Pet Taming

* Fix Pet Taming

* fix pet taming path loading
just make it go to build file since the asset managet handles intermediate steps
there is never res in the path in the live db, so no need to check

* special case BrickModels to uppercase if unpacked
remove redundent variable

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2022-11-05 19:09:26 -05:00

97 lines
2.4 KiB
C++

#include <sstream>
#include <fstream>
#include "BrickDatabase.h"
#include "Game.h"
#include "AssetManager.h"
std::vector<Brick> BrickDatabase::emptyCache{};
BrickDatabase* BrickDatabase::m_Address = nullptr;
BrickDatabase::BrickDatabase() = default;
BrickDatabase::~BrickDatabase() = default;
std::vector<Brick>& BrickDatabase::GetBricks(const std::string& lxfmlPath) {
const auto cached = m_Cache.find(lxfmlPath);
if (cached != m_Cache.end()) {
return cached->second;
}
AssetMemoryBuffer buffer = Game::assetManager->GetFileAsBuffer((lxfmlPath).c_str());
std::istream file(&buffer);
if (!file.good()) {
return emptyCache;
}
std::stringstream data;
data << file.rdbuf();
if (data.str().empty()) {
buffer.close();
return emptyCache;
}
buffer.close();
auto* doc = new tinyxml2::XMLDocument();
if (doc->Parse(data.str().c_str(), data.str().size()) != 0) {
delete doc;
return emptyCache;
}
std::vector<Brick> parts;
auto* lxfml = doc->FirstChildElement("LXFML");
auto* bricks = lxfml->FirstChildElement("Bricks");
std::string searchTerm = "Brick";
if (!bricks) {
searchTerm = "Part";
bricks = lxfml->FirstChildElement("Scene")->FirstChildElement("Model")->FirstChildElement("Group");
if (!bricks) {
return emptyCache;
}
}
auto* currentBrick = bricks->FirstChildElement(searchTerm.c_str());
while (currentBrick != nullptr) {
auto* part = currentBrick->FirstChildElement("Part");
if (part == nullptr) part = currentBrick;
if (part->Attribute("designID") != nullptr) {
Brick brick{ static_cast<uint32_t>(part->IntAttribute("designID")) };
// Depends on the file, some don't specify a list but just a single material
const auto* materialList = part->Attribute("materials");
const auto* materialID = part->Attribute("materialID");
if (materialList != nullptr) {
std::string materialString(materialList);
const auto materials = GeneralUtils::SplitString(materialString, ',');
if (!materials.empty()) {
brick.materialID = std::stoi(materials[0]);
} else {
brick.materialID = 0;
}
} else if (materialID != nullptr) {
brick.materialID = std::stoi(materialID);
} else {
brick.materialID = 0; // This is bad, makes it so the minigame can't be played
}
parts.push_back(brick);
}
currentBrick = currentBrick->NextSiblingElement(searchTerm.c_str());
}
m_Cache[lxfmlPath] = parts;
delete doc;
return m_Cache[lxfmlPath];
}