#!/opt/bin/perl #TODO: dwall3_3 => dwall_3_3 #TODO: fix dialogue #TODO: update file format version # this script checks, fixes and simplifies @match expressions in a map use common::sense; use Deliantra; use Deliantra::Map; Deliantra::load_archetypes; our $dirty; our $path; sub fix_msg($) { my ($msg) = @_; local $_ = $msg; # fx pretty common error of having "* First line of response" my $response = s/^\* (.*)/*/ ? "\n$1" : ""; warn "$path ($_) unexpected characters in match \n" if !/^[a-zA-Z\[\]\|\*\!\' 0-9\-\?]+$/; s/\[(.)(.)\]/(lc $1) eq (lc $2) ? lc $1 : "[$1$2]"/ge; my %alt; for my $kw (split /\|/) { $kw =~ s/^\s+//; $kw =~ s/\s+$//; $alt{lc $kw} = $kw; } $_ = join "|", sort keys %alt; $_ .= $response; warn "$path <$msg><$_>\n" if $_ ne $msg; warn "$path ($_) unexpected characters in match\n" if /[\[\]]/; $_ } sub patch_arch($) { warn "$path: references unknown archetype $_[0]{_name}\n" unless exists $ARCH{ $_[0]{_name} }; if ($_[0]{face} =~ /\.[1-9]\d\d$/) { $_[0]{face} =~ s/\.([2-9])\1\1$/.x1$1/; # 222, 333, 444 $_[0]{face} =~ s/\.1(\d\d)$/.x$1/; # 1AB xAB $dirty++; } } sub patch_inv($) { my ($arch) = @_; my $inv = $arch->{inventory} || []; for (@$inv) { patch_arch $_; if ($_->{type} == 116 || $_->{_name} =~ /^event_/) { # deliantra to old deliantra+ if ($_->{slaying} eq '/python/IPO/send.py') { $_->{title} = 'perl'; $_->{slaying} = 'ipo'; $dirty++ } elsif ($_->{slaying} eq '/python/IPO/receive.py') { $_->{title} = 'perl'; $_->{slaying} = 'ipo'; $dirty++; } elsif ($_->{slaying} eq '/python/IPO/board.py') { $_ = { _name => 'event_apply', title => 'perl', slaying => 'board' }; $arch->{msg} = '@match *'."\n".'@eval board::command $who, $msg, $npc'."\n"; $dirty++; } elsif ($_->{slaying} eq '/python/IPO/say.py') { $arch->{msg} = '@match *'."\n".'@eval ipo::command $who, $msg, $npc'."\n"; $_ = undef; $dirty++; } elsif ($_->{slaying} eq '/python/IPO/banksay.py') { $arch->{msg} = '@match *'."\n".'@eval bank::command $who, $msg, $npc'."\n"; $_ = undef; $dirty++; } # old deliantra+ to new plug-in system if ($_ && $_->{title} eq "perl") { if ($_->{slaying} eq "board") { push @{$arch->{attach}}, ["board"]; $_ = undef; $dirty++; } elsif ($_->{slaying} eq "ipo") { if ($_->{_name} eq "event_close") { push @{$arch->{attach}}, ["ipo_mailbox"]; } elsif ($_->{_name} eq "event_apply") { # } $_ = undef; $dirty++; } elsif ($_->{slaying} eq "nimbus") { push @{$arch->{attach}}, ["nimbus_exit", { restore => $_->{name} eq "restore"}]; $_ = undef; $dirty++; } elsif ($_->{slaying} eq "minesweeper") { push @{$arch->{attach}}, ["minesweeper", { split /(?:\s+|=)/, $_->{name} }]; $_ = undef; $dirty++; } elsif ($_->{slaying} eq "reseller") { if ($_->{_name} eq "event_drop_on") { push @{$arch->{attach}}, ["reseller_floor"]; } elsif ($_->{_name} eq "event_trigger") { my ($a, $b, $c) = split /,/, $_->{name}; push @{$arch->{attach}}, ["reseller_shopmat", {npc_name => $a, npc_x => $b, npc_y => $c}]; } $_ = undef; $dirty++; } else { warn "WARNING: unsupported perl event<$_->{slaying}>\n";#d# } } } } $arch->{inventory} = [grep $_, @$inv]; } for $path (@ARGV) { eval { open my $fh, "<:raw:perlio:utf8", $path or die "$path: $!\n"; <$fh> =~ /^arch \S+$/ or die "$path: not a deliantra map file\n"; my $map = new_from_file Deliantra::Map $path or die "$path: file load error\n"; $dirty = 0; for my $a (map @$_, grep $_, map @$_, grep $_, @{ $map->{map} }) { patch_arch $a; patch_inv $a if $a->{inventory}; next unless $a->{msg} =~ /^\@match /; my $old = $a->{msg}; $a->{msg} =~ s/^(\@match\s+)(.*)$/$1 . fix_msg $2/gme; $dirty ||= $old ne $a->{msg}; } $map->write_file ($path) if $dirty; 1 } or $@ =~ /not a deliantra map/ or warn $@; }