Skip to content

Commit

Permalink
Fix various crashes (#568)
Browse files Browse the repository at this point in the history
* Don't die while importing armies to dead countries.

* Handle capital state of -1.

* Handle a couple of cases of 'dead' blocks in databases.

* Keep but don't convert dead countries.

* trait -> traits

* Restore country importing.

* Update test

* Let rakaly differenciate ironman, text, and compressed saves.

* No-op some unneeded unit mappings.

* Actually handle plain-text saves properly.
  • Loading branch information
Idhrendur authored Jan 28, 2024
1 parent 1830366 commit b07747a
Show file tree
Hide file tree
Showing 10 changed files with 44 additions and 28 deletions.
2 changes: 1 addition & 1 deletion data/configurables/character_traits.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ army = { # Generals & Field Marshals
logistics = 2
}
pillager = {
trait = { commando }
traits = { commando }
attack = 1
logistics = 1
}
Expand Down
2 changes: 2 additions & 0 deletions data/configurables/unit_mappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ combat_unit_type_light_tanks = {

pm_no_organization = {}
pm_general_training = {}
pm_training_streamlining = {}
pm_advanced_tactics_training = {}

## Pre-1.5 conversions

Expand Down
7 changes: 6 additions & 1 deletion src/hoi4_world/countries/hoi4_countries_converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,13 @@ std::map<std::string, Country> ConvertCountries(const vic3::World source_world,
ConvoyDistributor convoys = BuildConvoyDistributor("configurables/convoy_config.txt");
convoys.CalculateStateWeights(source_world);

for (const auto& [country_number, source_country]: source_world.GetCountries())
for (const auto& source_country: source_world.GetCountries() | std::views::values)
{
if (source_country.IsDead())
{
continue;
}

std::optional<Country> new_country = ConvertCountry(source_world,
source_country,
source_localizations,
Expand Down
4 changes: 4 additions & 0 deletions src/vic3_world/countries/vic3_country.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct CountryOptions
{
int number = 0;
std::string tag;
bool is_dead;
std::optional<std::string> dynamic_name;
std::optional<std::string> dynamic_adjective;
commonItems::Color color;
Expand Down Expand Up @@ -76,6 +77,7 @@ class Country
explicit Country(CountryOptions options):
number_(options.number),
tag_(std::move(options.tag)),
is_dead_(options.is_dead),
dynamic_name_(std::move(options.dynamic_name)),
dynamic_adjective_(std::move(options.dynamic_adjective)),
color_(options.color),
Expand All @@ -102,6 +104,7 @@ class Country

[[nodiscard]] int GetNumber() const { return number_; }
[[nodiscard]] const std::string& GetTag() const { return tag_; }
[[nodiscard]] bool IsDead() const { return is_dead_; }
[[nodiscard]] const std::optional<std::string>& GetDynamicName() const { return dynamic_name_; }
[[nodiscard]] const std::optional<std::string>& GetDynamicAdjective() const { return dynamic_adjective_; }
[[nodiscard]] const commonItems::Color& GetColor() const { return color_; }
Expand Down Expand Up @@ -152,6 +155,7 @@ class Country
private:
int number_ = 0;
std::string tag_;
bool is_dead_;
std::optional<std::string> dynamic_name_;
std::optional<std::string> dynamic_adjective_;
commonItems::Color color_;
Expand Down
18 changes: 10 additions & 8 deletions src/vic3_world/countries/vic3_country_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ vic3::CountryImporter::CountryImporter()
options_.color = commonItems::Color::Factory{}.getColor(input_stream);
});
country_parser_.registerKeyword("capital", [this](std::istream& input_stream) {
options_.capital_state = commonItems::getInt(input_stream);
const int64_t temp_number = commonItems::getLlong(input_stream);
if (temp_number == 4294967295)
{
options_.capital_state = -1;
}
else
{
options_.capital_state = static_cast<int>(temp_number);
}
});
country_parser_.registerKeyword("country_type", [this](std::istream& input_stream) {
options_.country_type = commonItems::getString(input_stream);
Expand Down Expand Up @@ -83,7 +91,7 @@ vic3::CountryImporter::CountryImporter()
});

country_parser_.registerKeyword("dead", [this](std::istream& input_stream) {
is_dead_ = commonItems::getString(input_stream) == "yes";
options_.is_dead = commonItems::getString(input_stream) == "yes";
});

/// ---- counters parser ----
Expand All @@ -107,13 +115,7 @@ std::optional<vic3::Country> vic3::CountryImporter::ImportCountry(const int numb
const std::map<std::string, commonItems::Color>& color_definitions)
{
options_ = {};
is_dead_ = false;

country_parser_.parseStream(input_stream);
if (is_dead_)
{
return std::nullopt;
}

if (options_.color == commonItems::Color())
{
Expand Down
2 changes: 0 additions & 2 deletions src/vic3_world/countries/vic3_country_importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ class CountryImporter
commonItems::parser counters_parser_;

CountryOptions options_;

bool is_dead_ = false; // Country marked as invalid data by game, but not yet cleaned up
};

} // namespace vic3
Expand Down
6 changes: 4 additions & 2 deletions src/vic3_world/countries/vic3_country_importer_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ TEST(Vic3WorldCountriesCountryImporter, DefaultsAreDefaulted)

EXPECT_TRUE(country.has_value());
EXPECT_TRUE(country.value_or(Country({})).GetTag().empty());
EXPECT_FALSE(country.value_or(Country({})).IsDead());
EXPECT_FALSE(country.value_or(Country({})).GetDynamicName());
EXPECT_FALSE(country.value_or(Country({})).GetDynamicAdjective());
EXPECT_EQ(country.value_or(Country({})).GetColor(), commonItems::Color(std::array{0, 0, 0}));
Expand Down Expand Up @@ -170,7 +171,7 @@ TEST(Vic3WorldCountriesCountryImporter, IgIdsCanBeAdded)
}


TEST(Vic3WorldCountriesCountryImporter, DeadCountriesAreSkipped)
TEST(Vic3WorldCountriesCountryImporter, DeadCountriesAreImported)
{
std::stringstream input;
input << "={\n";
Expand All @@ -180,7 +181,8 @@ TEST(Vic3WorldCountriesCountryImporter, DeadCountriesAreSkipped)
input << "}";
const auto country = CountryImporter{}.ImportCountry(0, input, {});

EXPECT_FALSE(country.has_value());
EXPECT_TRUE(country.has_value());
EXPECT_TRUE(country.value_or(Country({})).IsDead());
}

TEST(Vic3WorldCountriesCountryImporter, CountersSectionParsed)
Expand Down
4 changes: 3 additions & 1 deletion src/vic3_world/institutions/institutions_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ void InstitutionsImporter::operator()(std::istream& input_stream)
this->current_institution_ = {};
};

DatabaseParser(elementParser).parseStream(input_stream);
DatabaseParser database_parser(elementParser);
database_parser.registerKeyword("dead", commonItems::ignoreItem);
database_parser.parseStream(input_stream);
}

} // namespace vic3
4 changes: 3 additions & 1 deletion src/vic3_world/laws/laws_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ std::map<int, std::set<std::string>> vic3::ImportLaws(std::istream& input_stream
}
};

DatabaseParser(law_parser_function).parseStream(input_stream);
DatabaseParser database_parser(law_parser_function);
database_parser.registerKeyword("dead", commonItems::ignoreItem);
database_parser.parseStream(input_stream);

LOG(LogLevel::Info) << fmt::format("\tImported {} active laws.", active_laws);
LOG(LogLevel::Info) << fmt::format("\tImported {} inactive laws.", inactive_laws);
Expand Down
23 changes: 11 additions & 12 deletions src/vic3_world/world/vic3_world_importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,19 @@ std::vector<Mod> GetModsFromSave(const std::vector<std::string>& mod_names)

std::istringstream MeltSave(const rakaly::GameFile& save, const std::string& save_string)
{
std::string melted_save_string;
if (save.is_binary())
const auto melt = save.melt();
if (melt.has_unknown_tokens())
{
const auto melt = save.melt();
if (melt.has_unknown_tokens())
{
throw std::runtime_error("Unable to melt ironman save");
}

melt.writeData(melted_save_string);
throw std::runtime_error("Unable to melt ironman save");
}
else

std::string melted_save_string;
melt.writeData(melted_save_string);

if (melted_save_string.empty())
{
melted_save_string = save_string;
return std::istringstream{save_string};
}

return std::istringstream{melted_save_string};
}

Expand Down Expand Up @@ -258,6 +255,7 @@ void AssignMilitaryFormationsToCountries(const std::map<int, vic3::MilitaryForma
if (country == countries.end())
{
Log(LogLevel::Warning) << fmt::format("Could not find country {} to assign army formations.", country_number);
continue;
}
country->second.SetArmyFormations(army_formations);
}
Expand All @@ -267,6 +265,7 @@ void AssignMilitaryFormationsToCountries(const std::map<int, vic3::MilitaryForma
if (country == countries.end())
{
Log(LogLevel::Warning) << fmt::format("Could not find country {} to assign navy formations.", country_number);
continue;
}
country->second.SetNavyFormations(navy_formations);
}
Expand Down

0 comments on commit b07747a

Please # to comment.