diff --git a/src/API/ChatAPI.php b/src/API/ChatAPI.php index 262b926f8..6f2f9a443 100644 --- a/src/API/ChatAPI.php +++ b/src/API/ChatAPI.php @@ -39,6 +39,10 @@ class ChatAPI{ $this->send(false, $message); } + public function sendTo($owner, $text, $username){ + $this->send($owner, $text, array($username)); + } + public function send($owner, $text, $whitelist = false, $blacklist = false){ $message = ""; if($owner !== false){ diff --git a/src/API/LevelAPI.php b/src/API/LevelAPI.php index af8a8ac4c..9be55f236 100644 --- a/src/API/LevelAPI.php +++ b/src/API/LevelAPI.php @@ -111,9 +111,8 @@ class LevelAPI{ return true; } - public function getOrderedChunk($X, $Z, $columnsPerPacket = 2){ + public function getOrderedChunks($X, $Z, $columnsPerPacket = 2){ $columnsPerPacket = max(1, (int) $columnsPerPacket); - $c = $this->getChunk($X, $Z); $ordered = array(); $i = 0; $cnt = 0; @@ -137,4 +136,26 @@ class LevelAPI{ } return $ordered; } + + public function getMiniChunk($X, $Z, $Y, $MTU){ + $ordered = array(); + $i = 0; + $ordered[$i] = ""; + $cnt = 0; + for($z = 0; $z < 16; ++$z){ + for($x = 0; $x < 16; ++$x){ + if((strlen($ordered[$i]) + 16 + 8 + 1) > $MTU){ + ++$i; + $ordered[$i] = str_repeat("\x00", $cnt); + } + $ordered[$i] .= chr(1 << $Y); + $block = $this->map->getChunkColumn($X, $Z, $x, $z, 0); + $meta = $this->map->getChunkColumn($X, $Z, $x, $z, 1); + $ordered[$i] .= substr($block, $Y << 4, 16); + $ordered[$i] .= substr($meta, $Y << 3, 8); + ++$cnt; + } + } + return $ordered; + } } \ No newline at end of file diff --git a/src/classes/Player.php b/src/classes/Player.php index 94b06cb7d..e57461836 100644 --- a/src/classes/Player.php +++ b/src/classes/Player.php @@ -100,27 +100,39 @@ class Player{ array_shift($this->chunksOrder); $this->chunksLoaded[$c] = true; $id = explode(":", $c); - $x = $id[0] * 16; - $z = $id[1] * 16; + $X = $id[0]; + $Z = $id[1]; + $x = $X * 16; + $z = $Z * 16; /* - $max = max(1, floor(($this->MTU - 16 - 255) / 192)); - $chunk = $this->server->api->level->getOrderedChunk('.$id[0].', '.$id[1].', $max); - foreach($chunk as $d){ - $this->dataPacket(MC_CHUNK_DATA, array( - "x" => '.$id[0].', - "z" => '.$id[1].', - "data" => $d, - ), true); + $MTU = $this->MTU - 16; + $y = $this->entity->y / 16; + $order = array(); + + for($Y = 0; $Y < 8; ++$Y){ + $order[$Y] = abs($y - ($Y + 0.5)); } + asort($order); + foreach($order as $Y => $distance){ + $chunk = $this->server->api->level->getMiniChunk('.$X.', '.$Z.', $Y, $MTU); + foreach($chunk as $d){ + $this->dataPacket(MC_CHUNK_DATA, array( + "x" => '.$X.', + "z" => '.$Z.', + "data" => $d, + ), true); + } + } + $tiles = $this->server->query("SELECT * FROM tileentities WHERE spawnable = 1 AND x >= '.$x.' AND x < '.($x + 16).' AND z >= '.$z.' AND z < '.($z + 16).';"); if($tiles !== false and $tiles !== true){ while(($tile = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){ $this->server->api->tileentity->spawnTo($tile["ID"], "'.$this->username.'", true); } } - $this->actionQueue('$this->orderChunks();$this->getNextChunk();'); + $this->actionQueue(\'$this->orderChunks();$this->getNextChunk();\'); */ - $this->actionQueue('$max = max(1, floor(($this->MTU - 16 - 255) / 192));$chunk = $this->server->api->level->getOrderedChunk('.$id[0].', '.$id[1].', $max);foreach($chunk as $d){$this->dataPacket(MC_CHUNK_DATA, array("x" => '.$id[0].',"z" => '.$id[1].',"data" => $d,), true);}$tiles = $this->server->query("SELECT * FROM tileentities WHERE spawnable = 1 AND x >= '.$x.' AND x < '.($x + 16).' AND z >= '.$z.' AND z < '.($z + 16).';");if($tiles !== false and $tiles !== true){while(($tile = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){$this->server->api->tileentity->spawnTo($tile["ID"], "'.$this->username.'", true);}}$this->actionQueue(\'$this->orderChunks();$this->getNextChunk();\');'); + $this->actionQueue('$MTU = $this->MTU - 16;$y = $this->entity->y / 16;$order = array();for($Y = 0; $Y < 8; ++$Y){$order[$Y] = abs($y - ($Y + 0.5));}asort($order);foreach($order as $Y => $distance){$chunk = $this->server->api->level->getMiniChunk('.$X.', '.$Z.', $Y, $MTU);foreach($chunk as $d){$this->dataPacket(MC_CHUNK_DATA, array("x" => '.$X.',"z" => '.$Z.',"data" => $d,), true);}}$tiles = $this->server->query("SELECT * FROM tileentities WHERE spawnable = 1 AND x >= '.$x.' AND x < '.($x + 16).' AND z >= '.$z.' AND z < '.($z + 16).';");if($tiles !== false and $tiles !== true){while(($tile = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){$this->server->api->tileentity->spawnTo($tile["ID"], "'.$this->username.'", true);}}$this->actionQueue(\'$this->orderChunks();$this->getNextChunk();\');'); } @@ -616,28 +628,6 @@ class Player{ break; case MC_REQUEST_CHUNK: break; - $x = $data["x"] * 16; - $z = $data["z"] * 16; - /* - $max = max(1, floor(($this->MTU - 16 - 255) / 192)); - $chunk = $this->server->api->level->getOrderedChunk('.$data["x"].', '.$data["z"].', $max); - foreach($chunk as $d){ - $this->dataPacket(MC_CHUNK_DATA, array( - "x" => '.$data["x"].', - "z" => '.$data["z"].', - "data" => $d, - ), true); - } - $tiles = $this->server->query("SELECT * FROM tileentities WHERE spawnable = 1 AND x >= '.$x.' AND x < '.($x + 16).' AND z >= '.$z.' AND z < '.($z + 16).';"); - if($tiles !== false and $tiles !== true){ - while(($tile = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){ - $this->server->api->tileentity->spawnTo($tile["ID"], "'.$this->username.'", true); - } - } - */ - $this->actionQueue('$max = max(1, floor(($this->MTU - 16 - 255) / 192));$chunk = $this->server->api->level->getOrderedChunk('.$data["x"].', '.$data["z"].', $max);foreach($chunk as $d){$this->dataPacket(MC_CHUNK_DATA, array("x" => '.$data["x"].',"z" => '.$data["z"].',"data" => $d,), true);}$tiles = $this->server->query("SELECT * FROM tileentities WHERE spawnable = 1 AND x >= '.$x.' AND x < '.($x + 16).' AND z >= '.$z.' AND z < '.($z + 16).';");if($tiles !== false and $tiles !== true){while(($tile = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){$this->server->api->tileentity->spawnTo($tile["ID"], "'.$this->username.'", true);}}'); - console("[INTERNAL] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 3); - break; case MC_USE_ITEM: $data["eid"] = $this->eid; if(Utils::distance($this->entity->position, $data) > 10){