public function parseKWData($data) { if (strlen($data) == 0) { return; } $hexdata = bin2hex($data); //先解析地图 //先找结尾 $mapEnd = strpos($hexdata, "0000460061006b006500"); //f.a.k.e $mapString = substr($hexdata, 0, $mapEnd); $mapStart = strrpos($mapString, "0000") + 4; //地图开头之前是0000 $mapName = substr($mapString, $mapStart); $this->mapName = hex2gbk($mapName); //地图名 //先寻找/official $flag = "/official/"; $fileStart = strpos($hexdata, bin2hex($flag)) + strlen($flag) * 2; $fileEnd = strpos($hexdata, "3b4d", $fileStart); $mapFileName = substr($hexdata, $fileStart, $fileEnd - $fileStart); $this->mapFileName = hex2bin($mapFileName); //玩家信息,"S=H"之后 $index = 0; $playerStart = strpos($hexdata, "533d48", $fileEnd) + 6; // $playerTotalEnd = strpos($hexdata, "3a3b", $playerStart) + 2; $playerString = substr($hexdata, $playerStart, $playerTotalEnd - $playerStart); //需要扫描两种标准,第一种玩家,第二种电脑 $playerStart = 0; //$players = preg_split("/313a|2c3a|293a/", $playerString); $players = preg_split("/2c/", $playerString); $ccount = count($players); $step = 11; for ($pindex = 0; $pindex < $ccount; $pindex += $step) { $nameclip = $players[$pindex + 0]; $nameStart = strpos($nameclip, "3a48"); if ($nameStart !== false || $pindex == 0) { //是人 $step = 11; if ($pindex != 0) { $nameStart += 4; $name = substr($players[$pindex + 0], $nameStart, strlen($players[$pindex + 0]) - $nameStart); } else { $name = $players[0]; } if (array_search(hex2bin($players[5 + $pindex]), $this->sides) !== false) { array_push($this->players['id'], hex2bin($name)); array_push($this->players['side'], 'kw' . hex2bin($players[5 + $pindex])); array_push($this->players['sidenumber'], hex2bin($players[5 + $pindex])); array_push($this->players['team'], hex2bin($players[7 + $pindex])); array_push($this->players['ishuman'], '1'); } } else { $nameStart = strpos($players[$pindex + 0], "3a43"); if ($nameStart !== false) { $nameStart += 4; //是机器 $step = 6; $name = substr($players[$pindex + 0], $nameStart, strlen($players[$pindex + 0]) - $nameStart); if (array_search(hex2bin($players[2 + $pindex]), $this->sides) !== false) { switch ($name) { case '45': array_push($this->players['id'], 'ra3CE'); //简单电脑 break; case '4d': array_push($this->players['id'], 'ra3CM'); //中等电脑 break; case '48': array_push($this->players['id'], 'ra3CH'); //困难电脑 break; case '42': array_push($this->players['id'], "ra3CB"); //凶残电脑 break; default: array_push($this->players['id'], "ra3CU"); //未知电脑 break; } array_push($this->players['side'], 'kw' . hex2bin($players[2 + $pindex])); array_push($this->players['sidenumber'], hex2bin($players[2 + $pindex])); array_push($this->players['team'], hex2bin($players[4 + $pindex])); array_push($this->players['ishuman'], '0'); } } } } //end for //寻找版本号 $verEnd = strpos($hexdata, "000000000002", $playerTotalEnd); //先找结尾,F3C748 $verData = substr($hexdata, $playerTotalEnd, $verEnd - $playerTotalEnd); //var_dump($verData); $verStart = strrpos($verData, "00") + 2; $verString = substr($verData, $verStart, 6); //只取3位版本 $this->version = hex2bin($verString); //只用了2字节,所以用hex2bin //寻找日期 //从版本号回退40字节 $dateStart = $verStart - 40 + $playerTotalEnd; $dateString = substr($hexdata, $dateStart, 24); //固定长度 //解析年 $year = substr($dateString, 0, 4); $year = ChangeLowHigh($year); $year = intval($year, 16); //解析月 $month = substr($dateString, 4, 2); $month = intval($month, 16); //解析日 $day = substr($dateString, 12, 2); $day = intval($day, 16); //时 $hour = substr($dateString, 16, 2); $hour = intval($hour, 16); //分 $min = substr($dateString, 20, 2); $min = intval($min, 16); $min = $min < 10 ? "0" . $min : $min; //时间字符串 $this->playTime = "{$year}-{$month}-{$day} {$hour}:{$min}"; //时长 $flag = "FOOTER"; $timeStart = strpos($hexdata, bin2hex($flag)) + strlen($flag) * 2; $timeSpan = substr($hexdata, $timeStart, 4); $timeSpan = ChangeLowHigh($timeSpan); $timeNumber = (int) (intval($timeSpan, 16) / 15); $this->gameLength = $timeNumber; $timeMin = (int) ($timeNumber / 60); $timeSec = $timeNumber - $timeMin * 60; $timeHour = (int) ($timeMin / 60); if ($timeHour != 0) { $timeMin = $timeMin - $timeHour * 60; } //$this->gameLengthString = "用时:"; if ($timeHour > 0) { $this->gameLengthString .= $timeHour . "时"; } if ($timeMin > 0) { $this->gameLengthString .= $timeMin . "分"; } if ($timeSec > 0) { $this->gameLengthString .= $timeSec . "秒"; } }
public function parseDOWIIData($data) { if (strlen($data) == 0) { return; } $hexdata = bin2hex($data); $hexdataLen = strlen($hexdata); //寻找日期 $start = strpos($hexdata, "4543") + 4; $end = strpos($hexdata, "0000", $start) + 2; //只所以向后加2是因为会有00是有用的情况 $replayTime = substr($hexdata, $start, $end - $start); $this->playTime = hex2gbk($replayTime); //寻找地图 $start = strpos($hexdata, "7076705c") + 8; //为“pvp\” $end = strpos($hexdata, "0000", $start) - 8; //结尾是找到四个0后,再往前8个字节 $maplen = $end - $start; if ($maplen != (int) ($maplen / 2) * 2) { $maplen += 1; } $replayMap = substr($hexdata, $start, $maplen); $this->mapName = hex2bin($replayMap); //寻找玩家 //DATAINFO后50个字节开始 $index = 0; $searchIndex = 0; while (true) { $datainfo = "44415441494e46"; $start = strpos($hexdata, $datainfo, $searchIndex); //寻找DATAINFO if ($start === false) { //没有了,退出 break; } $start = $start + strlen($datainfo) + 50; //地址前移自身长度与48个字节是玩家信息的开始 $lenStart = $start - 8; $lenString = substr($hexdata, $lenStart, 2); $len = intval($lenString, 16); //玩家名字长度 $replayPlayer = substr($hexdata, $start, $len * 4); //截取玩家信息 $replayPlayer = hex2gbk($replayPlayer); //截取阵营信息,从玩家结尾前进16个字节 //阵营信息长度 $lenStart = $start + $len * 4 + 16; $lenString = substr($hexdata, $lenStart, 2); $len = intval($lenString, 16); //阵营开头,前进8个字节 $sideStart = $lenStart + 8; $playerSide = substr($hexdata, $sideStart, $len * 2); $playerSide = hex2bin($playerSide); if (strlen($replayPlayer) > 0) { array_push($this->players['id'], $replayPlayer); array_push($this->players['side'], $playerSide); array_push($this->players['team'], $index); } $searchIndex = $end; $index++; if ($index > 16) { break; } $searchIndex = $start + 1; } //重新划定队伍,上半区为0,下半区为1 $separator = $index / 2; $count = count($this->players['id']); for ($ti = 0; $ti < $count; $ti++) { if ($this->players['team'][$ti] < $separator) { $this->players['team'][$ti] = 0; } else { $this->players['team'][$ti] = 1; } } //时间,文件结尾00 00 00 20后第一个字段,长度8字节 //读取文件最后的部分 $timeFlag = "00000020"; $timeStart = strrpos($hexdata, $timeFlag); $resist = 0; while ($timeStart != (int) ($timeStart / 2) * 2 && $resist < 10) { $timeStart = strrpos($hexdata, $timeFlag, $timeStart - $hexdataLen - 1); $resist++; } $timeStart += strlen($timeFlag); //$timeStart = strlen($hexdata)-24; $time1 = ChangeLowHigh(substr($hexdata, $timeStart, 4)); $time2 = ChangeLowHigh(substr($hexdata, $timeStart + 4, 4)); //对调高低位 $newtime = $time2 . $time1; // var_dump($newtime); $timeNumber = (int) (intval($newtime, 16) / 8); $this->gameLength = $timeNumber; $timeMin = (int) ($timeNumber / 60); $timeSec = $timeNumber - $timeMin * 60; $timeHour = (int) ($timeMin / 60); if ($timeHour != 0) { $timeMin = $timeMin - $timeHour * 60; } //$this->gameLengthString = "用时:"; if ($timeHour > 0) { $this->gameLengthString .= $timeHour . "时"; } if ($timeMin > 0) { $this->gameLengthString .= $timeMin . "分"; } if ($timeSec > 0) { $this->gameLengthString .= $timeSec . "秒"; } }
public function parseZHData($data) { if (strlen($data) == 0) { return; } $hexdata = bin2hex($data); //先解析地图 //地图名 $mapEnd = strpos($hexdata, "3b4d43"); //;MC $mapString = substr($hexdata, 0, $mapEnd); $mapStart = strrpos($mapString, "3b4d3d") + 6; //地图开头之前是;M= $mapStart = strrpos($mapString, "2f", $mapStart) + 2; $mapName = substr($mapString, $mapStart); $this->mapName = hex2bin($mapName); $this->mapFileName = preg_replace("/\\s/", "", $this->mapName); //玩家信息,"S=H"之后 $index = 0; $playerStart = strpos($hexdata, "533d48", $fileEnd) + 6; // $playerTotalEnd = strpos($hexdata, "3a3b", $playerStart) + 2; $playerString = substr($hexdata, $playerStart, $playerTotalEnd - $playerStart); //需要扫描两种标准,第一种玩家,第二种电脑 $playerStart = 0; //$players = preg_split("/313a|2c3a|293a/", $playerString); $players = preg_split("/2c/", $playerString); $ccount = count($players); for ($pindex = 0; $pindex < $ccount; $pindex += $step) { $nameclip = $players[$pindex + 0]; $nameStart = strpos($nameclip, "3a48"); if ($nameStart !== false || $pindex == 0) { //是人 $step = 8; if ($pindex != 0) { $nameStart += 4; $name = substr($players[$pindex + 0], $nameStart, strlen($players[$pindex + 0]) - $nameStart); } else { $name = $players[0]; } if (array_search(hex2bin($players[5 + $pindex]), $this->sides) !== false) { array_push($this->players['id'], hex2bin($name)); array_push($this->players['side'], $this->prefix . hex2bin($players[5 + $pindex])); array_push($this->players['sidenumber'], hex2bin($players[5 + $pindex])); array_push($this->players['team'], hex2bin($players[7 + $pindex])); array_push($this->players['ishuman'], '1'); } } else { $nameStart = strpos($players[$pindex + 0], "3a43"); if ($nameStart !== false) { $nameStart += 4; //是机器 $step = 4; $name = substr($players[$pindex + 0], $nameStart, strlen($players[$pindex + 0]) - $nameStart); if (array_search(hex2bin($players[2 + $pindex]), $this->sides) !== false) { switch ($name) { case '45': array_push($this->players['id'], 'ra3CE'); //简单电脑 break; case '4d': array_push($this->players['id'], 'ra3CM'); //中等电脑 break; case '48': array_push($this->players['id'], 'ra3CH'); //困难电脑 break; default: array_push($this->players['id'], "ra3CU"); //未知电脑 break; } array_push($this->players['side'], $this->prefix . hex2bin($players[2 + $pindex])); array_push($this->players['sidenumber'], hex2bin($players[2 + $pindex])); $team = hex2bin($players[4 + $pindex]); array_push($this->players['team'], substr($team, 0, 1)); array_push($this->players['ishuman'], '0'); } } } } //end for //寻找版本号 $verStart = strpos($hexdata, "002e00") - 2; //先找.,F3C748 $verEnd = strpos($hexdata, "000000", $verStart) + 2; //前面0是版本号的一部分 $verData = substr($hexdata, $verStart, $verEnd - $verStart); // var_dump($verData); $this->version = hex2gbk($verData); //寻找日期 //第一个00后推12个00,再次寻找到连续的两个00(英文版三个00) $dateStart = strpos($hexdata, "00"); $dateStart += 26; $dateStart = strpos($hexdata, "0000", $dateStart) + 4; $testchar = substr($hexdata, $dateStart, 2); if ($testchar == "00") { $dateStart += 2; } $dateString = substr($hexdata, $dateStart, 24); //固定长度 //解析年 $year = substr($dateString, 0, 4); $year = ChangeLowHigh($year); $year = intval($year, 16); //解析月 $month = substr($dateString, 4, 2); $month = intval($month, 16); //解析日 $day = substr($dateString, 12, 2); $day = intval($day, 16); //时 $hour = substr($dateString, 16, 2); $hour = intval($hour, 16); //分 $min = substr($dateString, 20, 2); $min = intval($min, 16); $min = $min < 10 ? "0" . $min : $min; //时间字符串 $this->playTime = "{$year}-{$month}-{$day} {$hour}:{$min}"; //游戏时长 //12位到20位是开始时间 $timeStart1 = ChangeLowHigh(substr($hexdata, 12, 4)); $timeStart2 = ChangeLowHigh(substr($hexdata, 16, 4)); $timeStart = intval($timeStart2 . $timeStart1, 16); //21到29是结束时间 $timeEnd1 = ChangeLowHigh(substr($hexdata, 20, 4)); $timeEnd2 = ChangeLowHigh(substr($hexdata, 24, 4)); $timeEnd = intval($timeEnd2 . $timeEnd1, 16); $timeNumber = $timeEnd - $timeStart; $this->gameLength = $timeNumber; $timeMin = (int) ($timeNumber / 60); $timeSec = $timeNumber - $timeMin * 60; $timeHour = (int) ($timeMin / 60); if ($timeHour != 0) { $timeMin = $timeMin - $timeHour * 60; } //$this->gameLengthString = "用时:"; if ($timeHour > 0) { $this->gameLengthString .= $timeHour . "时"; } if ($timeMin > 0) { $this->gameLengthString .= $timeMin . "分"; } if ($timeSec > 0) { $this->gameLengthString .= $timeSec . "秒"; } }
public function parseCOHData($data) { $newVersion = "2.601"; //最新的版本号统一在这里修改 if (strlen($data) == 0) { return; } $hexdata = bin2hex($data); $hexdataLen = strlen($hexdata); //寻找日期 $start = strpos($hexdata, "4543") + 4; $end = strpos($hexdata, "0000", $start) + 2; //只所以向后加2是因为会有00是有用的情况 $replayTime = substr($hexdata, $start, $end - $start); $this->playTime = hex2gbk($replayTime); //寻找地图 $start = strpos($hexdata, "6d705c") + 6; //为“mp\” $end = strpos($hexdata, "0000", $start) - 8; //结尾是找到四个0后,再往前8个字节 $maplen = $end - $start; if ($maplen != (int) ($maplen / 2) * 2) { $maplen += 1; } $replayMap = substr($hexdata, $start, $maplen); $replayMap = hex2bin($replayMap); if (strpos($replayMap, "\\") !== false) { $version = $newVersion; $realMapIndex = strrpos($replayMap, "\\"); $replayMap = substr($replayMap, $realMapIndex + 1, strlen($replayMap) - $realMapIndex); } $this->mapName = $replayMap; //寻找玩家 //DATAINFO后50个字节开始 $index = 0; $searchIndex = 0; while (true) { $datainfo = "44415441494e46"; $start = strpos($hexdata, $datainfo, $searchIndex); //寻找DATAINFO if ($start === false) { //没有了,退出 break; } $start = $start + strlen($datainfo) + 50; //地址前移自身长度与48个字节是玩家信息的开始 $lenStart = $start - 8; $lenString = substr($hexdata, $lenStart, 2); $len = intval($lenString, 16); //玩家名字长度 $replayPlayer = substr($hexdata, $start, $len * 4); //截取玩家信息 $replayPlayer = hex2gbk($replayPlayer); //截取阵营信息,从玩家结尾前进24个字节 $sideStart = $start + $len * 4 + 24; //阵营结束,第一个00 $sideEnd = strpos($hexdata, "00", $sideStart); $playerSide = substr($hexdata, $sideStart, $sideEnd - $sideStart); $playerSide = hex2bin($playerSide); array_push($this->players['id'], $replayPlayer); array_push($this->players['side'], $playerSide); $searchIndex = $end; $index++; if ($index > 16) { break; } $searchIndex = $start + 1; } //时间,文件结尾00 00 00 20后第二个字段,长度4字节 //读取文件最后的部分 $timeFlag = "00000020"; $timeStart = strrpos($hexdata, $timeFlag); $resist = 0; while (($timeStart & 1) == 1 && $resist < 10) { $timeStart = strrpos($hexdata, $timeFlag, $timeStart - $hexdataLen - 1); $resist++; } $timeStart += strlen($timeFlag); if ($version != $newVersion) { //检查第9-10位是否为0 $versionCheck = substr($hexdata, $timeStart + 8, 2); //$vcheck2 = if ($versionCheck == "00") { $timeStart += 2; //是老版本 $this->version = "2.301"; } else { $this->version = "2.400"; } //是新版本 } else { $this->version = $version; } //$timeStart = strlen($hexdata)-24; $time = substr($hexdata, $timeStart, 4); //var_dump($timeStart); //对调高低位 $newtime = ChangeLowHigh($time); //var_dump($newtime); $timeNumber = (int) (intval($newtime, 16) / 8); $this->gameLength = $timeNumber; $timeMin = (int) ($timeNumber / 60); $timeSec = $timeNumber - $timeMin * 60; $timeHour = (int) ($timeMin / 60); if ($timeHour != 0) { $timeMin = $timeMin - $timeHour * 60; } //$this->gameLengthString = "用时:"; if ($timeHour > 0) { $this->gameLengthString .= $timeHour . "时"; } if ($timeMin > 0) { $this->gameLengthString .= $timeMin . "分"; } if ($timeSec > 0) { $this->gameLengthString .= $timeSec . "秒"; } }