238 lines
6.1 KiB
Perl
238 lines
6.1 KiB
Perl
package GEmeTool::Save;
|
|
|
|
use v5.16.3;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Rsaves;
|
|
use Rsaves::Constants::Global
|
|
qw/$SAPPHIRE_VERSION $RUBY_VERSION $EMERALD_VERSION $FIRERED_VERSION $LEAFGREEN_VERSION $COLOSSEUM_VERSION/;
|
|
use Rsaves::Constants::Emerald::Flags;
|
|
use Rsaves::Constants::Emerald::Rematches;
|
|
|
|
use Moo;
|
|
|
|
use GEmeTool::Log qw/logger/;
|
|
use namespace::clean;
|
|
use GEmeTool::Save::PokemonPC;
|
|
|
|
has __saves => ( is => 'rw' );
|
|
|
|
has __extra => ( is => 'rw' );
|
|
|
|
has input_file => ( is => 'rw', required => 1 );
|
|
|
|
has _initial_rematches => ( is => 'rw' );
|
|
|
|
has _initial_flags => ( is => 'rw' );
|
|
|
|
has _pc => ( is => 'rw' );
|
|
|
|
sub instance {
|
|
my $class = shift;
|
|
my $input_file = shift;
|
|
my $save = $class->new( input_file => $input_file );
|
|
return $save;
|
|
}
|
|
|
|
sub BUILD {
|
|
my $self = shift;
|
|
logger()->msg( 'Opening save...', $self->input_file );
|
|
}
|
|
|
|
sub get_flags_save {
|
|
my $self = shift;
|
|
my %flags_by_id = $self->_get_flags_hash_by_id;
|
|
my @return;
|
|
for my $i ( sort { $a <=> $b } keys %flags_by_id ) {
|
|
push @return,
|
|
{ value => $self->has_flag($i), name => $flags_by_id{$i}, id => $i };
|
|
}
|
|
return \@return;
|
|
}
|
|
|
|
sub get_rematches_save {
|
|
my $self = shift;
|
|
my %rematch_by_id = $self->_get_rematches_hash_by_id;
|
|
my @return;
|
|
for my $i ( sort { $a <=> $b } keys %rematch_by_id ) {
|
|
push @return,
|
|
{
|
|
value => $self->has_rematch($i),
|
|
name => $rematch_by_id{$i},
|
|
id => $i
|
|
};
|
|
}
|
|
return \@return;
|
|
}
|
|
|
|
sub save {
|
|
my $self = shift;
|
|
my $file = shift;
|
|
my $extra = $self->__extra;
|
|
my $saves = $self->__saves;
|
|
my $ini_flags = $self->_initial_flags;
|
|
my $end_flags = $self->get_flags_save;
|
|
my $ini_rematches = $self->_initial_rematches;
|
|
my $end_rematches = $self->get_rematches_save;
|
|
logger()->msg(
|
|
"Saving, edited data:\n"
|
|
. $self->diff_boolean_flag_like( $ini_flags, $end_flags )
|
|
. $self->diff_boolean_flag_like( $ini_rematches, $end_rematches ),
|
|
$self->input_file,
|
|
$file,
|
|
);
|
|
Rsaves::save_changes( @$saves, $extra, $file );
|
|
}
|
|
|
|
sub diff_boolean_flag_like {
|
|
my $self = shift;
|
|
my $initial = shift;
|
|
my $final = shift;
|
|
my $result_string = '';
|
|
for ( my $i = 0 ; $i < scalar @$initial ; $i++ ) {
|
|
my $flag_ini = $initial->[$i];
|
|
my $flag_end = $final->[$i];
|
|
if ( ( !!$flag_ini->{value} ) == ( !!$flag_end->{value} ) ) {
|
|
next;
|
|
}
|
|
$result_string .=
|
|
"@{[$flag_end->{name}]} => @{[$flag_end->{value} ? 'ON' : 'OFF']}\n";
|
|
}
|
|
return $result_string;
|
|
}
|
|
|
|
sub has_rematch {
|
|
my $self = shift;
|
|
my $flag_id = shift;
|
|
my $superdata = $self->_get_superdata;
|
|
my $save = $self->_get_current_save;
|
|
return Rsaves::check_rematch( $save, $superdata, $flag_id );
|
|
}
|
|
|
|
sub has_flag {
|
|
my $self = shift;
|
|
my $flag_id = shift;
|
|
my $superdata = $self->_get_superdata;
|
|
my $save = $self->_get_current_save;
|
|
return Rsaves::check_flag_id( $save, $superdata, $flag_id );
|
|
}
|
|
|
|
sub set_rematch {
|
|
my $self = shift;
|
|
my $flag_id = shift;
|
|
my $value = shift;
|
|
my $superdata = $self->_get_superdata;
|
|
my $save = $self->_get_current_save;
|
|
Rsaves::set_rematch( $save, $superdata, $flag_id, $value );
|
|
$self->_set_superdata($superdata);
|
|
}
|
|
|
|
sub set_flag {
|
|
my $self = shift;
|
|
my $flag_id = shift;
|
|
my $value = shift;
|
|
my $superdata = $self->_get_superdata;
|
|
my $save = $self->_get_current_save;
|
|
Rsaves::set_flag_id( $save, $superdata, $flag_id, $value );
|
|
$self->_set_superdata($superdata);
|
|
}
|
|
|
|
sub _set_superdata {
|
|
my $self = shift;
|
|
my $superdata = shift;
|
|
my $save = $self->_get_current_save;
|
|
Rsaves::set_first_super_data( $save, $superdata );
|
|
}
|
|
|
|
sub _saves {
|
|
my $self = shift;
|
|
my $saves = $self->__saves;
|
|
if ( !defined $saves ) {
|
|
$self->_build_saves_and_extra;
|
|
}
|
|
return $self->__saves;
|
|
}
|
|
|
|
sub _extra {
|
|
my $self = shift;
|
|
my $extra = $self->__extra;
|
|
if ( !defined $extra ) {
|
|
$self->_build_saves_and_extra;
|
|
}
|
|
return $self->__extra;
|
|
}
|
|
|
|
sub _get_superdata {
|
|
my $self = shift;
|
|
return Rsaves::get_first_super_data( $self->_get_current_save );
|
|
}
|
|
|
|
sub _get_rematches_hash_by_id {
|
|
my $self = shift;
|
|
my @rematches = $self->_get_rematches_constant_list;
|
|
my $rematches = {@rematches};
|
|
my @final_hash = (
|
|
map { $_ => $rematches->{$_} }
|
|
grep { $_ =~ /^\d+$/ } keys %$rematches
|
|
);
|
|
return @final_hash;
|
|
}
|
|
|
|
sub _build_saves_and_extra {
|
|
my $self = shift;
|
|
my ( @saves_raw, $extra );
|
|
( @saves_raw[ 0, 1 ], $extra ) = Rsaves::read_save( $self->input_file );
|
|
my @saves = Rsaves::get_saves( @saves_raw, $EMERALD_VERSION );
|
|
$self->__saves( \@saves );
|
|
$self->__extra($extra);
|
|
$self->store_initial_flags_and_rematch;
|
|
}
|
|
|
|
sub store_initial_flags_and_rematch {
|
|
my $self = shift;
|
|
$self->_initial_flags( [@{$self->get_flags_save}] );
|
|
$self->_initial_rematches( [@{$self->get_rematches_save}] );
|
|
}
|
|
|
|
sub _get_rematches_constant_list {
|
|
return @Rsaves::Constants::Emerald::Rematches::REMATCHES;
|
|
}
|
|
|
|
sub _get_flags_constant_list {
|
|
return @Rsaves::Constants::Emerald::Flags::FLAGS;
|
|
}
|
|
|
|
sub _get_current_save {
|
|
my $self = shift;
|
|
return
|
|
$self->_saves->[ Rsaves::find_current_save_index( @{ $self->_saves } ) ];
|
|
}
|
|
|
|
sub _get_flags_hash_by_id {
|
|
my $self = shift;
|
|
my @flags = $self->_get_flags_constant_list;
|
|
my $flags = {@flags};
|
|
my @final_hash = (
|
|
map { $_ => $flags->{$_} }
|
|
grep { $_ =~ /^\d+$/ } keys %$flags
|
|
);
|
|
return @final_hash;
|
|
}
|
|
|
|
sub get_pc_system {
|
|
my $self = shift;
|
|
if (defined $self->_pc) {
|
|
return $self->_pc;
|
|
}
|
|
my $pc = Rsaves::read_pc_storage($self->_get_current_save);
|
|
my $return = GEmeTool::Save::PokemonPC->new(_pc => $pc, _save => sub {
|
|
my $pc = shift;
|
|
Rsaves::save_pc_changes($self->_get_current_save, $pc)
|
|
});
|
|
$self->_pc($return);
|
|
return $return;
|
|
}
|
|
1;
|