mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-05-09 16:11:17 +00:00

* Add utilities for formats * Normalize model positions when placing in the world Have tested that placing a small and very large model both place and are located at the correct position. * add migration * Update Logger.cpp * add some notes and remove some logs * change arguments and add eof check Revert "fix: buff station cycling and dying too soon" This reverts commit 1c6cb2921e10eb2000ac40007d0c2636ba2ac151. fix: buff station cycling and dying too soon Tested that the buff station now only cycles after it has been built and has been alive for 25 seconds.
116 lines
3.3 KiB
C++
116 lines
3.3 KiB
C++
#include "Lxfml.h"
|
|
|
|
#include "GeneralUtils.h"
|
|
#include "StringifiedEnum.h"
|
|
#include "TinyXmlUtils.h"
|
|
|
|
#include <ranges>
|
|
|
|
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data) {
|
|
Result toReturn;
|
|
tinyxml2::XMLDocument doc;
|
|
const auto err = doc.Parse(data.data());
|
|
if (err != tinyxml2::XML_SUCCESS) {
|
|
LOG("Failed to parse xml %s.", StringifiedEnum::ToString(err).data());
|
|
return toReturn;
|
|
}
|
|
|
|
TinyXmlUtils::DocumentReader reader(doc);
|
|
std::map<std::string/* refID */, std::string> transformations;
|
|
|
|
auto lxfml = reader["LXFML"];
|
|
if (!lxfml) {
|
|
LOG("Failed to find LXFML element.");
|
|
return toReturn;
|
|
}
|
|
|
|
// First get all the positions of bricks
|
|
for (const auto& brick : lxfml["Bricks"]) {
|
|
const auto* part = brick.FirstChildElement("Part");
|
|
if (part) {
|
|
const auto* bone = part->FirstChildElement("Bone");
|
|
if (bone) {
|
|
auto* transformation = bone->Attribute("transformation");
|
|
if (transformation) {
|
|
auto* refID = bone->Attribute("refID");
|
|
if (refID) transformations[refID] = transformation;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// These points are well out of bounds for an actual player
|
|
NiPoint3 lowest{ 10'000.0f, 10'000.0f, 10'000.0f };
|
|
NiPoint3 highest{ -10'000.0f, -10'000.0f, -10'000.0f };
|
|
|
|
// Calculate the lowest and highest points on the entire model
|
|
for (const auto& transformation : transformations | std::views::values) {
|
|
auto split = GeneralUtils::SplitString(transformation, ',');
|
|
if (split.size() < 12) {
|
|
LOG("Not enough in the split?");
|
|
continue;
|
|
}
|
|
|
|
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
|
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
|
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
|
if (x < lowest.x) lowest.x = x;
|
|
if (y < lowest.y) lowest.y = y;
|
|
if (z < lowest.z) lowest.z = z;
|
|
|
|
if (highest.x < x) highest.x = x;
|
|
if (highest.y < y) highest.y = y;
|
|
if (highest.z < z) highest.z = z;
|
|
}
|
|
|
|
auto delta = (highest - lowest) / 2.0f;
|
|
auto newRootPos = lowest + delta;
|
|
|
|
// Clamp the Y to the lowest point on the model
|
|
newRootPos.y = lowest.y;
|
|
|
|
// Adjust all positions to account for the new origin
|
|
for (auto& transformation : transformations | std::views::values) {
|
|
auto split = GeneralUtils::SplitString(transformation, ',');
|
|
if (split.size() < 12) {
|
|
LOG("Not enough in the split?");
|
|
continue;
|
|
}
|
|
|
|
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x;
|
|
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y;
|
|
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z;
|
|
std::stringstream stream;
|
|
for (int i = 0; i < 9; i++) {
|
|
stream << split[i];
|
|
stream << ',';
|
|
}
|
|
stream << x << ',' << y << ',' << z;
|
|
transformation = stream.str();
|
|
}
|
|
|
|
// Finally write the new transformation back into the lxfml
|
|
for (auto& brick : lxfml["Bricks"]) {
|
|
auto* part = brick.FirstChildElement("Part");
|
|
if (part) {
|
|
auto* bone = part->FirstChildElement("Bone");
|
|
if (bone) {
|
|
auto* transformation = bone->Attribute("transformation");
|
|
if (transformation) {
|
|
auto* refID = bone->Attribute("refID");
|
|
if (refID) {
|
|
bone->SetAttribute("transformation", transformations[refID].c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tinyxml2::XMLPrinter printer;
|
|
doc.Print(&printer);
|
|
|
|
toReturn.lxfml = printer.CStr();
|
|
toReturn.center = newRootPos;
|
|
return toReturn;
|
|
}
|