Skip to content

Commit

Permalink
Merge pull request #72717 from anothersimulacrum/migrate-from-dead-va…
Browse files Browse the repository at this point in the history
…riants

Allow migrating from deleted variants
  • Loading branch information
dseguin authored Mar 30, 2024
2 parents 5a8cdec + f3ad0e9 commit df6c8e3
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 29 deletions.
7 changes: 7 additions & 0 deletions data/json/obsoletion_and_migration_0.I/migration_items.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
77 changes: 49 additions & 28 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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 )
{
Expand Down
3 changes: 3 additions & 0 deletions src/item_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
6 changes: 5 additions & 1 deletion src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit df6c8e3

Please sign in to comment.