forked from crawl/sequell
/
reassemble-logmile.pl
141 lines (120 loc) · 3.68 KB
/
reassemble-logmile.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#! /usr/bin/perl
use strict;
use warnings;
use DBI;
my $version = '0.5';
my $REBUILT_LOGFILE = 'logfile-rebuilt';
my $REBUILT_MILESTONES = 'milestones-rebuilt';
# Log field names. These are logfile names, although rstart, rend, and rtime
# are Henzell db column names instead.
my @RLOGF = qw/v lv sc name uid race cls char
xl sk sklev title ktyp killer kaux place br lvl
ltyp hp mhp mmhp dam str int dex god piety pen wiz rstart
rend dur turn urune nrune tmsg vmsg/;
my @RMILEF =
qw/v name race cls char xl sk sklev title
place br lvl ltyp hp mhp mmhp str int dex god
dur turn urune nrune rstart rtime verb milestone/;
our %LOG2SQL = ( name => 'pname',
char => 'charabbrev',
str => 'sstr',
dex => 'sdex',
int => 'sint',
start => 'tstart',
end => 'tend',
time => 'ttime');
# Map field names from Henzellese to logfilese or milestonese.
my %HENZELL_TO_LOG =
(
rstart => 'start',
rend => 'end',
rtime => 'time',
verb => 'type'
);
reconstruct_files();
sub new_db_handle {
DBI->connect("dbi:mysql:henzell", 'henzell', '')
}
sub run_query {
my ($db, $query) = @_;
my $st = $db->prepare($query) or die "Can't prepare $query: $!\n";
$st->execute() or die "Query $query failed: $!\n";
$st
}
sub xlog_escape {
my $field = shift;
$field =~ s/:/::/g;
$field
}
sub xlog_str {
my $hash = shift;
my @keys = sort(keys %$hash);
join(":", map("$_=" . xlog_escape($$hash{$_}), sort(keys %$hash)))
}
sub reconstruct_xfile {
my ($db, $file, $table, @fields) = @_;
if (-f $file) {
print "Skipping reconstruction of $file, delete it if you want to regen\n";
return;
}
open my $outf, '>', $file or die "Can't write $file: $!\n";
push @fields, 'offset';
my @sqlfields = map($LOG2SQL{$_} || $_, @fields);
my $query = ('SELECT ' . join(", ", @sqlfields) . ' FROM ' . $table
. " WHERE v = '$version' AND src='cao' ORDER BY id");
print "Rebuilding $file using $query\n";
my $st = run_query($db, $query);
my $lastrow;
my $lastrowsz;
my $lastrowoffset;
my $offset = 0;
while (my $row = $st->fetchrow_arrayref) {
my %table;
my @henzell_fields = map($HENZELL_TO_LOG{$_} || $_, @fields);
@table{@henzell_fields} = @$row;
my $diff = $table{offset} - $offset;
if ($diff > 10 || $diff < 0) {
die "Row at wrong offset ($offset, wanted $table{offset}), possibly because of previous row: $lastrow\n";
}
# Oops, are we short on a few characters? FAKE IT!
my $padding = '';
if ($diff) {
# Arr, pad it out, me hearties!
$padding = ' ' x $diff;
}
$lastrowoffset = $table{offset};
delete $table{offset};
for (qw/nrune urune wiz pen god kaux piety vmsg killer/) {
delete $table{$_} if exists $table{$_} && !$table{$_};
}
if (exists $table{type}) {
for ($table{type}) {
s/\.ban$//;
$_ = 'branch-finale' if $_ eq 'br.end';
$_ = 'enter' if $_ eq 'br.enter';
}
}
$table{lv} ||= '0.1';
$table{uid} ||= '5';
$lastrow = $padding . xlog_str(\%table);
$lastrowsz = length($lastrow) + 1;
$offset += $lastrowsz;
print $outf "$lastrow\n";
}
close $outf;
}
sub reconstruct_logfile {
my ($db, $file) = @_;
reconstruct_xfile($db, $file, 'logrecord', @RLOGF);
}
sub reconstruct_milestones {
my ($db, $file) = @_;
reconstruct_xfile($db, $file, 'milestone', @RMILEF);
}
sub reconstruct_files {
my $db = new_db_handle();
print "Rebuilding logfiles and milestones ",
"(to $REBUILT_LOGFILE/$REBUILT_MILESTONES)\n";
reconstruct_logfile($db, $REBUILT_LOGFILE);
reconstruct_milestones($db, $REBUILT_MILESTONES);
}