GEmeTool/lib/GEmeTool/Save.pm

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;