Skip to content
Snippets Groups Projects
Commit dc4fc81c authored by James R.'s avatar James R.
Browse files

Update replay format to Kart 1.1

parent b08fcdb0
No related branches found
No related tags found
1 merge request!1Update replay parser to Kart 1.1 demo format
......@@ -30,7 +30,7 @@ class ReplayParser
'speed' => $info['kartspeed'],
'weight' => $info['kartweight'],
]);
$replay = new Replay([
'race_tics' => $info['racetime'],
'lap_tics' => $info['laptime'],
......@@ -57,12 +57,47 @@ class ReplayParser
return $checksum;
}
protected function skipFileList(string $p, int $off) : int
{
// PHP sucks and I don't like it.
$total = unpack('C', $p, $off)[1];
for ($off++; $total--;)
{
// file name
// Basically memchr to find the terminating byte.
if (( $n = strpos($p, "\0", $off) - $off + 1 ) < 64)
$off += $n;
else
$off += 64;
$off += 16; // checksum
}
return $off;
}
protected function skipNetVars(string $p, int $off) : int
{
$total = unpack('v', $p, $off)[1];
for ($off += 2; $total--;)
{
// netid, string value, and stealth flag.
$off = ( strpos($p, "\0", $off + 2) + 1 ) + 1;
}
return $off;
}
protected function parseInfo(string $replayContents) : array
{
return unpack($this->replayFormat(), $replayContents);
$header = unpack($this->replayHeaderFormat(), $replayContents);
$off = $this->skipFileList($replayContents, 120);
$timing = unpack($this->replayRecordFormat(), $replayContents, $off);
// Skip Record Attack info, random seed and extrainfo offset.
// Also skip demo player number.
$off = $this->skipNetVars($replayContents, $off + 16) + 1;
$player = unpack($this->replayPlayerFormat(), $replayContents, $off);
return array_merge($header, $timing, $player);
}
protected function validateStructure(string $header, string $playString, int $demoFlags) : void
{
if ($header !== "\xF0" . 'KartReplay' . "\x0F") {
......@@ -102,7 +137,7 @@ class ReplayParser
}
}
protected function replayFormat() : string
protected function replayHeaderFormat() : string
{
$props = [
// Header - should equal "\xF0" "KartReplay" "\x0F"
......@@ -112,6 +147,9 @@ class ReplayParser
'c' . 'version',
'c' . 'subversion',
'v' . 'demoversion',
// Replay title, which we don't actually need.
'a64' . 'UNUSED',
// Checksum
'a16' . 'checksum',
......@@ -127,21 +165,32 @@ class ReplayParser
// Demo flags - This % 6 == 2 or replay is invalid
'c' . 'demoflags',
];
return implode('/', $props);
}
protected function replayRecordFormat() : string
{
$props = [
// Time/lap
'V' . 'racetime',
'V' . 'laptime',
];
return implode('/', $props);
}
// Random seed. We don't care about this but it's in the way.
'V' . 'UNUSED',
protected function replayPlayerFormat() : string
{
$props = [
// Player attributes
'Z16' . 'name',
'Z16' . 'skin',
'Z16' . 'color',
// Stats that aren't relevant for us
'c5' . 'UNUSED',
// Score; not relavent for us
'V' . 'UNUSED',
// Kart stats, to differentiate between characters with the same name and different stats.
'c' . 'kartspeed',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment