From c7ae27a664199cd297b81e0651d957b41f2fd13e Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 16 Oct 2022 16:17:42 +0100 Subject: [PATCH] [Json] Sorround with try/catch (#531) * [Json] Sorround with try/catch * Minor format fix --- .../Modules/AssetInterfaces/IFont_s.cpp | 285 +++++++++--------- .../Modules/AssetInterfaces/IMaterial.cpp | 21 +- .../AssetInterfaces/Isnd_alias_list_t.cpp | 43 +-- src/Components/Modules/Bans.cpp | 16 +- src/Components/Modules/Download.cpp | 59 ++-- src/Components/Modules/ServerList.cpp | 35 ++- src/Components/Modules/StructuredData.cpp | 32 +- src/Components/Modules/StructuredData.hpp | 31 +- src/Components/Modules/Theatre.cpp | 49 +-- src/Components/Modules/ZoneBuilder.cpp | 2 +- 10 files changed, 317 insertions(+), 256 deletions(-) diff --git a/src/Components/Modules/AssetInterfaces/IFont_s.cpp b/src/Components/Modules/AssetInterfaces/IFont_s.cpp index 52093f54..0840b809 100644 --- a/src/Components/Modules/AssetInterfaces/IFont_s.cpp +++ b/src/Components/Modules/AssetInterfaces/IFont_s.cpp @@ -80,7 +80,7 @@ namespace Assets 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) { @@ -98,154 +98,163 @@ namespace Assets Components::FileSystem::File fontDefFile(Utils::String::VA("%s.json", 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()); + return; + } - if (!fontDef.is_object()) + nlohmann::json fontDef = nlohmann::json::parse(fontDefFile.getBuffer()); + 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; + } + + auto w = fontDef["textureWidth"].get(); + auto h = fontDef["textureHeight"].get(); + + auto size = fontDef["size"].get(); + auto yOffset = fontDef["yOffset"].get(); + + auto* pixels = builder->getAllocator()->allocateArray(w * h); + + // Setup assets + const auto* texName = builder->getAllocator()->duplicateString(Utils::String::VA("if_%s", name.data() + 6 /* skip "fonts/" */)); + const auto* fontName = builder->getAllocator()->duplicateString(name); + const auto* glowMaterialName = builder->getAllocator()->duplicateString(Utils::String::VA("%s_glow", name.data())); + + auto* image = builder->getAllocator()->allocate(); + std::memcpy(image, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_IMAGE, "gamefonts_pc").image, sizeof(Game::GfxImage)); + + image->name = texName; + + auto* material = builder->getAllocator()->allocate(); + std::memcpy(material, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "fonts/gamefonts_pc").material, sizeof(Game::Material)); + + auto textureTable = builder->getAllocator()->allocate(); + std::memcpy(textureTable, material->textureTable, sizeof(Game::MaterialTextureDef)); + + material->textureTable = textureTable; + material->textureTable->u.image = image; + material->info.name = fontName; + + auto* glowMaterial = builder->getAllocator()->allocate(); + std::memcpy(glowMaterial, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "fonts/gamefonts_pc_glow").material, sizeof(Game::Material)); + + glowMaterial->textureTable = material->textureTable; + glowMaterial->info.name = glowMaterialName; + + std::vector charset; + + if (fontDef["charset"].is_array()) + { + nlohmann::json::array_t charsetArray = fontDef["charset"]; + for (auto& ch : charsetArray) { - Components::Logger::Error(Game::ERR_FATAL, "Font define {} is invalid", name); - return; + charset.push_back(static_cast(ch.get())); } - int w = fontDef["textureWidth"].get(); - int h = fontDef["textureHeight"].get(); - - int size = fontDef["size"].get(); - int yOffset = fontDef["yOffset"].get(); + // order matters + std::ranges::sort(charset); - auto* pixels = builder->getAllocator()->allocateArray(w * h); - - // Setup assets - 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* glowMaterialName = builder->getAllocator()->duplicateString(Utils::String::VA("%s_glow", name.data())); - - auto* image = builder->getAllocator()->allocate(); - std::memcpy(image, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_IMAGE, "gamefonts_pc").image, sizeof(Game::GfxImage)); - - image->name = texName; - - auto* material = builder->getAllocator()->allocate(); - std::memcpy(material, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "fonts/gamefonts_pc").material, sizeof(Game::Material)); - - auto textureTable = builder->getAllocator()->allocate(); - std::memcpy(textureTable, material->textureTable, sizeof(Game::MaterialTextureDef)); - - material->textureTable = textureTable; - material->textureTable->u.image = image; - material->info.name = fontName; - - auto* glowMaterial = builder->getAllocator()->allocate(); - std::memcpy(glowMaterial, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "fonts/gamefonts_pc_glow").material, sizeof(Game::Material)); - - glowMaterial->textureTable = material->textureTable; - glowMaterial->info.name = glowMaterialName; - - std::vector charset; - - if (fontDef["charset"].is_array()) + for (std::uint16_t i = 32; i < 128; i++) { - nlohmann::json::array_t charsetArray = fontDef["charset"]; - for (auto& ch : charsetArray) - charset.push_back(static_cast(ch.get())); - - // order matters - std::sort(charset.begin(), charset.end()); - - for (uint16_t i = 32; i < 128; i++) + if (std::ranges::find(charset, i) == charset.end()) { - if (std::find(charset.begin(), charset.end(), 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); } } - else - { - for (uint16_t i = 32; i < 128; i++) - charset.push_back(i); - } - - auto* font = builder->getAllocator()->allocate(); - - font->fontName = fontName; - font->pixelHeight = size; - font->material = material; - font->glowMaterial = glowMaterial; - font->glyphCount = charset.size(); - font->glyphs = builder->getAllocator()->allocateArray(charset.size()); - - // Generate glyph data - int result = PackFonts(reinterpret_cast(fontFile.getBuffer().data()), charset, font->glyphs, static_cast(size), pixels, w, h, yOffset); - - if (result == -1) - { - Components::Logger::Error(Game::ERR_FATAL, "Truetype font {} is broken", name); - } - else if (result < 0) - { - Components::Logger::Error(Game::ERR_FATAL, "Texture size of font {} is not enough", name); - } - else if(h - result > size) - { - Components::Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Texture of font {} have too much left over space: {}\n", name, h - result); - } - - header->font = font; - - // Save generated materials - Game::XAssetHeader tmpHeader; - - tmpHeader.image = image; - Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_IMAGE, tmpHeader); - - tmpHeader.material = material; - Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_MATERIAL, tmpHeader); - - tmpHeader.material = glowMaterial; - Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_MATERIAL, tmpHeader); - - // Save generated image - Utils::IO::CreateDir("userraw\\images"); - - int fileSize = w * h * 4; - int iwiHeaderSize = static_cast(sizeof(Game::GfxImageFileHeader)); - - Game::GfxImageFileHeader iwiHeader = - { - { 'I', 'W', 'i' }, - /* version */ - 8, - /* flags */ - 2, - /* format */ - Game::IMG_FORMAT_BITMAP_RGBA, - 0, - /* dimensions(x, y, z) */ - { static_cast(w), static_cast(h), 1 }, - /* fileSizeForPicmip (mipSize in bytes + sizeof(GfxImageFileHeader)) */ - { fileSize + iwiHeaderSize, fileSize, fileSize, fileSize } - }; - - std::string outIwi; - outIwi.resize(fileSize + sizeof(Game::GfxImageFileHeader)); - - std::memcpy(outIwi.data(), &iwiHeader, sizeof(Game::GfxImageFileHeader)); - - // Generate RGBA data - auto* rgbaPixels = outIwi.data() + sizeof(Game::GfxImageFileHeader); - - for (int i = 0; i < w * h * 4; i += 4) - { - rgbaPixels[i + 0] = static_cast(255); - rgbaPixels[i + 1] = static_cast(255); - rgbaPixels[i + 2] = static_cast(255); - rgbaPixels[i + 3] = static_cast(pixels[i / 4]); - } - - Utils::IO::WriteFile(Utils::String::VA("userraw\\images\\%s.iwi", texName), outIwi); } + else + { + for (std::uint16_t i = 32; i < 128; i++) + { + charset.push_back(i); + } + } + + auto* font = builder->getAllocator()->allocate(); + + font->fontName = fontName; + font->pixelHeight = size; + font->material = material; + font->glowMaterial = glowMaterial; + font->glyphCount = static_cast(charset.size()); + font->glyphs = builder->getAllocator()->allocateArray(charset.size()); + + // Generate glyph data + int result = PackFonts(reinterpret_cast(fontFile.getBuffer().data()), charset, font->glyphs, static_cast(size), pixels, w, h, yOffset); + + if (result == -1) + { + Components::Logger::Error(Game::ERR_FATAL, "Truetype font {} is broken", name); + } + else if (result < 0) + { + Components::Logger::Error(Game::ERR_FATAL, "Texture size of font {} is not enough", name); + } + else if(h - result > size) + { + Components::Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Texture of font {} have too much left over space: {}\n", name, h - result); + } + + header->font = font; + + // Save generated materials + Game::XAssetHeader tmpHeader; + + tmpHeader.image = image; + Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_IMAGE, tmpHeader); + + tmpHeader.material = material; + Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_MATERIAL, tmpHeader); + + tmpHeader.material = glowMaterial; + Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_MATERIAL, tmpHeader); + + // Save generated image + Utils::IO::CreateDir("userraw\\images"); + + int fileSize = w * h * 4; + int iwiHeaderSize = static_cast(sizeof(Game::GfxImageFileHeader)); + + Game::GfxImageFileHeader iwiHeader = + { + { 'I', 'W', 'i' }, + /* version */ + 8, + /* flags */ + 2, + /* format */ + Game::IMG_FORMAT_BITMAP_RGBA, + 0, + /* dimensions(x, y, z) */ + { static_cast(w), static_cast(h), 1 }, + /* fileSizeForPicmip (mipSize in bytes + sizeof(GfxImageFileHeader)) */ + { fileSize + iwiHeaderSize, fileSize, fileSize, fileSize } + }; + + std::string outIwi; + outIwi.resize(fileSize + sizeof(Game::GfxImageFileHeader)); + + std::memcpy(outIwi.data(), &iwiHeader, sizeof(Game::GfxImageFileHeader)); + + // Generate RGBA data + auto* rgbaPixels = outIwi.data() + sizeof(Game::GfxImageFileHeader); + + for (auto i = 0; i < w * h * 4; i += 4) + { + rgbaPixels[i + 0] = static_cast(255); + rgbaPixels[i + 1] = static_cast(255); + rgbaPixels[i + 2] = static_cast(255); + rgbaPixels[i + 3] = static_cast(pixels[i / 4]); + } + + Utils::IO::WriteFile(Utils::String::VA("userraw\\images\\%s.iwi", texName), outIwi); } void IFont_s::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp index ac23ed17..499acf36 100644 --- a/src/Components/Modules/AssetInterfaces/IMaterial.cpp +++ b/src/Components/Modules/AssetInterfaces/IMaterial.cpp @@ -30,7 +30,8 @@ namespace Assets "_add_lin_nofog", }; - std::map techSetCorrespondance = { + static std::unordered_map techSetCorrespondance = + { {"effect", "effect_blend"}, {"effect", "effect_blend"}, {"effect_nofog", "effect_blend_nofog"}, @@ -50,12 +51,6 @@ namespace Assets {"mc_unlit_nofog", "mc_unlit_blend_nofog_ua"}, {"mc_unlit", "mc_unlit_replace_lin_nocast"}, {"mc_unlit_alphatest", "mc_unlit_blend_lin"} - /*, - {"", ""}, - {"", ""}, - {"", ""}, - {"", ""}, - {"", ""},*/ }; 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()); char* magic = reader.readArray(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); } @@ -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); } - Game::Material* asset = reader.readObject(); + auto* asset = reader.readObject(); if (asset->info.name) { @@ -408,13 +403,13 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); builder->storePointer(asset->textureTable); - Game::MaterialTextureDef* destTextureTable = buffer->dest(); + auto* destTextureTable = buffer->dest(); 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]; - Game::MaterialTextureDef* textureDef = &asset->textureTable[i]; + auto* destTextureDef = &destTextureTable[i]; + auto* textureDef = &asset->textureTable[i]; if (textureDef->semantic == SEMANTIC_WATER_MAP) { diff --git a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp index d70c9aaa..021781b3 100644 --- a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp +++ b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp @@ -12,16 +12,26 @@ namespace Assets return; } - Game::snd_alias_list_t* aliasList = builder->getAllocator()->allocate(); + auto* aliasList = builder->getAllocator()->allocate(); 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; } - nlohmann::json infoData = nlohmann::json::parse(aliasFile.getBuffer()); - nlohmann::json aliasesContainer = infoData["head"]; + nlohmann::json infoData; + 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; aliasList->count = aliases.size(); @@ -34,7 +44,7 @@ namespace Assets return; } - aliasList->aliasName = builder->getAllocator()->duplicateString(name.c_str()); + aliasList->aliasName = builder->getAllocator()->duplicateString(name); for (size_t i = 0; i < aliasList->count; i++) { @@ -288,19 +298,14 @@ namespace Assets if (volumeFalloffCurve.is_string()) { - std::string fallOffCurve = volumeFalloffCurve.get(); + auto fallOffCurve = volumeFalloffCurve.get(); - if (fallOffCurve.size() == 0) + if (fallOffCurve.empty()) { fallOffCurve = "$default"; } - auto curve = Components::AssetHandler::FindAssetForZone( - Game::XAssetType::ASSET_TYPE_SOUND_CURVE, - fallOffCurve.c_str(), - builder - ).sndCurve; - + auto curve = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, fallOffCurve, builder).sndCurve; alias->volumeFalloffCurve = curve; } @@ -376,9 +381,9 @@ namespace Assets { AssertSize(Game::snd_alias_list_t, 12); - Utils::Stream* buffer = builder->getBuffer(); - Game::snd_alias_list_t* asset = header.sound; - Game::snd_alias_list_t* dest = buffer->dest(); + auto* buffer = builder->getBuffer(); + auto* asset = header.sound; + auto* dest = buffer->dest(); buffer->save(asset); buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); @@ -402,7 +407,7 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); builder->storePointer(asset->head); - Game::snd_alias_t* destHead = buffer->dest(); + auto* destHead = buffer->dest(); buffer->saveArray(asset->head, asset->count); for (unsigned int i = 0; i < asset->count; ++i) @@ -453,7 +458,7 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); builder->storePointer(alias->soundFile); - Game::SoundFile* destSoundFile = buffer->dest(); + auto* destSoundFile = buffer->dest(); buffer->save(alias->soundFile); // Save_SoundFileRef @@ -503,7 +508,7 @@ namespace Assets buffer->align(Utils::Stream::ALIGN_4); builder->storePointer(alias->speakerMap); - Game::SpeakerMap* destSoundFile = buffer->dest(); + auto* destSoundFile = buffer->dest(); buffer->save(alias->speakerMap); if (alias->speakerMap->name) diff --git a/src/Components/Modules/Bans.cpp b/src/Components/Modules/Bans.cpp index dd7e0bec..8973036e 100644 --- a/src/Components/Modules/Bans.cpp +++ b/src/Components/Modules/Bans.cpp @@ -130,12 +130,14 @@ namespace Components return; } - std::string error; - const auto banData = nlohmann::json::parse(bans.getBuffer()); - - if (!banData.is_object()) + nlohmann::json banData; + try { - 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; } @@ -144,7 +146,7 @@ namespace Components if (idList.is_array()) { - nlohmann::json::array_t arr = idList; + const nlohmann::json::array_t arr = idList; for (auto &idEntry : arr) { @@ -161,7 +163,7 @@ namespace Components if (ipList.is_array()) { - nlohmann::json::array_t arr = ipList; + const nlohmann::json::array_t arr = ipList; for (auto &ipEntry : arr) { diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index 58e0f64c..5685bc92 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -32,15 +32,15 @@ namespace Components if (needPassword) { - std::string pass = Dvar::Var("password").get(); - if (pass.empty()) + const auto password = Dvar::Var("password").get(); + if (password.empty()) { // shouldn't ever happen but this is safe Party::ConnectError("A password is required to connect to this server!"); 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; @@ -61,37 +61,50 @@ namespace Components if (!download) return false; download->files.clear(); - std::string error; - nlohmann::json listData = nlohmann::json::parse(list); - - if (!error.empty() || !listData.is_array()) + nlohmann::json listData; + try + { + 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; } download->totalBytes = 0; - nlohmann::json::array_t listDataArray = listData; + const nlohmann::json::array_t listDataArray = listData; for (auto& file : listDataArray) { if (!file.is_object()) return false; - auto hash = file["hash"]; - auto name = file["name"]; - auto size = file["size"]; - - if (!hash.is_string() || !name.is_string() || !size.is_number()) return false; - - Download::ClientDownload::File fileEntry; - fileEntry.name = name.get(); - fileEntry.hash = hash.get(); - fileEntry.size = size.get(); - - if (!fileEntry.name.empty()) + try { - download->files.push_back(fileEntry); - download->totalBytes += fileEntry.size; + const auto hash = file.at("hash").get(); + const auto name = file.at("name").get(); + const auto size = file.at("size").get(); + + Download::ClientDownload::File fileEntry; + fileEntry.name = name; + fileEntry.hash = hash; + fileEntry.size = size; + + if (!fileEntry.name.empty()) + { + download->files.push_back(fileEntry); + download->totalBytes += fileEntry.size; + } + } + catch (const nlohmann::json::exception& ex) + { + Logger::PrintError(Game::CON_CHANNEL_ERROR, "Json Error: {}\n", ex.what()); + return false; } } diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 36b0081b..18ef579f 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -327,7 +327,17 @@ namespace Components const auto parseData = Utils::IO::ReadFile(FavouriteFile); 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()) { Logger::Print("Favourites storage file is invalid!\n"); @@ -363,7 +373,16 @@ namespace Components const auto parseData = Utils::IO::ReadFile(FavouriteFile); 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()) { @@ -409,7 +428,17 @@ namespace Components 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()) { Logger::Print("Favourites storage file is invalid!\n"); diff --git a/src/Components/Modules/StructuredData.cpp b/src/Components/Modules/StructuredData.cpp index abc1597b..42ead9e1 100644 --- a/src/Components/Modules/StructuredData.cpp +++ b/src/Components/Modules/StructuredData.cpp @@ -4,7 +4,7 @@ namespace Components { Utils::Memory::Allocator StructuredData::MemAllocator; - const char* StructuredData::EnumTranslation[ENUM_MAX] = + const char* StructuredData::EnumTranslation[COUNT] = { "features", "weapons", @@ -23,7 +23,7 @@ namespace Components void StructuredData::PatchPlayerDataEnum(Game::StructuredDataDef* data, StructuredData::PlayerDataType type, std::vector& entries) { - if (!data || type >= StructuredData::PlayerDataType::ENUM_MAX) return; + if (!data || type >= StructuredData::PlayerDataType::COUNT) return; Game::StructuredDataEnum* dataEnum = &data->enums[type]; @@ -192,8 +192,8 @@ namespace Components return; } - std::map>> patchDefinitions; - std::map> otherPatchDefinitions; + std::unordered_map>> patchDefinitions; + std::unordered_map> otherPatchDefinitions; // First check if all versions are present for (int i = 156;; ++i) @@ -205,12 +205,14 @@ namespace Components std::vector> enumContainer; std::unordered_map otherPatches; - std::string errors; - nlohmann::json defData = nlohmann::json::parse(definition.getBuffer()); - - if (!errors.empty()) + nlohmann::json defData; + try { - 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; } @@ -220,7 +222,7 @@ namespace Components 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]]; @@ -228,7 +230,7 @@ namespace Components if (enumData.is_array()) { - for (auto rawEntry : enumData) + for (const auto& rawEntry : enumData) { if (rawEntry.is_string()) { @@ -261,7 +263,7 @@ namespace Components if (patchDefinitions.empty()) return; // Reallocate the definition - Game::StructuredDataDef* newData = StructuredData::MemAllocator.allocateArray(data->defCount + patchDefinitions.size()); + auto* newData = StructuredData::MemAllocator.allocateArray(data->defCount + patchDefinitions.size()); std::memcpy(&newData[patchDefinitions.size()], data->defs, sizeof Game::StructuredDataDef * data->defCount); // Prepare the buffers @@ -271,7 +273,7 @@ namespace Components newData[i].version = (patchDefinitions.size() - i) + 155; // Reallocate the enum array - Game::StructuredDataEnum* newEnums = StructuredData::MemAllocator.allocateArray(data->defs->enumCount); + auto* newEnums = StructuredData::MemAllocator.allocateArray(data->defs->enumCount); std::memcpy(newEnums, data->defs->enums, sizeof Game::StructuredDataEnum * data->defs->enumCount); newData[i].enums = newEnums; } @@ -292,14 +294,14 @@ namespace Components auto otherData = otherPatchDefinitions[newData[i].version]; // 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); continue; } // 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()) { diff --git a/src/Components/Modules/StructuredData.hpp b/src/Components/Modules/StructuredData.hpp index 3a1b42f2..acd61a94 100644 --- a/src/Components/Modules/StructuredData.hpp +++ b/src/Components/Modules/StructuredData.hpp @@ -7,20 +7,21 @@ namespace Components public: enum PlayerDataType { - ENUM_FEATURES, - ENUM_WEAPONS, - ENUM_ATTACHEMENTS, - ENUM_CHALLENGES, - ENUM_CAMOS, - ENUM_PERKS, - ENUM_KILLSTREAKS, - ENUM_ACCOLADES, - ENUM_CARDICONS, - ENUM_CARDTITLES, - ENUM_CARDNAMEPLATES, - ENUM_TEAMS, - ENUM_GAMETYPES, - ENUM_MAX + FEATURES, + WEAPONS, + ATTACHEMENTS, + CHALLENGES, + CAMOS, + PERKS, + KILLSTREAKS, + ACCOLADES, + CARDICONS, + CARDTITLES, + CARDNAMEPLATES, + TEAMS, + GAMETYPES, + + COUNT }; StructuredData(); @@ -34,6 +35,6 @@ namespace Components static void PatchCustomClassLimit(Game::StructuredDataDef* data, int count); static Utils::Memory::Allocator MemAllocator; - static const char* EnumTranslation[ENUM_MAX]; + static const char* EnumTranslation[COUNT]; }; } diff --git a/src/Components/Modules/Theatre.cpp b/src/Components/Modules/Theatre.cpp index 29963619..a62826d2 100644 --- a/src/Components/Modules/Theatre.cpp +++ b/src/Components/Modules/Theatre.cpp @@ -6,7 +6,7 @@ namespace Components unsigned int Theatre::CurrentSelection; std::vector Theatre::Demos; - char Theatre::BaselineSnapshot[131072] = { 0 }; + char Theatre::BaselineSnapshot[131072] = {0}; int Theatre::BaselineSnapshotMsgLen; int Theatre::BaselineSnapshotMsgOff; @@ -18,7 +18,7 @@ namespace Components void Theatre::RecordGamestateStub() { - int sequence = (*Game::serverMessageSequence - 1); + const auto sequence = (*Game::serverMessageSequence - 1); 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_WriteByte(&buf, 6); - int compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast(buf.data), cmpData, buf.cursize); - int fileCompressedSize = compressedSize + 4; + const auto compressedSize = Game::MSG_WriteBitsCompress(false, reinterpret_cast(buf.data), cmpData, buf.cursize); + const auto fileCompressedSize = compressedSize + 4; int byte8 = 8; char byte0 = 0; @@ -67,9 +67,9 @@ namespace Components Game::FS_WriteToDemo(&fileCompressedSize, 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)) { @@ -186,7 +186,7 @@ namespace Components Theatre::CurrentSelection = 0; Theatre::Demos.clear(); - auto demos = FileSystem::GetFileList("demos/", "dm_13"); + const auto demos = FileSystem::GetFileList("demos/", "dm_13"); for (auto demo : demos) { @@ -194,27 +194,32 @@ namespace Components if (meta.exists()) { - std::string error; - nlohmann::json metaObject = nlohmann::json::parse(meta.getBuffer()); - - if (metaObject.is_object()) + nlohmann::json metaObject; + try { - Theatre::DemoInfo demoInfo; - demoInfo.name = demo.substr(0, demo.find_last_of(".")); - demoInfo.author = metaObject["author"].get(); - demoInfo.gametype = metaObject["gametype"].get(); - demoInfo.mapname = metaObject["mapname"].get(); - demoInfo.length = metaObject["length"].get(); - auto timestamp = metaObject["timestamp"].get(); - demoInfo.timeStamp = _atoi64(timestamp.data()); - - Theatre::Demos.push_back(demoInfo); + 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; + demoInfo.name = demo.substr(0, demo.find_last_of(".")); + demoInfo.author = metaObject["author"].get(); + demoInfo.gametype = metaObject["gametype"].get(); + demoInfo.mapname = metaObject["mapname"].get(); + demoInfo.length = metaObject["length"].get(); + auto timestamp = metaObject["timestamp"].get(); + demoInfo.timeStamp = _atoi64(timestamp.data()); + + Theatre::Demos.push_back(demoInfo); } } // 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) diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index d3d6a373..58fc5195 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -226,7 +226,7 @@ namespace Components Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset); if (!assetHeader.data) - { + { Logger::Error(Game::ERR_FATAL, "Missing asset '{}' of type '{}'\n", name, Game::DB_GetXAssetTypeName(type)); return false; }