PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/classes/NBT.class.php

https://github.com/domanicYL/PocketMine-MP
PHP | 102 lines | 87 code | 5 blank | 10 comment | 9 complexity | d22a2bcbf84756ea36f2aa7f297f31d6 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /**
  3. * Class for reading in NBT-format files.
  4. *
  5. * @author Justin Martin <frozenfire@thefrozenfire.com>
  6. * @version 1.0
  7. * MODIFIED BY @shoghicp
  8. *
  9. * Dependencies:
  10. * PHP 4.3+ (5.3+ recommended)
  11. */
  12. class NBT {
  13. public $root = array();
  14. const TAG_END = 0;
  15. const TAG_BYTE = 1;
  16. const TAG_SHORT = 2;
  17. const TAG_INT = 3;
  18. const TAG_LONG = 4;
  19. const TAG_FLOAT = 5;
  20. const TAG_DOUBLE = 6;
  21. const TAG_BYTE_ARRAY = 7;
  22. const TAG_STRING = 8;
  23. const TAG_LIST = 9;
  24. const TAG_COMPOUND = 10;
  25. public function loadFile($filename) {
  26. if(is_file($filename)) {
  27. $fp = fopen($filename, "rb");
  28. }else{
  29. trigger_error("First parameter must be a filename", E_USER_WARNING);
  30. return false;
  31. }
  32. switch(basename($filename, ".dat")){
  33. case "level":
  34. $version = Utils::readLInt(fread($fp, 4));
  35. $lenght = Utils::readLInt(fread($fp, 4));
  36. break;
  37. case "entities":
  38. fread($fp, 12);
  39. break;
  40. }
  41. $this->traverseTag($fp, $this->root);
  42. return end($this->root);
  43. }
  44. public function traverseTag($fp, &$tree) {
  45. if(feof($fp)) {
  46. return false;
  47. }
  48. $tagType = $this->readType($fp, self::TAG_BYTE); // Read type byte.
  49. if($tagType == self::TAG_END) {
  50. return false;
  51. } else {
  52. $tagName = $this->readType($fp, self::TAG_STRING);
  53. $tagData = $this->readType($fp, $tagType);
  54. $tree[] = array("type"=>$tagType, "name"=>$tagName, "value"=>$tagData);
  55. return true;
  56. }
  57. }
  58. public function readType($fp, $tagType) {
  59. switch($tagType) {
  60. case self::TAG_BYTE: // Signed byte (8 bit)
  61. return Utils::readByte(fread($fp, 1));
  62. case self::TAG_SHORT: // Signed short (16 bit, big endian)
  63. return Utils::readLShort(fread($fp, 2));
  64. case self::TAG_INT: // Signed integer (32 bit, big endian)
  65. return Utils::readLInt(fread($fp, 4));
  66. case self::TAG_LONG: // Signed long (64 bit, big endian)
  67. return Utils::readLLong(fread($fp, 8));
  68. case self::TAG_FLOAT: // Floating point value (32 bit, big endian, IEEE 754-2008)
  69. return Utils::readLFloat(fread($fp, 4));
  70. case self::TAG_DOUBLE: // Double value (64 bit, big endian, IEEE 754-2008)
  71. return Utils::readLDouble(fread($fp, 8));
  72. case self::TAG_BYTE_ARRAY: // Byte array
  73. $arrayLength = $this->readType($fp, self::TAG_INT);
  74. $array = array();
  75. for($i = 0; $i < $arrayLength; $i++) $array[] = $this->readType($fp, self::TAG_BYTE);
  76. return $array;
  77. case self::TAG_STRING: // String
  78. if(!$stringLength = $this->readType($fp, self::TAG_SHORT)) return "";
  79. $string = fread($fp, $stringLength); // Read in number of bytes specified by string length, and decode from utf8.
  80. return $string;
  81. case self::TAG_LIST: // List
  82. $tagID = $this->readType($fp, self::TAG_BYTE);
  83. $listLength = $this->readType($fp, self::TAG_INT);
  84. $list = array("type"=>$tagID, "value"=>array());
  85. for($i = 0; $i < $listLength; $i++) {
  86. if(feof($fp)) break;
  87. $list["value"][] = $this->readType($fp, $tagID);
  88. }
  89. return $list;
  90. case self::TAG_COMPOUND: // Compound
  91. $tree = array();
  92. while($this->traverseTag($fp, $tree));
  93. return $tree;
  94. }
  95. }
  96. }
  97. ?>