2022-12-14 08:40:15 +00:00

195 lines
6.3 KiB
C++

#include <STDInclude.hpp>
#include "IGameWorldMp.hpp"
#define IW4X_GAMEWORLD_VERSION 1
namespace Assets
{
void IGameWorldMp::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{
AssertSize(Game::GameWorldMp, 8);
Utils::Stream* buffer = builder->getBuffer();
Game::GameWorldMp* asset = header.gameWorldMp;
Game::GameWorldMp* dest = buffer->dest<Game::GameWorldMp>();
buffer->save(asset);
buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL);
if (asset->name)
{
buffer->saveString(builder->getAssetName(this->getType(), asset->name));
Utils::Stream::ClearPointer(&dest->name);
}
if (asset->g_glassData)
{
buffer->align(Utils::Stream::ALIGN_4);
// Save_G_GlassData
{
AssertSize(Game::G_GlassData, 128);
Game::G_GlassData* destGlass = buffer->dest<Game::G_GlassData>();
buffer->save(asset->g_glassData);
if (asset->g_glassData->glassPieces)
{
AssertSize(Game::G_GlassPiece, 12);
buffer->align(Utils::Stream::ALIGN_4);
buffer->saveArray(asset->g_glassData->glassPieces, asset->g_glassData->pieceCount);
Utils::Stream::ClearPointer(&destGlass->glassPieces);
}
if (asset->g_glassData->glassNames)
{
AssertSize(Game::G_GlassName, 12);
buffer->align(Utils::Stream::ALIGN_4);
Game::G_GlassName* destGlassNames = buffer->dest<Game::G_GlassName>();
buffer->saveArray(asset->g_glassData->glassNames, asset->g_glassData->glassNameCount);
for (unsigned int i = 0; i < asset->g_glassData->glassNameCount; ++i)
{
Game::G_GlassName* destGlassName = &destGlassNames[i];
Game::G_GlassName* glassName = &asset->g_glassData->glassNames[i];
if (glassName->nameStr)
{
buffer->saveString(glassName->nameStr);
Utils::Stream::ClearPointer(&destGlassName->nameStr);
}
if (glassName->pieceIndices)
{
buffer->align(Utils::Stream::ALIGN_2);
buffer->saveArray(glassName->pieceIndices, glassName->pieceCount);
Utils::Stream::ClearPointer(&destGlassName->pieceIndices);
}
}
Utils::Stream::ClearPointer(&destGlass->glassNames);
}
}
Utils::Stream::ClearPointer(&dest->g_glassData);
}
buffer->popBlock();
}
void IGameWorldMp::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder)
{
std::string name = _name;
Utils::String::Replace(name, "maps/mp/", "");
Utils::String::Replace(name, ".d3dbsp", "");
Components::FileSystem::File gameWorld(std::format("gameworld/{}.iw4x.json", name));
if (gameWorld.exists())
{
nlohmann::json gameWorldJson;
try
{
gameWorldJson = nlohmann::json::parse(gameWorld.getBuffer());
}
catch (const std::exception& e)
{
Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid JSON for gameworld {}! {}", name, e.what());
return;
}
auto* asset = builder->getAllocator()->allocate<Game::GameWorldMp>();
if (!gameWorldJson.is_object())
{
Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid GameWorldMp json for {}\n", name);
return;
}
auto version = gameWorldJson["version"].is_number() ? gameWorldJson["version"].get<int>() : 0;
if (version != IW4X_GAMEWORLD_VERSION)
{
Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Invalid GameWorld json version for {}, expected {} and got {}\n", name, IW4X_GAMEWORLD_VERSION, version);
return;
}
if (!gameWorldJson["name"].is_string())
{
Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Missing gameworld name! on {}\n", name);
return;
}
asset->name = builder->getAllocator()->duplicateString(gameWorldJson["name"].get<std::string>());
auto glassData = builder->getAllocator()->allocate<Game::G_GlassData>();
if (gameWorldJson["glassData"].is_object())
{
auto jsonGlassData = gameWorldJson["glassData"];
try
{
glassData->damageToDestroy = jsonGlassData["damageToDestroy"].get<unsigned short>();
glassData->damageToWeaken = jsonGlassData["damageToWeaken"].get<unsigned short>();
if (jsonGlassData["glassNames"].is_array())
{
nlohmann::json::array_t glassNames = jsonGlassData["glassNames"];
glassData->glassNameCount = glassNames.size();
glassData->glassNames = builder->getAllocator()->allocateArray<Game::G_GlassName>(glassData->glassNameCount);
for (size_t i = 0; i < glassData->glassNameCount; i++)
{
auto jsonGlassName = glassNames[i];
glassData->glassNames[i].nameStr = builder->getAllocator()->duplicateString(jsonGlassName["nameStr"]);
glassData->glassNames[i].name = jsonGlassName["name"].get<unsigned short>();
if (jsonGlassName["piecesIndices"].is_array())
{
nlohmann::json::array_t jsonPiecesIndices = jsonGlassName["piecesIndices"];
glassData->glassNames[i].pieceCount = static_cast<unsigned short>(jsonPiecesIndices.size());
for (size_t j = 0; j < glassData->glassNames[i].pieceCount; j++)
{
glassData->glassNames[i].pieceIndices[j] = jsonPiecesIndices[j].get<unsigned short>();
}
}
}
}
if (gameWorldJson["glassPieces"].is_array())
{
nlohmann::json::array_t glassPieces = gameWorldJson["glassPieces"];
glassData->pieceCount = glassPieces.size();
glassData->glassPieces = builder->getAllocator()->allocateArray<Game::G_GlassPiece>(glassData->pieceCount);
for (size_t i = 0; i < glassData->pieceCount; i++)
{
glassData->glassPieces[i].collapseTime = glassPieces[i]["collapseTime"].get<unsigned short>();
glassData->glassPieces[i].damageTaken = glassPieces[i]["damageTaken"].get<unsigned short>();
glassData->glassPieces[i].lastStateChangeTime = glassPieces[i]["lastStateChangeTime"].get<int>();
glassData->glassPieces[i].impactDir = glassPieces[i]["impactDir"].get<char>();
nlohmann::json::array_t jsonPos = glassPieces[i]["impactPos"];
glassData->glassPieces[i].impactPos[0] = jsonPos[0].get<char>();
glassData->glassPieces[i].impactPos[1] = jsonPos[1].get<char>();
}
}
}
catch (const nlohmann::json::exception& e)
{
Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Malformed GameWorldMp json for {} ({})\n", name, e.what());
return;
}
}
asset->g_glassData = glassData;
header->gameWorldMp = asset;
}
}
}