[Json] Sorround with try/catch (#531)

* [Json] Sorround with try/catch

* Minor format fix
This commit is contained in:
Edo 2022-10-16 16:17:42 +01:00 committed by GitHub
parent bff0d22e81
commit c7ae27a664
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 317 additions and 256 deletions

View File

@ -80,7 +80,7 @@ namespace Assets
void IFont_s::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IFont_s::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{ {
Game::Font_s *asset = header.font; const auto* asset = header.font;
if (asset->material) if (asset->material)
{ {
@ -98,27 +98,33 @@ namespace Assets
Components::FileSystem::File fontDefFile(Utils::String::VA("%s.json", name.data())); Components::FileSystem::File fontDefFile(Utils::String::VA("%s.json", name.data()));
Components::FileSystem::File fontFile(Utils::String::VA("%s.ttf", name.data())); Components::FileSystem::File fontFile(Utils::String::VA("%s.ttf", name.data()));
if (fontDefFile.exists() && fontFile.exists()) if (!fontDefFile.exists() || !fontFile.exists())
{ {
auto fontDef = nlohmann::json::parse(fontDefFile.getBuffer());
if (!fontDef.is_object())
{
Components::Logger::Error(Game::ERR_FATAL, "Font define {} is invalid", name);
return; return;
} }
int w = fontDef["textureWidth"].get<int>(); nlohmann::json fontDef = nlohmann::json::parse(fontDefFile.getBuffer());
int h = fontDef["textureHeight"].get<int>(); try
{
fontDef = nlohmann::json::parse(fontDefFile.getBuffer());
}
catch (const nlohmann::json::parse_error& ex)
{
Components::Logger::Error(Game::ERR_FATAL, "Json Parse Error: {}. Font {} is invalid", ex.what(), name);
return;
}
int size = fontDef["size"].get<int>(); auto w = fontDef["textureWidth"].get<int>();
int yOffset = fontDef["yOffset"].get<int>(); auto h = fontDef["textureHeight"].get<int>();
auto size = fontDef["size"].get<int>();
auto yOffset = fontDef["yOffset"].get<int>();
auto* pixels = builder->getAllocator()->allocateArray<uint8_t>(w * h); auto* pixels = builder->getAllocator()->allocateArray<uint8_t>(w * h);
// Setup assets // Setup assets
const auto* texName = builder->getAllocator()->duplicateString(Utils::String::VA("if_%s", name.data() + 6 /* skip "fonts/" */)); const auto* texName = builder->getAllocator()->duplicateString(Utils::String::VA("if_%s", name.data() + 6 /* skip "fonts/" */));
const auto* fontName = builder->getAllocator()->duplicateString(name.data()); const auto* fontName = builder->getAllocator()->duplicateString(name);
const auto* glowMaterialName = builder->getAllocator()->duplicateString(Utils::String::VA("%s_glow", name.data())); const auto* glowMaterialName = builder->getAllocator()->duplicateString(Utils::String::VA("%s_glow", name.data()));
auto* image = builder->getAllocator()->allocate<Game::GfxImage>(); auto* image = builder->getAllocator()->allocate<Game::GfxImage>();
@ -142,20 +148,22 @@ namespace Assets
glowMaterial->textureTable = material->textureTable; glowMaterial->textureTable = material->textureTable;
glowMaterial->info.name = glowMaterialName; glowMaterial->info.name = glowMaterialName;
std::vector<uint16_t> charset; std::vector<std::uint16_t> charset;
if (fontDef["charset"].is_array()) if (fontDef["charset"].is_array())
{ {
nlohmann::json::array_t charsetArray = fontDef["charset"]; nlohmann::json::array_t charsetArray = fontDef["charset"];
for (auto& ch : charsetArray) for (auto& ch : charsetArray)
charset.push_back(static_cast<uint16_t>(ch.get<int>())); {
charset.push_back(static_cast<std::uint16_t>(ch.get<int>()));
}
// order matters // order matters
std::sort(charset.begin(), charset.end()); std::ranges::sort(charset);
for (uint16_t i = 32; i < 128; i++) for (std::uint16_t i = 32; i < 128; i++)
{ {
if (std::find(charset.begin(), charset.end(), i) == charset.end()) if (std::ranges::find(charset, i) == charset.end())
{ {
Components::Logger::Error(Game::ERR_FATAL, "Font {} missing codepoint {}", name.data(), i); Components::Logger::Error(Game::ERR_FATAL, "Font {} missing codepoint {}", name.data(), i);
} }
@ -163,9 +171,11 @@ namespace Assets
} }
else else
{ {
for (uint16_t i = 32; i < 128; i++) for (std::uint16_t i = 32; i < 128; i++)
{
charset.push_back(i); charset.push_back(i);
} }
}
auto* font = builder->getAllocator()->allocate<Game::Font_s>(); auto* font = builder->getAllocator()->allocate<Game::Font_s>();
@ -173,7 +183,7 @@ namespace Assets
font->pixelHeight = size; font->pixelHeight = size;
font->material = material; font->material = material;
font->glowMaterial = glowMaterial; font->glowMaterial = glowMaterial;
font->glyphCount = charset.size(); font->glyphCount = static_cast<int>(charset.size());
font->glyphs = builder->getAllocator()->allocateArray<Game::Glyph>(charset.size()); font->glyphs = builder->getAllocator()->allocateArray<Game::Glyph>(charset.size());
// Generate glyph data // Generate glyph data
@ -236,7 +246,7 @@ namespace Assets
// Generate RGBA data // Generate RGBA data
auto* rgbaPixels = outIwi.data() + sizeof(Game::GfxImageFileHeader); auto* rgbaPixels = outIwi.data() + sizeof(Game::GfxImageFileHeader);
for (int i = 0; i < w * h * 4; i += 4) for (auto i = 0; i < w * h * 4; i += 4)
{ {
rgbaPixels[i + 0] = static_cast<char>(255); rgbaPixels[i + 0] = static_cast<char>(255);
rgbaPixels[i + 1] = static_cast<char>(255); rgbaPixels[i + 1] = static_cast<char>(255);
@ -246,7 +256,6 @@ namespace Assets
Utils::IO::WriteFile(Utils::String::VA("userraw\\images\\%s.iwi", texName), outIwi); Utils::IO::WriteFile(Utils::String::VA("userraw\\images\\%s.iwi", texName), outIwi);
} }
}
void IFont_s::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IFont_s::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{ {

View File

@ -30,7 +30,8 @@ namespace Assets
"_add_lin_nofog", "_add_lin_nofog",
}; };
std::map<std::string, std::string> techSetCorrespondance = { static std::unordered_map<std::string, std::string> techSetCorrespondance =
{
{"effect", "effect_blend"}, {"effect", "effect_blend"},
{"effect", "effect_blend"}, {"effect", "effect_blend"},
{"effect_nofog", "effect_blend_nofog"}, {"effect_nofog", "effect_blend_nofog"},
@ -50,12 +51,6 @@ namespace Assets
{"mc_unlit_nofog", "mc_unlit_blend_nofog_ua"}, {"mc_unlit_nofog", "mc_unlit_blend_nofog_ua"},
{"mc_unlit", "mc_unlit_replace_lin_nocast"}, {"mc_unlit", "mc_unlit_replace_lin_nocast"},
{"mc_unlit_alphatest", "mc_unlit_blend_lin"} {"mc_unlit_alphatest", "mc_unlit_blend_lin"}
/*,
{"", ""},
{"", ""},
{"", ""},
{"", ""},
{"", ""},*/
}; };
Components::FileSystem::File materialFile(Utils::String::VA("materials/%s.iw4xMaterial", name.data())); Components::FileSystem::File materialFile(Utils::String::VA("materials/%s.iw4xMaterial", name.data()));
@ -64,7 +59,7 @@ namespace Assets
Utils::Stream::Reader reader(builder->getAllocator(), materialFile.getBuffer()); Utils::Stream::Reader reader(builder->getAllocator(), materialFile.getBuffer());
char* magic = reader.readArray<char>(7); char* magic = reader.readArray<char>(7);
if (std::memcmp(magic, "IW4xMat", 7)) if (std::memcmp(magic, "IW4xMat", 7) != 0)
{ {
Components::Logger::Error(Game::ERR_FATAL, "Reading material '{}' failed, header is invalid!", name); Components::Logger::Error(Game::ERR_FATAL, "Reading material '{}' failed, header is invalid!", name);
} }
@ -76,7 +71,7 @@ namespace Assets
Components::Logger::Error(Game::ERR_FATAL, "Reading material '{}' failed, expected version is {}, but it was {}!", name, IW4X_MAT_VERSION, version); Components::Logger::Error(Game::ERR_FATAL, "Reading material '{}' failed, expected version is {}, but it was {}!", name, IW4X_MAT_VERSION, version);
} }
Game::Material* asset = reader.readObject<Game::Material>(); auto* asset = reader.readObject<Game::Material>();
if (asset->info.name) if (asset->info.name)
{ {
@ -408,13 +403,13 @@ namespace Assets
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
builder->storePointer(asset->textureTable); builder->storePointer(asset->textureTable);
Game::MaterialTextureDef* destTextureTable = buffer->dest<Game::MaterialTextureDef>(); auto* destTextureTable = buffer->dest<Game::MaterialTextureDef>();
buffer->saveArray(asset->textureTable, asset->textureCount); buffer->saveArray(asset->textureTable, asset->textureCount);
for (char i = 0; i < asset->textureCount; ++i) for (std::uint8_t i = 0; i < asset->textureCount; ++i)
{ {
Game::MaterialTextureDef* destTextureDef = &destTextureTable[i]; auto* destTextureDef = &destTextureTable[i];
Game::MaterialTextureDef* textureDef = &asset->textureTable[i]; auto* textureDef = &asset->textureTable[i];
if (textureDef->semantic == SEMANTIC_WATER_MAP) if (textureDef->semantic == SEMANTIC_WATER_MAP)
{ {

View File

@ -12,16 +12,26 @@ namespace Assets
return; return;
} }
Game::snd_alias_list_t* aliasList = builder->getAllocator()->allocate<Game::snd_alias_list_t>(); auto* aliasList = builder->getAllocator()->allocate<Game::snd_alias_list_t>();
if (!aliasList) if (!aliasList)
{ {
Components::Logger::Print("Error allocating memory for sound alias structure!\n"); Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Failed to allocate memory for sound alias structure!\n");
return; return;
} }
nlohmann::json infoData = nlohmann::json::parse(aliasFile.getBuffer()); nlohmann::json infoData;
nlohmann::json aliasesContainer = infoData["head"]; try
{
infoData = nlohmann::json::parse(aliasFile.getBuffer());
}
catch (const nlohmann::json::parse_error& ex)
{
Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return;
}
nlohmann::json aliasesContainer = infoData["head"];
nlohmann::json::array_t aliases = aliasesContainer; nlohmann::json::array_t aliases = aliasesContainer;
aliasList->count = aliases.size(); aliasList->count = aliases.size();
@ -34,7 +44,7 @@ namespace Assets
return; return;
} }
aliasList->aliasName = builder->getAllocator()->duplicateString(name.c_str()); aliasList->aliasName = builder->getAllocator()->duplicateString(name);
for (size_t i = 0; i < aliasList->count; i++) for (size_t i = 0; i < aliasList->count; i++)
{ {
@ -288,19 +298,14 @@ namespace Assets
if (volumeFalloffCurve.is_string()) if (volumeFalloffCurve.is_string())
{ {
std::string fallOffCurve = volumeFalloffCurve.get<std::string>(); auto fallOffCurve = volumeFalloffCurve.get<std::string>();
if (fallOffCurve.size() == 0) if (fallOffCurve.empty())
{ {
fallOffCurve = "$default"; fallOffCurve = "$default";
} }
auto curve = Components::AssetHandler::FindAssetForZone( auto curve = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, fallOffCurve, builder).sndCurve;
Game::XAssetType::ASSET_TYPE_SOUND_CURVE,
fallOffCurve.c_str(),
builder
).sndCurve;
alias->volumeFalloffCurve = curve; alias->volumeFalloffCurve = curve;
} }
@ -376,9 +381,9 @@ namespace Assets
{ {
AssertSize(Game::snd_alias_list_t, 12); AssertSize(Game::snd_alias_list_t, 12);
Utils::Stream* buffer = builder->getBuffer(); auto* buffer = builder->getBuffer();
Game::snd_alias_list_t* asset = header.sound; auto* asset = header.sound;
Game::snd_alias_list_t* dest = buffer->dest<Game::snd_alias_list_t>(); auto* dest = buffer->dest<Game::snd_alias_list_t>();
buffer->save(asset); buffer->save(asset);
buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL);
@ -402,7 +407,7 @@ namespace Assets
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
builder->storePointer(asset->head); builder->storePointer(asset->head);
Game::snd_alias_t* destHead = buffer->dest<Game::snd_alias_t>(); auto* destHead = buffer->dest<Game::snd_alias_t>();
buffer->saveArray(asset->head, asset->count); buffer->saveArray(asset->head, asset->count);
for (unsigned int i = 0; i < asset->count; ++i) for (unsigned int i = 0; i < asset->count; ++i)
@ -453,7 +458,7 @@ namespace Assets
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
builder->storePointer(alias->soundFile); builder->storePointer(alias->soundFile);
Game::SoundFile* destSoundFile = buffer->dest<Game::SoundFile>(); auto* destSoundFile = buffer->dest<Game::SoundFile>();
buffer->save(alias->soundFile); buffer->save(alias->soundFile);
// Save_SoundFileRef // Save_SoundFileRef
@ -503,7 +508,7 @@ namespace Assets
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
builder->storePointer(alias->speakerMap); builder->storePointer(alias->speakerMap);
Game::SpeakerMap* destSoundFile = buffer->dest<Game::SpeakerMap>(); auto* destSoundFile = buffer->dest<Game::SpeakerMap>();
buffer->save(alias->speakerMap); buffer->save(alias->speakerMap);
if (alias->speakerMap->name) if (alias->speakerMap->name)

View File

@ -130,12 +130,14 @@ namespace Components
return; return;
} }
std::string error; nlohmann::json banData;
const auto banData = nlohmann::json::parse(bans.getBuffer()); try
if (!banData.is_object())
{ {
Logger::Debug("bans.json contains invalid data"); banData = nlohmann::json::parse(bans.getBuffer());
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return; return;
} }
@ -144,7 +146,7 @@ namespace Components
if (idList.is_array()) if (idList.is_array())
{ {
nlohmann::json::array_t arr = idList; const nlohmann::json::array_t arr = idList;
for (auto &idEntry : arr) for (auto &idEntry : arr)
{ {
@ -161,7 +163,7 @@ namespace Components
if (ipList.is_array()) if (ipList.is_array())
{ {
nlohmann::json::array_t arr = ipList; const nlohmann::json::array_t arr = ipList;
for (auto &ipEntry : arr) for (auto &ipEntry : arr)
{ {

View File

@ -32,15 +32,15 @@ namespace Components
if (needPassword) if (needPassword)
{ {
std::string pass = Dvar::Var("password").get<std::string>(); const auto password = Dvar::Var("password").get<std::string>();
if (pass.empty()) if (password.empty())
{ {
// shouldn't ever happen but this is safe // shouldn't ever happen but this is safe
Party::ConnectError("A password is required to connect to this server!"); Party::ConnectError("A password is required to connect to this server!");
return; return;
} }
Download::CLDownload.hashedPassword = Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(pass), ""); Download::CLDownload.hashedPassword = Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(password), "");
} }
Download::CLDownload.running = true; Download::CLDownload.running = true;
@ -61,32 +61,39 @@ namespace Components
if (!download) return false; if (!download) return false;
download->files.clear(); download->files.clear();
std::string error; nlohmann::json listData;
nlohmann::json listData = nlohmann::json::parse(list); try
{
if (!error.empty() || !listData.is_array()) listData = nlohmann::json::parse(list);
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return false;
}
if (!listData.is_array())
{ {
Logger::Print("Error: {}\n", error);
return false; return false;
} }
download->totalBytes = 0; download->totalBytes = 0;
nlohmann::json::array_t listDataArray = listData; const nlohmann::json::array_t listDataArray = listData;
for (auto& file : listDataArray) for (auto& file : listDataArray)
{ {
if (!file.is_object()) return false; if (!file.is_object()) return false;
auto hash = file["hash"]; try
auto name = file["name"]; {
auto size = file["size"]; const auto hash = file.at("hash").get<std::string>();
const auto name = file.at("name").get<std::string>();
if (!hash.is_string() || !name.is_string() || !size.is_number()) return false; const auto size = file.at("size").get<std::size_t>();
Download::ClientDownload::File fileEntry; Download::ClientDownload::File fileEntry;
fileEntry.name = name.get<std::string>(); fileEntry.name = name;
fileEntry.hash = hash.get<std::string>(); fileEntry.hash = hash;
fileEntry.size = size.get<size_t>(); fileEntry.size = size;
if (!fileEntry.name.empty()) if (!fileEntry.name.empty())
{ {
@ -94,6 +101,12 @@ namespace Components
download->totalBytes += fileEntry.size; download->totalBytes += fileEntry.size;
} }
} }
catch (const nlohmann::json::exception& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Error: {}\n", ex.what());
return false;
}
}
return true; return true;
} }

View File

@ -327,7 +327,17 @@ namespace Components
const auto parseData = Utils::IO::ReadFile(FavouriteFile); const auto parseData = Utils::IO::ReadFile(FavouriteFile);
if (!parseData.empty()) if (!parseData.empty())
{ {
const nlohmann::json object = nlohmann::json::parse(parseData); nlohmann::json object;
try
{
object = nlohmann::json::parse(parseData);
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return;
}
if (!object.is_array()) if (!object.is_array())
{ {
Logger::Print("Favourites storage file is invalid!\n"); Logger::Print("Favourites storage file is invalid!\n");
@ -363,7 +373,16 @@ namespace Components
const auto parseData = Utils::IO::ReadFile(FavouriteFile); const auto parseData = Utils::IO::ReadFile(FavouriteFile);
if (!parseData.empty()) if (!parseData.empty())
{ {
const nlohmann::json object = nlohmann::json::parse(parseData); nlohmann::json object;
try
{
object = nlohmann::json::parse(parseData);
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return;
}
if (!object.is_array()) if (!object.is_array())
{ {
@ -409,7 +428,17 @@ namespace Components
return; return;
} }
const nlohmann::json object = nlohmann::json::parse(parseData); nlohmann::json object;
try
{
object = nlohmann::json::parse(parseData);
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return;
}
if (!object.is_array()) if (!object.is_array())
{ {
Logger::Print("Favourites storage file is invalid!\n"); Logger::Print("Favourites storage file is invalid!\n");

View File

@ -4,7 +4,7 @@ namespace Components
{ {
Utils::Memory::Allocator StructuredData::MemAllocator; Utils::Memory::Allocator StructuredData::MemAllocator;
const char* StructuredData::EnumTranslation[ENUM_MAX] = const char* StructuredData::EnumTranslation[COUNT] =
{ {
"features", "features",
"weapons", "weapons",
@ -23,7 +23,7 @@ namespace Components
void StructuredData::PatchPlayerDataEnum(Game::StructuredDataDef* data, StructuredData::PlayerDataType type, std::vector<std::string>& entries) void StructuredData::PatchPlayerDataEnum(Game::StructuredDataDef* data, StructuredData::PlayerDataType type, std::vector<std::string>& entries)
{ {
if (!data || type >= StructuredData::PlayerDataType::ENUM_MAX) return; if (!data || type >= StructuredData::PlayerDataType::COUNT) return;
Game::StructuredDataEnum* dataEnum = &data->enums[type]; Game::StructuredDataEnum* dataEnum = &data->enums[type];
@ -192,8 +192,8 @@ namespace Components
return; return;
} }
std::map<int, std::vector<std::vector<std::string>>> patchDefinitions; std::unordered_map<int, std::vector<std::vector<std::string>>> patchDefinitions;
std::map<int, std::unordered_map<std::string, std::string>> otherPatchDefinitions; std::unordered_map<int, std::unordered_map<std::string, std::string>> otherPatchDefinitions;
// First check if all versions are present // First check if all versions are present
for (int i = 156;; ++i) for (int i = 156;; ++i)
@ -205,12 +205,14 @@ namespace Components
std::vector<std::vector<std::string>> enumContainer; std::vector<std::vector<std::string>> enumContainer;
std::unordered_map<std::string, std::string> otherPatches; std::unordered_map<std::string, std::string> otherPatches;
std::string errors; nlohmann::json defData;
nlohmann::json defData = nlohmann::json::parse(definition.getBuffer()); try
if (!errors.empty())
{ {
Logger::Error(Game::ERR_FATAL, "Parsing patch file '{}' for PlayerDataDef version {} failed: {}", definition.getName(), i, errors); defData = nlohmann::json::parse(definition.getBuffer());
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
return; return;
} }
@ -220,7 +222,7 @@ namespace Components
return; return;
} }
for (std::size_t pType = 0; pType < StructuredData::PlayerDataType::ENUM_MAX; ++pType) for (auto pType = 0; pType < StructuredData::PlayerDataType::COUNT; ++pType)
{ {
auto enumData = defData[StructuredData::EnumTranslation[pType]]; auto enumData = defData[StructuredData::EnumTranslation[pType]];
@ -228,7 +230,7 @@ namespace Components
if (enumData.is_array()) if (enumData.is_array())
{ {
for (auto rawEntry : enumData) for (const auto& rawEntry : enumData)
{ {
if (rawEntry.is_string()) if (rawEntry.is_string())
{ {
@ -261,7 +263,7 @@ namespace Components
if (patchDefinitions.empty()) return; if (patchDefinitions.empty()) return;
// Reallocate the definition // Reallocate the definition
Game::StructuredDataDef* newData = StructuredData::MemAllocator.allocateArray<Game::StructuredDataDef>(data->defCount + patchDefinitions.size()); auto* newData = StructuredData::MemAllocator.allocateArray<Game::StructuredDataDef>(data->defCount + patchDefinitions.size());
std::memcpy(&newData[patchDefinitions.size()], data->defs, sizeof Game::StructuredDataDef * data->defCount); std::memcpy(&newData[patchDefinitions.size()], data->defs, sizeof Game::StructuredDataDef * data->defCount);
// Prepare the buffers // Prepare the buffers
@ -271,7 +273,7 @@ namespace Components
newData[i].version = (patchDefinitions.size() - i) + 155; newData[i].version = (patchDefinitions.size() - i) + 155;
// Reallocate the enum array // Reallocate the enum array
Game::StructuredDataEnum* newEnums = StructuredData::MemAllocator.allocateArray<Game::StructuredDataEnum>(data->defs->enumCount); auto* newEnums = StructuredData::MemAllocator.allocateArray<Game::StructuredDataEnum>(data->defs->enumCount);
std::memcpy(newEnums, data->defs->enums, sizeof Game::StructuredDataEnum * data->defs->enumCount); std::memcpy(newEnums, data->defs->enums, sizeof Game::StructuredDataEnum * data->defs->enumCount);
newData[i].enums = newEnums; newData[i].enums = newEnums;
} }
@ -292,14 +294,14 @@ namespace Components
auto otherData = otherPatchDefinitions[newData[i].version]; auto otherData = otherPatchDefinitions[newData[i].version];
// Invalid patch data // Invalid patch data
if (patchData.size() != StructuredData::PlayerDataType::ENUM_MAX) if (patchData.size() != StructuredData::PlayerDataType::COUNT)
{ {
Logger::Error(Game::ERR_FATAL, "PlayerDataDef patch for version {} wasn't parsed correctly!", newData[i].version); Logger::Error(Game::ERR_FATAL, "PlayerDataDef patch for version {} wasn't parsed correctly!", newData[i].version);
continue; continue;
} }
// Apply the patch data // Apply the patch data
for (unsigned int pType = 0; pType < StructuredData::PlayerDataType::ENUM_MAX; ++pType) for (auto pType = 0; pType < StructuredData::PlayerDataType::COUNT; ++pType)
{ {
if (!patchData[pType].empty()) if (!patchData[pType].empty())
{ {

View File

@ -7,20 +7,21 @@ namespace Components
public: public:
enum PlayerDataType enum PlayerDataType
{ {
ENUM_FEATURES, FEATURES,
ENUM_WEAPONS, WEAPONS,
ENUM_ATTACHEMENTS, ATTACHEMENTS,
ENUM_CHALLENGES, CHALLENGES,
ENUM_CAMOS, CAMOS,
ENUM_PERKS, PERKS,
ENUM_KILLSTREAKS, KILLSTREAKS,
ENUM_ACCOLADES, ACCOLADES,
ENUM_CARDICONS, CARDICONS,
ENUM_CARDTITLES, CARDTITLES,
ENUM_CARDNAMEPLATES, CARDNAMEPLATES,
ENUM_TEAMS, TEAMS,
ENUM_GAMETYPES, GAMETYPES,
ENUM_MAX
COUNT
}; };
StructuredData(); StructuredData();
@ -34,6 +35,6 @@ namespace Components
static void PatchCustomClassLimit(Game::StructuredDataDef* data, int count); static void PatchCustomClassLimit(Game::StructuredDataDef* data, int count);
static Utils::Memory::Allocator MemAllocator; static Utils::Memory::Allocator MemAllocator;
static const char* EnumTranslation[ENUM_MAX]; static const char* EnumTranslation[COUNT];
}; };
} }

View File

@ -18,7 +18,7 @@ namespace Components
void Theatre::RecordGamestateStub() void Theatre::RecordGamestateStub()
{ {
int sequence = (*Game::serverMessageSequence - 1); const auto sequence = (*Game::serverMessageSequence - 1);
Game::FS_WriteToDemo(&sequence, 4, *Game::demoFile); Game::FS_WriteToDemo(&sequence, 4, *Game::demoFile);
} }
@ -56,8 +56,8 @@ namespace Components
Game::MSG_WriteData(&buf, &Theatre::BaselineSnapshot[Theatre::BaselineSnapshotMsgOff], Theatre::BaselineSnapshotMsgLen - Theatre::BaselineSnapshotMsgOff); Game::MSG_WriteData(&buf, &Theatre::BaselineSnapshot[Theatre::BaselineSnapshotMsgOff], Theatre::BaselineSnapshotMsgLen - Theatre::BaselineSnapshotMsgOff);
Game::MSG_WriteByte(&buf, 6); Game::MSG_WriteByte(&buf, 6);
int compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast<char*>(buf.data), cmpData, buf.cursize); const auto compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast<char*>(buf.data), cmpData, buf.cursize);
int fileCompressedSize = compressedSize + 4; const auto fileCompressedSize = compressedSize + 4;
int byte8 = 8; int byte8 = 8;
char byte0 = 0; char byte0 = 0;
@ -67,9 +67,9 @@ namespace Components
Game::FS_WriteToDemo(&fileCompressedSize, 4, *Game::demoFile); Game::FS_WriteToDemo(&fileCompressedSize, 4, *Game::demoFile);
Game::FS_WriteToDemo(&byte8, 4, *Game::demoFile); Game::FS_WriteToDemo(&byte8, 4, *Game::demoFile);
for (int i = 0; i < compressedSize; i += 1024) for (auto i = 0; i < compressedSize; i += 1024)
{ {
int size = std::min(compressedSize - i, 1024); const auto size = std::min(compressedSize - i, 1024);
if (i + size >= sizeof(cmpData)) if (i + size >= sizeof(cmpData))
{ {
@ -186,7 +186,7 @@ namespace Components
Theatre::CurrentSelection = 0; Theatre::CurrentSelection = 0;
Theatre::Demos.clear(); Theatre::Demos.clear();
auto demos = FileSystem::GetFileList("demos/", "dm_13"); const auto demos = FileSystem::GetFileList("demos/", "dm_13");
for (auto demo : demos) for (auto demo : demos)
{ {
@ -194,11 +194,17 @@ namespace Components
if (meta.exists()) if (meta.exists())
{ {
std::string error; nlohmann::json metaObject;
nlohmann::json metaObject = nlohmann::json::parse(meta.getBuffer()); try
if (metaObject.is_object())
{ {
metaObject = nlohmann::json::parse(meta.getBuffer());
}
catch (const nlohmann::json::parse_error& ex)
{
Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Parse Error: {}\n", ex.what());
continue;
}
Theatre::DemoInfo demoInfo; Theatre::DemoInfo demoInfo;
demoInfo.name = demo.substr(0, demo.find_last_of(".")); demoInfo.name = demo.substr(0, demo.find_last_of("."));
demoInfo.author = metaObject["author"].get<std::string>(); demoInfo.author = metaObject["author"].get<std::string>();
@ -211,10 +217,9 @@ namespace Components
Theatre::Demos.push_back(demoInfo); Theatre::Demos.push_back(demoInfo);
} }
} }
}
// Reverse, latest demo first! // Reverse, latest demo first!
std::reverse(Theatre::Demos.begin(), Theatre::Demos.end()); std::ranges::reverse(Theatre::Demos);
} }
void Theatre::DeleteDemo([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) void Theatre::DeleteDemo([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)