mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-17 11:18:52 +00:00
New chunk indexing and sending algorithm
This commit is contained in:
parent
8403a34eb3
commit
9d02ed9a28
@ -41,13 +41,12 @@ class PlayerAPI{
|
|||||||
$this->server->api->ban->cmdWhitelist("list");
|
$this->server->api->ban->cmdWhitelist("list");
|
||||||
$this->server->api->ban->cmdWhitelist("ping");
|
$this->server->api->ban->cmdWhitelist("ping");
|
||||||
$this->server->api->ban->cmdWhitelist("spawn");
|
$this->server->api->ban->cmdWhitelist("spawn");
|
||||||
$this->server->preparedSQL->selectPlayersToHeal = $this->server->database->prepare("SELECT EID FROM entities WHERE class = ".ENTITY_PLAYER." AND health < 20;");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle($data, $event){
|
public function handle($data, $event){
|
||||||
switch($event){
|
switch($event){
|
||||||
case "server.regeneration":
|
case "server.regeneration":
|
||||||
if($this->server->difficulty === 0){
|
/*if($this->server->difficulty === 0){
|
||||||
$result = $this->server->preparedSQL->selectPlayersToHeal->execute();
|
$result = $this->server->preparedSQL->selectPlayersToHeal->execute();
|
||||||
if($result !== false){
|
if($result !== false){
|
||||||
while(($player = $result->fetchArray()) !== false){
|
while(($player = $result->fetchArray()) !== false){
|
||||||
@ -60,7 +59,7 @@ class PlayerAPI{
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
break;
|
break;
|
||||||
case "player.death":
|
case "player.death":
|
||||||
if(is_numeric($data["cause"])){
|
if(is_numeric($data["cause"])){
|
||||||
@ -267,7 +266,7 @@ class PlayerAPI{
|
|||||||
if(!isset($params[0]) and ($issuer instanceof Player)){
|
if(!isset($params[0]) and ($issuer instanceof Player)){
|
||||||
$player = $issuer;
|
$player = $issuer;
|
||||||
}else{
|
}else{
|
||||||
$player = $this->get($params[0]);
|
$player = Player::get($params[0]);
|
||||||
}
|
}
|
||||||
if($player instanceof Player){
|
if($player instanceof Player){
|
||||||
$player->entity->harm(1000, "console", true);
|
$player->entity->harm(1000, "console", true);
|
||||||
@ -294,7 +293,7 @@ class PlayerAPI{
|
|||||||
if(substr($target, 0, 2) === "w:"){
|
if(substr($target, 0, 2) === "w:"){
|
||||||
$lv = $this->server->api->level->get(substr($target, 2));
|
$lv = $this->server->api->level->get(substr($target, 2));
|
||||||
if($lv instanceof Level){
|
if($lv instanceof Level){
|
||||||
$origin = $this->get($name);
|
$origin = Player::get($name);
|
||||||
if($origin instanceof Player){
|
if($origin instanceof Player){
|
||||||
$name = $origin->username;
|
$name = $origin->username;
|
||||||
return $origin->teleport($lv->getSafeSpawn());
|
return $origin->teleport($lv->getSafeSpawn());
|
||||||
@ -303,10 +302,10 @@ class PlayerAPI{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$player = $this->get($target);
|
$player = Player::get($target);
|
||||||
if(($player instanceof Player) and ($player->entity instanceof Entity)){
|
if(($player instanceof Player) and ($player->entity instanceof Entity)){
|
||||||
$target = $player->username;
|
$target = $player->username;
|
||||||
$origin = $this->get($name);
|
$origin = Player::get($name);
|
||||||
if($origin instanceof Player){
|
if($origin instanceof Player){
|
||||||
$name = $origin->username;
|
$name = $origin->username;
|
||||||
return $origin->teleport($player->entity);
|
return $origin->teleport($player->entity);
|
||||||
@ -316,7 +315,7 @@ class PlayerAPI{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function tppos(&$name, &$x, &$y, &$z){
|
public function tppos(&$name, &$x, &$y, &$z){
|
||||||
$player = $this->get($name);
|
$player = Player::get($name);
|
||||||
if(($player instanceof Player) and ($player->entity instanceof Entity)){
|
if(($player instanceof Player) and ($player->entity instanceof Entity)){
|
||||||
$name = $player->username;
|
$name = $player->username;
|
||||||
$x = $x{0} === "~" ? $player->entity->x + floatval(substr($x, 1)):floatval($x);
|
$x = $x{0} === "~" ? $player->entity->x + floatval(substr($x, 1)):floatval($x);
|
||||||
|
@ -25,8 +25,8 @@ abstract class Entity extends Position{
|
|||||||
public static $needUpdate = array();
|
public static $needUpdate = array();
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
//public $passenger = null;
|
public $passenger = null;
|
||||||
//public $vehicle = null;
|
public $vehicle = null;
|
||||||
|
|
||||||
public $chunkIndex;
|
public $chunkIndex;
|
||||||
|
|
||||||
@ -258,12 +258,14 @@ abstract class Entity extends Position{
|
|||||||
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
|
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
|
||||||
$this->despawnFromAll();
|
$this->despawnFromAll();
|
||||||
if($this instanceof Player){
|
if($this instanceof Player){
|
||||||
foreach($this->chunksLoaded as $index => $boolean){
|
foreach($this->chunksLoaded as $index => $Yndex){
|
||||||
$X = null;
|
if($Yndex !== 0xff){
|
||||||
$Z = null;
|
$X = null;
|
||||||
PMFLevel::getXZ($index, $X, $Z);
|
$Z = null;
|
||||||
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
PMFLevel::getXZ($index, $X, $Z);
|
||||||
$entity->despawnFrom($this);
|
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
||||||
|
$entity->despawnFrom($this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->level->freeAllChunks($this);
|
$this->level->freeAllChunks($this);
|
||||||
|
@ -137,8 +137,6 @@ class MainServer{
|
|||||||
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
|
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
|
||||||
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");
|
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");
|
||||||
$this->preparedSQL->updateAction = $this->database->prepare("UPDATE actions SET last = :time WHERE ID = :id;");
|
$this->preparedSQL->updateAction = $this->database->prepare("UPDATE actions SET last = :time WHERE ID = :id;");
|
||||||
$this->preparedSQL->entity->setPosition = $this->database->prepare("UPDATE entities SET x = :x, y = :y, z = :z, pitch = :pitch, yaw = :yaw WHERE EID = :eid ;");
|
|
||||||
$this->preparedSQL->entity->setLevel = $this->database->prepare("UPDATE entities SET level = :level WHERE EID = :eid ;");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function query($sql, $fetch = false){
|
public function query($sql, $fetch = false){
|
||||||
@ -154,10 +152,8 @@ class MainServer{
|
|||||||
$info["tps"] = $this->getTPS();
|
$info["tps"] = $this->getTPS();
|
||||||
$info["memory_usage"] = round((memory_get_usage() / 1024) / 1024, 2)."MB";
|
$info["memory_usage"] = round((memory_get_usage() / 1024) / 1024, 2)."MB";
|
||||||
$info["memory_peak_usage"] = round((memory_get_peak_usage() / 1024) / 1024, 2)."MB";
|
$info["memory_peak_usage"] = round((memory_get_peak_usage() / 1024) / 1024, 2)."MB";
|
||||||
$info["entities"] = $this->query("SELECT count(EID) as count FROM entities;", true);
|
$info["entities"] = count(Entity::$list);
|
||||||
$info["entities"] = $info["entities"]["count"];
|
$info["players"] = count(Player::$list);
|
||||||
$info["players"] = $this->query("SELECT count(CID) as count FROM players;", true);
|
|
||||||
$info["players"] = $info["players"]["count"];
|
|
||||||
$info["events"] = count($this->eventsID);
|
$info["events"] = count($this->eventsID);
|
||||||
$info["handlers"] = $this->query("SELECT count(ID) as count FROM handlers;", true);
|
$info["handlers"] = $this->query("SELECT count(ID) as count FROM handlers;", true);
|
||||||
$info["handlers"] = $info["handlers"]["count"];
|
$info["handlers"] = $info["handlers"]["count"];
|
||||||
|
@ -181,7 +181,7 @@ class Player extends PlayerEntity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
$newOrder = array();
|
$newOrder = array();
|
||||||
$lastLoaded = $this->chunksLoaded;
|
$lastChunk = $this->chunksLoaded;
|
||||||
$centerX = intval(($this->x - 0.5) / 16);
|
$centerX = intval(($this->x - 0.5) / 16);
|
||||||
$centerZ = intval(($this->z - 0.5) / 16);
|
$centerZ = intval(($this->z - 0.5) / 16);
|
||||||
$startX = $centerX - $this->viewDistance;
|
$startX = $centerX - $this->viewDistance;
|
||||||
@ -191,21 +191,26 @@ class Player extends PlayerEntity{
|
|||||||
for($X = $startX; $X <= $finalX; ++$X){
|
for($X = $startX; $X <= $finalX; ++$X){
|
||||||
for($Z = $startZ; $Z <= $finalZ; ++$Z){
|
for($Z = $startZ; $Z <= $finalZ; ++$Z){
|
||||||
$distance = abs($X - $centerX) + abs($Z - $centerZ);
|
$distance = abs($X - $centerX) + abs($Z - $centerZ);
|
||||||
for($Y = 0; $Y < 8; ++$Y){
|
$index = PMFLevel::getIndex($X, $Z);
|
||||||
$index = "$X:$Y:$Z";
|
if(!isset($this->chunksLoaded[$index]) or $this->chunksLoaded[$index] !== 0){
|
||||||
if(!isset($lastLoaded[$index])){
|
$newOrder[$index] = $distance;
|
||||||
$newOrder[$index] = $distance;
|
|
||||||
}else{
|
|
||||||
unset($lastLoaded[$index]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
unset($lastChunk[$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
asort($newOrder);
|
asort($newOrder);
|
||||||
$this->chunksOrder = $newOrder;
|
$this->chunksOrder = $newOrder;
|
||||||
foreach($lastLoaded as $index => $distance){
|
foreach($lastChunk as $index => $Yndex){
|
||||||
$id = explode(":", $index);
|
if($Yndex !== 0xff){
|
||||||
$this->level->freeChunk($id[0], $id[2], $this);
|
$X = null;
|
||||||
|
$Z = null;
|
||||||
|
PMFLevel::getXZ($index, $X, $Z);
|
||||||
|
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
||||||
|
if($entity !== $this){
|
||||||
|
$entity->despawnFrom($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
unset($this->chunksLoaded[$index]);
|
unset($this->chunksLoaded[$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,6 +240,11 @@ class Player extends PlayerEntity{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(is_array($this->lastChunk)){
|
if(is_array($this->lastChunk)){
|
||||||
|
foreach($this->level->getChunkEntities($this->lastChunk[0], $this->lastChunk[1]) as $entity){
|
||||||
|
if($entity !== $this){
|
||||||
|
$entity->spawnTo($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
foreach($this->level->getChunkTiles($this->lastChunk[0], $this->lastChunk[1]) as $tile){
|
foreach($this->level->getChunkTiles($this->lastChunk[0], $this->lastChunk[1]) as $tile){
|
||||||
if($tile instanceof SpawnableTile){
|
if($tile instanceof SpawnableTile){
|
||||||
$tile->spawnTo($this);
|
$tile->spawnTo($this);
|
||||||
@ -243,29 +253,24 @@ class Player extends PlayerEntity{
|
|||||||
$this->lastChunk = false;
|
$this->lastChunk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$c = key($this->chunksOrder);
|
$index = key($this->chunksOrder);
|
||||||
$d = @$this->chunksOrder[$c];
|
$distance = @$this->chunksOrder[$index];
|
||||||
if($c === null or $d === null){
|
if($index === null or $distance === null){
|
||||||
if($this->chunkScheduled === 0){
|
if($this->chunkScheduled === 0){
|
||||||
$this->server->schedule(40, array($this, "getNextChunk"));
|
$this->server->schedule(40, array($this, "getNextChunk"));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unset($this->chunksOrder[$c]);
|
unset($this->chunksOrder[$index]);
|
||||||
$this->chunksLoaded[$c] = true;
|
if(!isset($this->chunksLoaded[$index])){
|
||||||
$id = explode(":", $c);
|
$this->chunksLoaded[$index] = 0xff;
|
||||||
$X = $id[0];
|
|
||||||
$Z = $id[2];
|
|
||||||
$Y = $id[1];
|
|
||||||
$this->level->useChunk($X, $Z, $this);
|
|
||||||
$Yndex = 1 << $Y;
|
|
||||||
for($iY = 0; $iY < 8; ++$iY){
|
|
||||||
if(isset($this->chunksOrder["$X:$iY:$Z"])){
|
|
||||||
unset($this->chunksOrder["$X:$iY:$Z"]);
|
|
||||||
$this->chunksLoaded["$X:$iY:$Z"] = true;
|
|
||||||
$Yndex |= 1 << $iY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$X = null;
|
||||||
|
$Z = null;
|
||||||
|
PMFLevel::getXZ($index, $X, $Z);
|
||||||
|
$this->level->useChunk($X, $Z, $this);
|
||||||
|
$Yndex = $this->chunksLoaded[$index];
|
||||||
|
$this->chunksLoaded[$index] = 0; //Load them all
|
||||||
$pk = new ChunkDataPacket;
|
$pk = new ChunkDataPacket;
|
||||||
$pk->chunkX = $X;
|
$pk->chunkX = $X;
|
||||||
$pk->chunkZ = $Z;
|
$pk->chunkZ = $Z;
|
||||||
|
@ -34,8 +34,8 @@ class UDPSocket{
|
|||||||
}else{
|
}else{
|
||||||
if(socket_bind($this->sock, $serverip, $port) === true){
|
if(socket_bind($this->sock, $serverip, $port) === true){
|
||||||
socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 0);
|
socket_set_option($this->sock, SOL_SOCKET, SO_REUSEADDR, 0);
|
||||||
socket_set_option($this->sock, SOL_SOCKET, SO_SNDBUF, 1024 * 1024 * 2); //2MB
|
@socket_set_option($this->sock, SOL_SOCKET, SO_SNDBUF, 1024 * 1024 * 2); //2MB
|
||||||
socket_set_option($this->sock, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB
|
@socket_set_option($this->sock, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB
|
||||||
$this->unblock();
|
$this->unblock();
|
||||||
$this->connected = true;
|
$this->connected = true;
|
||||||
}else{
|
}else{
|
||||||
|
@ -109,28 +109,37 @@ class Level{
|
|||||||
$now = microtime(true);
|
$now = microtime(true);
|
||||||
|
|
||||||
if($this->level->isGenerating === 0 and count($this->changedCount) > 0){
|
if($this->level->isGenerating === 0 and count($this->changedCount) > 0){
|
||||||
arsort($this->changedCount);
|
foreach($this->changedCount as $index => $mini){
|
||||||
foreach($this->changedCount as $index => $count){
|
for($Y = 0; $Y < 8; ++$Y){
|
||||||
if($count < 582){//Optimal value, calculated using the relation between minichunks and single packets
|
if(($mini & (1 << $Y)) === 0){
|
||||||
break;
|
continue;
|
||||||
|
}
|
||||||
|
if(count($this->changedBlocks[$index][$Y]) < 582){//Optimal value, calculated using the relation between minichunks and single packets
|
||||||
|
continue;
|
||||||
|
}else{
|
||||||
|
foreach($this->players as $p){
|
||||||
|
if(isset($p->chunksLoaded[$index])){
|
||||||
|
$p->chunksLoaded[$index] |= $mini;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($this->changedBlocks[$index][$Y]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach($this->players as $p){
|
|
||||||
unset($p->chunksLoaded[$index]);
|
|
||||||
}
|
|
||||||
unset($this->changedBlocks[$index]);
|
|
||||||
}
|
}
|
||||||
$this->changedCount = array();
|
$this->changedCount = array();
|
||||||
|
|
||||||
if(count($this->changedBlocks) > 0){
|
if(count($this->changedBlocks) > 0){
|
||||||
foreach($this->changedBlocks as $blocks){
|
foreach($this->changedBlocks as $index => $mini){
|
||||||
foreach($blocks as $b){
|
foreach($mini as $blocks){
|
||||||
$pk = new UpdateBlockPacket;
|
foreach($blocks as $b){
|
||||||
$pk->x = $b->x;
|
$pk = new UpdateBlockPacket;
|
||||||
$pk->y = $b->y;
|
$pk->x = $b->x;
|
||||||
$pk->z = $b->z;
|
$pk->y = $b->y;
|
||||||
$pk->block = $b->getID();
|
$pk->z = $b->z;
|
||||||
$pk->meta = $b->getMetadata();
|
$pk->block = $b->getID();
|
||||||
$this->server->api->player->broadcastPacket($this->players, $pk);
|
$pk->meta = $b->getMetadata();
|
||||||
|
$this->server->api->player->broadcastPacket($this->players, $pk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->changedBlocks = array();
|
$this->changedBlocks = array();
|
||||||
@ -251,16 +260,20 @@ class Level{
|
|||||||
$pos = new Position($pos->x, $pos->y, $pos->z, $this);
|
$pos = new Position($pos->x, $pos->y, $pos->z, $this);
|
||||||
}
|
}
|
||||||
$block->position($pos);
|
$block->position($pos);
|
||||||
$i = ($pos->x >> 4).":".($pos->y >> 4).":".($pos->z >> 4);
|
$index = PMFLevel::getIndex($pos->x >> 4, $pos->z >> 4);
|
||||||
if(ADVANCED_CACHE == true){
|
if(ADVANCED_CACHE == true){
|
||||||
Cache::remove("world:{$this->name}:".($pos->x >> 4).":".($pos->z >> 4));
|
Cache::remove("world:{$this->name}:{$index}");
|
||||||
}
|
}
|
||||||
if(!isset($this->changedBlocks[$i])){
|
if(!isset($this->changedBlocks[$index])){
|
||||||
$this->changedBlocks[$i] = array();
|
$this->changedBlocks[$index] = array();
|
||||||
$this->changedCount[$i] = 0;
|
$this->changedCount[$index] = 0;
|
||||||
}
|
}
|
||||||
$this->changedBlocks[$i][] = clone $block;
|
$Y = $pos->y >> 4;
|
||||||
++$this->changedCount[$i];
|
if(!isset($this->changedBlocks[$index][$Y])){
|
||||||
|
$this->changedBlocks[$index][$Y] = array();
|
||||||
|
$this->changedCount[$index] |= 1 << $Y;
|
||||||
|
}
|
||||||
|
$this->changedBlocks[$index][$Y][] = clone $block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
@ -287,16 +300,20 @@ class Level{
|
|||||||
$pk->meta = $block->getMetadata();
|
$pk->meta = $block->getMetadata();
|
||||||
$this->server->api->player->broadcastPacket($this->players, $pk);
|
$this->server->api->player->broadcastPacket($this->players, $pk);
|
||||||
}else{
|
}else{
|
||||||
$i = ($pos->x >> 4).":".($pos->y >> 4).":".($pos->z >> 4);
|
$index = PMFLevel::getIndex($pos->x >> 4, $pos->z >> 4);
|
||||||
if(!isset($this->changedBlocks[$i])){
|
|
||||||
$this->changedBlocks[$i] = array();
|
|
||||||
$this->changedCount[$i] = 0;
|
|
||||||
}
|
|
||||||
if(ADVANCED_CACHE == true){
|
if(ADVANCED_CACHE == true){
|
||||||
Cache::remove("world:{$this->name}:".($pos->x >> 4).":".($pos->z >> 4));
|
Cache::remove("world:{$this->name}:{$index}");
|
||||||
}
|
}
|
||||||
$this->changedBlocks[$i][] = clone $block;
|
if(!isset($this->changedBlocks[$index])){
|
||||||
++$this->changedCount[$i];
|
$this->changedBlocks[$index] = array();
|
||||||
|
$this->changedCount[$index] = 0;
|
||||||
|
}
|
||||||
|
$Y = $pos->y >> 4;
|
||||||
|
if(!isset($this->changedBlocks[$index][$Y])){
|
||||||
|
$this->changedBlocks[$index][$Y] = array();
|
||||||
|
$this->changedCount[$index] |= 1 << $Y;
|
||||||
|
}
|
||||||
|
$this->changedBlocks[$index][$Y][] = clone $block;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($update === true){
|
if($update === true){
|
||||||
@ -440,8 +457,8 @@ class Level{
|
|||||||
if(!isset($this->level)){
|
if(!isset($this->level)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(ADVANCED_CACHE == true and $Yndex == 0xff){
|
if(ADVANCED_CACHE == true and $Yndex === 0xff){
|
||||||
$identifier = "world:{$this->name}:$X:$Z";
|
$identifier = "world:{$this->name}:".PMFLevel::getIndex($X, $Z);
|
||||||
if(($cache = Cache::get($identifier)) !== false){
|
if(($cache = Cache::get($identifier)) !== false){
|
||||||
return $cache;
|
return $cache;
|
||||||
}
|
}
|
||||||
@ -450,7 +467,7 @@ class Level{
|
|||||||
|
|
||||||
$raw = array();
|
$raw = array();
|
||||||
for($Y = 0; $Y < 8; ++$Y){
|
for($Y = 0; $Y < 8; ++$Y){
|
||||||
if(($Yndex & (1 << $Y)) > 0){
|
if(($Yndex & (1 << $Y)) !== 0){
|
||||||
$raw[$Y] = $this->level->getMiniChunk($X, $Z, $Y);
|
$raw[$Y] = $this->level->getMiniChunk($X, $Z, $Y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user