Načtení DBC souborů v PHP
Z WoWResource Wiki
Popis PHP třídy
$dbc = new DbcReader(); // Vztvoření instance $dbc->loadDbc("jmenosoubor.dbc", "format souboru"); // Načtení souboru
Formátovací značky
- u - unsigned long (4B - 32 bitu)
- i - signed long (4B - 32 bitu)
- s - retezec
- f - float (4B)
- x - preskoč 4B
- X - preskoč 1B
Načtení hodnot se provádí pomocí fcí getInt(row, col), getUint(r, c), getString(r, c), getFloat(r, c), getByte(r, c). Funkce count() vrací počet řádků v dbc soubrou, fieldCount() vrací počet polí v jednom řádku. getLine(row) vrací celý jeden řádek, getLineCols(row, array cols) vrací vybrané sloupce jednoho řádku.
Kód tříd
class BinaryReader { private $handle; /// Handle na otevreny dbc soubor /// Konstruktor function __construct() { $this->handle = false; } /// Destruktor function __destruct() { if ($this->handle) fclose($this->handle); } public function loadFile($filename) { if ($this->handle) fclose($this->handle); $this->handle = @fopen($filename, "rb"); if (!$this->handle) die ("Soubor $filename neexistuje"); } /// Nacteni bytu public function readByte() { return ord(fread($this->handle, 1)); } /// Nacteni unsigned int public function readUint() { $val = unpack("V*", fread($this->handle, 4)); return $val[1]; } /// Nacteni signed int public function readInt() { $val = unpack("I*", fread($this->handle, 4)); return $val[1]; } /// Nacteni float public function readFloat() { $val = unpack("f*", fread($this->handle, 4)); return $val[1]; } /// Nacteni znaku public function readChar() { return fgetc($this->handle); } public function seekPos($pos, $type = SEEK_SET) { fseek($this->handle, $pos, $type); } } class DbcReader extends BinaryReader { private $offsets; /// Offsety jednotlivych poli private $format; /// Format dbc souboru private $recSize; /// Velikost jednoho zaznamu private $recCount;/// Pocet zaznamu private $strSize; /// Velikost string casti private $fldCount;/// Pocet poli (v 1 zaznamu) /// Nacteni dbc souboru public function loadDbc($file, $format) { $this->loadFile($file); if ($this->readUint() != 0x43424457) die ("NO DBC!"); $this->recCount = $this->readUint(); $this->fldCount = $this->readUint(); $this->recSize = $this->readUint(); $this->strSize = $this->readUint(); //if (strlen($format) != $this->fldCount) // die ("Field count error"); $this->format = $format; $this->generateOffsetTable($format); } /// Vytvoreni tabulky offsetu private function generateOffsetTable($format) { $this->offsets = array(); $this->offsets[0] = 0; for ($i = 1; $i < strlen($format); $i++) { $this->offsets[$i] = $this->offsets[$i-1]; switch ($format[$i-1]) { case "b": case "X": $this->offsets[$i] += 1; break; case "x": case "u": case "i": case "f": case "s": $this->offsets[$i] += 4; break; } } $lastOff = $this->offsets[strlen($format) - 1] + ($format[strlen($format)-1] == "b" || $format[strlen($format)-1] == "X" ? 1 : 4); if ($lastOff != $this->recSize) die ("Record size error!"); } ////////////////////////////////////////////////////////////////////////////// /// Nastaveni pozice v souboru private function seekPosi($row, $col) { $pos = 20 + $row*$this->recSize + $this->offsets[$col]; //fseek($this->handle, $pos, SEEK_SET); $this->seekPos($pos); } ////////////////////////////////////////////////////////////////////////////// public function getByte($row, $col) { $this->seekPosi($row, $col); return $this->readByte(); } public function getUint($row, $col) { $this->seekPosi($row, $col); return $this->readUint(); } public function getInt($row, $col) { $this->seekPosi($row, $col); return $this->readInt(); } public function getFloat($row, $col) { $this->seekPosi($row, $col); return $this->readFloat(); } public function getString($row, $col) { $offset = $this->getUint($row, $col); $pos = 20 + $this->recCount * $this->recSize + $offset; $this->seekPos($pos); $str = ""; while (($char = $this->readChar()) != "\0") $str .= $char; return $str; } /// Vrati jeden cely radek jako pole public function getLine($row) { $ret = array(); for($i = 0; $i < $this->fldCount; $i++) { switch($this->format[$i]) { case "b": $ret[$i] = $this->getByte($row, $i); break; case "u": $ret[$i] = $this->getUint($row, $i); break; case "i": $ret[$i] = $this->getInt($row, $i); break; case "f": $ret[$i] = $this->getFloat($row, $i); break; case "s": $ret[$i] = $this->getString($row, $i); break; case "x": case "X": default: break; } } return $ret; } /// Vrati vybrane sloupecky z jednoho radku public function getLineCols($row, $cols) { $ret = array(); for($i = 0; $i < count($cols); $i++) { switch($this->format[$cols[$i]]) { case "b": $ret[$i] = $this->getByte($row, $cols[$i]); break; case "u": $ret[$i] = $this->getUint($row, $cols[$i]); break; case "i": $ret[$i] = $this->getInt($row, $cols[$i]); break; case "f": $ret[$i] = $this->getFloat($row, $cols[$i]); break; case "s": $ret[$i] = $this->getString($row, $cols[$i]); break; case "x": case "X": default: break; } } return $ret; } /// Pocet zaznamu public function count() { return $this->recCount; } /// Pocet poli public function fieldCount() { return $this->fldCount; } }
Příklad použití
$dbc =& new DbcReader(); $dbc->loadDbc("Map.dbc", "uxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxx"); //$dbc->loadDbc("SpellItemEnchantmentCondition.dbc", "ubbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"); $c = $dbc->count(); for($i = 0; $i < $c; $i++) { echo $dbc->getUint($i, 0). "\t".$dbc->getInt($i, 2)."\t".$dbc->getString($i, 4)." \n"; //echo $dbc->getUint($i,0)."\t".$dbc->getByte($i,1)."\t".$dbc->getByte($i,2)."\t".$dbc->getByte($i,3)."\n"; }