From 8942ef3d6b4889b46d884225a24066c30c8215e0 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sat, 30 Mar 2024 11:24:16 +0000 Subject: [PATCH 1/2] Allow migrating from deleted variants On loading a variant that is not a possible variant for the given item, search for a migration from that item with the variant that was loaded, and apply that migration if relevant. --- src/item_factory.cpp | 77 +++++++++++++++++++++++++++---------------- src/item_factory.h | 3 ++ src/savegame_json.cpp | 6 +++- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/item_factory.cpp b/src/item_factory.cpp index c683def866b85..c47724d7a8f4d 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -4563,35 +4563,8 @@ itype_id Item_factory::migrate_id( const itype_id &id ) return parent != nullptr ? parent->replace : id; } -void Item_factory::migrate_item( const itype_id &id, item &obj ) +static void apply_migration( const migration *migrant, item &obj ) { - auto iter = migrations.find( id ); - if( iter == migrations.end() ) { - return; - } - bool convert = false; - const migration *migrant = nullptr; - for( const migration &m : iter->second ) { - if( m.from_variant && obj.has_itype_variant() && obj.itype_variant().id == *m.from_variant ) { - migrant = &m; - // This is not the variant that the item has already been convert to - // So we'll convert it again. - convert = true; - break; - } - // When we find a migration that doesn't care about variants, keep it around - if( !m.from_variant ) { - migrant = &m; - } - } - if( migrant == nullptr ) { - return; - } - - if( convert ) { - obj.convert( migrant->replace ); - } - if( migrant->reset_item_vars ) { obj.clear_vars(); for( const auto &pair : migrant->replace.obj().item_variables ) { @@ -4629,6 +4602,54 @@ void Item_factory::migrate_item( const itype_id &id, item &obj ) } } +void Item_factory::migrate_item( const itype_id &id, item &obj ) +{ + auto iter = migrations.find( id ); + if( iter == migrations.end() ) { + return; + } + bool convert = false; + const migration *migrant = nullptr; + for( const migration &m : iter->second ) { + if( m.from_variant && obj.has_itype_variant() && obj.itype_variant().id == *m.from_variant ) { + migrant = &m; + // This is not the variant that the item has already been convert to + // So we'll convert it again. + convert = true; + break; + } + // When we find a migration that doesn't care about variants, keep it around + if( !m.from_variant ) { + migrant = &m; + } + } + if( migrant == nullptr ) { + return; + } + + if( convert ) { + obj.convert( migrant->replace ); + } + + apply_migration( migrant, obj ); +} + +void Item_factory::migrate_item_from_variant( item &obj, const std::string &from_variant ) +{ + auto iter = migrations.find( obj.typeId() ); + if( iter == migrations.end() ) { + return; + } + for( const migration &m : iter->second ) { + if( !m.from_variant.has_value() || m.from_variant.value() != from_variant ) { + continue; + } + obj.convert( m.replace ); + apply_migration( &m, obj ); + break; + } +} + void Item_factory::set_qualities_from_json( const JsonObject &jo, const std::string &member, itype &def ) { diff --git a/src/item_factory.h b/src/item_factory.h index 7d4c1563560c9..b6622d730095e 100644 --- a/src/item_factory.h +++ b/src/item_factory.h @@ -224,6 +224,9 @@ class Item_factory */ void migrate_item( const itype_id &id, item &obj ); + /** applies a migration to the item if one exists with the given from_variant */ + void migrate_item_from_variant( item &obj, const std::string &from_variant ); + /** * Check if an item type is known to the Item_factory. * @param id Item type id (@ref itype::id). diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index 572aed9e32ce7..83f281d4af21b 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -2875,7 +2875,11 @@ void item::io( Archive &archive ) } ); archive.io( "craft_data", craft_data_, decltype( craft_data_ )() ); const auto ivload = [this]( const std::string & variant ) { - set_itype_variant( variant ); + if( possible_itype_variant( variant ) ) { + set_itype_variant( variant ); + } else { + item_controller->migrate_item_from_variant( *this, variant ); + } }; const auto ivsave = []( const itype_variant_data * iv ) { return iv->id; From f3ad0e9a1af5d0808b2c8ed01fe813a66a281f93 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sat, 30 Mar 2024 11:37:23 +0000 Subject: [PATCH 2/2] Properly migrate mossberg 500 security The variant moved from one shotgun to another, so add a migration. In b9c40929c29bed9a3ea16823c757ad76e3ee68fd --- .../json/obsoletion_and_migration_0.I/migration_items.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/data/json/obsoletion_and_migration_0.I/migration_items.json b/data/json/obsoletion_and_migration_0.I/migration_items.json index b35251cf701c0..6c4b99f9b03c2 100644 --- a/data/json/obsoletion_and_migration_0.I/migration_items.json +++ b/data/json/obsoletion_and_migration_0.I/migration_items.json @@ -1212,6 +1212,13 @@ "type": "MIGRATION", "replace": "remington_870" }, + { + "id": "mossberg_500", + "type": "MIGRATION", + "from_variant": "mossberg_500_security", + "replace": "benelli_tsa", + "variant": "mossberg_500_security" + }, { "id": "bottle_suppressor", "type": "MIGRATION",