private function parseGameEventsFile_22612(&$string) { $playerLeft = array(); $events = array(); $time = 0; $numEvents = 0; $eventType = 0; $stream = new BitStream($string); while (true) { $stream->alignToNextByte(); if ($stream->EOFreached()) { break; } $knownEvent = true; $timeStampLen = $stream->readBits(2); $timeStamp = $stream->readBits(6 + $timeStampLen * 8); $playerId = $stream->readBits(4); $globalEventFlag = $stream->readBits(1); if (isset($this->players[$playerId])) { $playerName = $this->players[$playerId]['name']; } else { $playerName = ""; } $eventType = $stream->readBits(7); $time += $timeStamp; $numEvents++; if ($globalEventFlag > 0 && $playerId > 0) { $knownEvent = false; } else { switch ($eventType) { case 0x5: // game starts if ($globalEventFlag == 0 || $playerId > 0) { $knownEvent = false; } break; case 0xc: // player enters game $stream->readBits(8); if ($playerId == 0) { $knownEvent = false; } break; case 0x1b: // abilities $flags = $stream->readBits(20); $defaultAbility = $stream->readBits(1); if ($defaultAbility) { $abilityID = $stream->readBits(16); $buttonIndex = $stream->readBits(5); $stream->skipBits(1); if (!$this->players[$playerId]['isObs'] && $this->players[$playerId]['race'] == "") { if ($abilityID == 0x93) { $this->players[$playerId]['race'] = "Terran"; } elseif ($abilityID == 0xa7) { $this->players[$playerId]['race'] = "Protoss"; } elseif ($abilityID == 0xb9) { $this->players[$playerId]['race'] = "Zerg"; } } } $targetType = $stream->readBits(2); switch ($targetType) { case 0: break; case 1: $targetX = $stream->readBits(20); $targetY = $stream->readBits(20); $targetZ = $stream->readBits(32); break; case 2: $stream->skipBits(8); $stream->skipBits(8); $unitID = $stream->readBits(32); $unitType = $stream->readBits(16); $hasPlayer = $stream->readBits(1); if ($hasPlayer) { $targetPlayer = $stream->readBits(4); } $hasTeam = $stream->readBits(1); if ($hasTeam) { $targetTeam = $stream->readBits(4); } $targetX = $stream->readBits(20); $targetY = $stream->readBits(20); $targetZ = $stream->readBits(32); break; case 3: $unitID = $stream->readBits(32); break; } $stream->skipBits(1); break; case 0x1c: // unit selection $wireframeIndex = $stream->readBits(4); $subgroupIndex = $stream->readBits(9); $updateFlags = $stream->readBits(2); switch ($updateFlags) { case 0: $unitTypes = $stream->readBits(9); for ($i = 0; $i < $unitTypes; $i++) { $unitTypeID = $stream->readBits(16); $unitSubtype = $stream->readBits(8); $unitsOfType = $stream->readBits(9); } $unitIDs = $stream->readBits(9); for ($i = 0; $i < $unitIDs; $i++) { $unitID = $stream->readBits(32); } break; case 1: $unitsAffected = $stream->readBits(9); $removedUnitFlags = $stream->readBits($unitsAffected); $unitTypes = $stream->readBits(9); for ($i = 0; $i < $unitTypes; $i++) { $unitTypeID = $stream->readBits(16); $unitSubtype = $stream->readBits(8); $unitsOfType = $stream->readBits(9); } $unitIDs = $stream->readBits(9); for ($i = 0; $i < $unitIDs; $i++) { $unitID = $stream->readBits(32); } break; case 2: case 3: $wIndexLen = $stream->readBits(9); $stream->skipBits(9 * $wIndexLen); $unitTypes = $stream->readBits(9); for ($i = 0; $i < $unitTypes; $i++) { $unitTypeID = $stream->readBits(16); $unitSubtype = $stream->readBits(8); $unitsOfType = $stream->readBits(9); } $unitIDs = $stream->readBits(9); for ($i = 0; $i < $unitIDs; $i++) { $unitID = $stream->readBits(32); } break; } break; case 0x1d: // Control groups $controlGroup = $stream->readBits(4); $actionType = $stream->readBits(2); $updateType = $stream->readBits(2); switch ($updateType) { case 0: break; case 1: $unitsAffected = $stream->readBits(9); $stream->skipBits($unitsAffected); break; case 2: case 3: $unitIndices = $stream->readBits(9); $stream->skipBits($unitIndices * 9); break; } break; case 0x19: // leaves game if ($this->players[$playerId]['team'] > 0) { // don't log observers/party members etc $playerLeft[] = $playerId; } break; case 0x1f: // Resource trading $sendee = $stream - readBits(4); $stream->skipBits(3); $minerals = $stream->readBits(32); $vespene = $stream->readBits(32); $terrazine = $stream->readBits(32); $wasistdas = $stream->readBits(32); break; case 0x23: // Unknown $stream->skipBits(8); break; case 0x26: // Unknown $stream->skipBits(64); break; case 0x27: // Target critter $stream->skipBits(32); break; case 0x31: // camera movement $xCoord = $stream->readBits(16); $yCoord = $stream->readBits(16); $zoomFlag = $stream->readBits(1); if ($zoomFlag) { $zoom = $stream->readBits(16); } $pitchFlag = $stream->readBits(1); if ($pitchFlag) { $pitch = $stream->readBits(16); } $yawFlag = $stream->readBits(1); if ($yawFlag) { $yaw = $stream->readBits(16); } $someFlag = $stream->readBits(1); break; case 0x37: // Unknown $stream->skipBits(64); break; case 0x38: // Unknown $arrayLen = $stream->readBits(8); $stream->skipBits(32 * $arrayLen); $arrayLen = $stream->readBits(8); $stream->skipBits(32 * $arrayLen); break; case 0x3c: // Unknown $stream->skipBits(16); break; case 0x46: // Computer requests resources $stream->skipBits(3); $minerals = $stream->readBits(32); $vespene = $stream->readBits(32); $terrazine = $stream->readBits(32); $wasistdas = $stream->readBits(32); break; case 0x4c: //???? $stream->skipBits(4); break; case 0x59: // sync? $stream->skipBits(32); break; default: $knownEvent = false; break; } } if ($knownEvent == false) { if ($this->debug) { $this->debug(sprintf("Unknown event: Timestamp: %d, Type: %02X, Global: %d, Player ID: %d (%s), Byte: %08X<br />\n", $timeStamp, $eventType, $globalEventFlag, $playerId, $playerName, $stream->getByte())); } return false; } else { if ($this->debug >= 2) { $this->debug(sprintf("DEBUG L2: Timestamp: %d, Frames: %d, Type: %02X, Global: %d, Player ID: %d (%s), Byte: %08X<br />\n", floor($time / 16), $timeStamp, $eventType, $globalEventFlag, $playerId, $playerName, $stream->getByte())); } } } $this->populateWinners($playerLeft); return $numEvents; }