PageRenderTime 58ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/Anvil.class.php

https://github.com/leemcd56/Minecraft-PHP-Client-2
PHP | 208 lines | 152 code | 17 blank | 39 comment | 18 complexity | b86c8dd7feac0c61c8c549e52b0696a1 MD5 | raw file
Possible License(s): WTFPL
  1. <?php
  2. /*
  3. -
  4. / \
  5. / \
  6. / MINECRAFT \
  7. / PHP \
  8. |\ CLIENT /|
  9. |. \ 2 / .|
  10. | .. \ / .. |
  11. | .. | .. |
  12. | .. | .. |
  13. \ | /
  14. \ | /
  15. \ | /
  16. \ | /
  17. by @shoghicp
  18. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  19. Version 2, December 2004
  20. Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
  21. Everyone is permitted to copy and distribute verbatim or modified
  22. copies of this license document, and changing it is allowed as long
  23. as the name is changed.
  24. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  25. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  26. 0. You just DO WHAT THE FUCK YOU WANT TO.
  27. */
  28. class Anvil{
  29. private $sections = array(
  30. "blockData" => 4096,
  31. "metaData" => 2048,
  32. "lightData" => 2048,
  33. "skyLightData" => 2048,
  34. "addData" => 2048,
  35. );
  36. protected $column, $material, $air;
  37. var $sectionSize;
  38. function __construct(){
  39. include("misc/materials.php");
  40. $this->material = $material;
  41. $this->column = array();
  42. $this->height = (int) ((string) log(HEIGHT_LIMIT, 2));
  43. $this->air = str_repeat("\x00", 2048);
  44. $this->sectionSize = 0;
  45. foreach($this->sections as $type => $size){
  46. if($type === "addData"){
  47. continue;
  48. }
  49. $this->sectionSize += $size;
  50. }
  51. }
  52. protected function splitColumns($data, $bitmask, $addBitmask, $X, $Z){
  53. $offset = 0;
  54. $len = HEIGHT_LIMIT >> 4;
  55. $lastBlock = 0;
  56. foreach($this->sections as $type => $size){
  57. $$type = b"";
  58. for($i = 0; $i < $len; ++$i){
  59. if (($type !== "addData" and $bitmask & (1 << $i)) or ($type === "addData" and $addBitmask & (1 << $i))){
  60. $$type .= substr($data, $offset, $size);
  61. $offset += $size;
  62. $lastBlock = $i << 4;
  63. }elseif($type === "blockData" and isset($this->column[$X][$Z])){
  64. $$type .= substr($this->column[$X][$Z][0], $i << 12, $size);
  65. $lastBlock = $i << 4;
  66. }elseif($type === "metaData" and isset($this->column[$X][$Z])){
  67. $$type .= substr($this->column[$X][$Z][1], $i << 11, $size);
  68. }else{
  69. $$type .= $size === 4096 ? $this->air . $this->air:$this->air;
  70. }
  71. }
  72. }
  73. $biomeData = substr($data, $offset, 256);
  74. if(!isset($this->column[$X])){
  75. $this->column[$X] = array();
  76. }
  77. $this->column[$X][$Z] = array(0 => $blockData, 1 => $metaData, 2 => $lastBlock, 3 => $biomeData);
  78. console("[DEBUG] [Anvil] Parsed X ".$X.", Z ".$Z, true, true, 2);
  79. }
  80. public function addChunk($X, $Z, $data, $bitmask, $compressed = true, $addBitmask = 0){
  81. $X = $X << 4;
  82. $Z = $Z << 4;
  83. $this->splitColumns(($compressed === true ? gzinflate(substr($data,2)):$data), $bitmask, $addBitmask, $X, $Z);
  84. console("[INTERNAL] [Anvil] Loaded X ".$X.", Z ".$Z, true, true, 3);
  85. }
  86. //O(1)
  87. public function unloadChunk($X, $Z){
  88. $X = $X << 4;
  89. $Z = $Z << 4;
  90. unset($this->column[$X][$Z]);
  91. console("[DEBUG] [Anvil] Unloaded X ".$X." Z ".$Z, true, true, 2);
  92. }
  93. //O(1)
  94. public function getIndex($x, $y, $z){
  95. $X = ($x >> 4) << 4;
  96. $Z = ($z >> 4) << 4;
  97. $aX = $x - $X;
  98. $aZ = $z - $Z;
  99. $index = ($y << $this->height) + ($aZ << 4) + $aX;
  100. return array($X, $Z, $index);
  101. }
  102. public function getColumn($x, $z, $meta = true){
  103. $index = $this->getIndex($x, 0, $z);
  104. if(!isset($this->column[$index[0]][$index[1]])){
  105. return array_fill(0, HEIGHT_LIMIT, array(0, 0));
  106. }
  107. $block = preg_replace("/(.).{".(HEIGHT_LIMIT - 1)."}/s", '$1', substr($this->column[$index[0]][$index[1]][0], $index[2], HEIGHT_LIMIT << $this->height));
  108. if($meta === true){
  109. $meta = preg_replace("/(.).{".(HEIGHT_LIMIT >> 1 - 1)."}/s", '$1', substr($this->column[$index[0]][$index[1]][0], $index[2], HEIGHT_LIMIT << ($this->height - 1)));
  110. }
  111. $data = array();
  112. $m = 0;
  113. for($i = 0; $i < HEIGHT_LIMIT; ++$i){
  114. $b = ord($block{$i});
  115. if($meta === true){
  116. $m = ord($this->column[$index[0]][$index[1]][1]{$index[2] >> 1});
  117. if($y % 2 === 0){
  118. $m = $m & 0x0F;
  119. }else{
  120. $m = $m >> 4;
  121. }
  122. }
  123. $data[$i] = array($b, $m);
  124. }
  125. return $data;
  126. }
  127. public function getFloor($x, $z, $startY = -1){ //Fast method
  128. $index = $this->getIndex($x, HEIGHT_LIMIT, $z);
  129. if(!isset($this->column[$index[0]][$index[1]])){
  130. return array(0, 0, 0);
  131. }
  132. if(((int) $startY) > -1){
  133. $i = ((int) $startY >> 4) << 4;
  134. }else{
  135. $i = $this->column[$index[0]][$index[1]][2] + 16;
  136. }
  137. $index[2] -= (HEIGHT_LIMIT - $i) << $this->height;
  138. $b =& $this->column[$index[0]][$index[1]][0];
  139. for($y = $i; $y > 0; --$y){
  140. if(!isset($this->material["nosolid"][ord($b{$index[2]})])){
  141. break;
  142. }
  143. $index[2] -= HEIGHT_LIMIT;
  144. }
  145. $block = $this->getBlock($x, $y, $z, $index);
  146. return array($y, $block[0], $block[1]);
  147. }
  148. public function getBlock($x, $y, $z, $index = false){
  149. if($index === false){
  150. $index = $this->getIndex($x, $y, $z);
  151. }
  152. if(isset($this->column[$index[0]][$index[1]])){
  153. $block = ord($this->column[$index[0]][$index[1]][0]{$index[2]});
  154. $meta = ord($this->column[$index[0]][$index[1]][1]{$index[2] >> 1});
  155. if($index[2] % 2 === 0){
  156. $meta = $meta & 0x0F;
  157. }else{
  158. $meta = $meta >> 4;
  159. }
  160. return array($block, $meta);
  161. }
  162. return array(0, 0);
  163. }
  164. public function getBiome($x, $z){
  165. $index = $this->getIndex($x, 0, $z);
  166. return ord($this->column[$index[0]][$index[1]][3]{(($z - $index[1]) << 4) + ($x - $index[0])});
  167. }
  168. public function changeBlock($x, $y, $z, $block, $meta = 0){
  169. console("[INTERNAL] [Anvil] Changed block X ".$x." Y ".$y." Z ".$z, true, true, 3);
  170. $index = $this->getIndex($x, $y, $z);
  171. if(isset($this->column[$index[0]][$index[1]][0]{$index[2]})){
  172. $this->column[$index[0]][$index[1]][0]{$index[2]} = chr($block);
  173. if($index[2] % 2 === 0){
  174. $this->column[$index[0]][$index[1]][1]{$index[2] >> 1} = chr((ord($this->column[$index[0]][$index[1]][1]{$index[2] >> 1}) & 0xF0) | ($meta & 0x0F));
  175. }else{
  176. $this->column[$index[0]][$index[1]][1]{$index[2] >> 1} = chr((ord($this->column[$index[0]][$index[1]][1]{$index[2] >> 1}) & 0x0F) | ($meta >> 4));
  177. }
  178. }
  179. }
  180. }