[Json] Sorround with try/catch (#531)
* [Json] Sorround with try/catch * Minor format fix
This commit is contained in:
parent
bff0d22e81
commit
c7ae27a664
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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())
|
||||||
{
|
{
|
||||||
|
@ -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];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user