mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-16 18:59:00 +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("ping");
|
||||
$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){
|
||||
switch($event){
|
||||
case "server.regeneration":
|
||||
if($this->server->difficulty === 0){
|
||||
/*if($this->server->difficulty === 0){
|
||||
$result = $this->server->preparedSQL->selectPlayersToHeal->execute();
|
||||
if($result !== false){
|
||||
while(($player = $result->fetchArray()) !== false){
|
||||
@ -60,7 +59,7 @@ class PlayerAPI{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
case "player.death":
|
||||
if(is_numeric($data["cause"])){
|
||||
@ -267,7 +266,7 @@ class PlayerAPI{
|
||||
if(!isset($params[0]) and ($issuer instanceof Player)){
|
||||
$player = $issuer;
|
||||
}else{
|
||||
$player = $this->get($params[0]);
|
||||
$player = Player::get($params[0]);
|
||||
}
|
||||
if($player instanceof Player){
|
||||
$player->entity->harm(1000, "console", true);
|
||||
@ -294,7 +293,7 @@ class PlayerAPI{
|
||||
if(substr($target, 0, 2) === "w:"){
|
||||
$lv = $this->server->api->level->get(substr($target, 2));
|
||||
if($lv instanceof Level){
|
||||
$origin = $this->get($name);
|
||||
$origin = Player::get($name);
|
||||
if($origin instanceof Player){
|
||||
$name = $origin->username;
|
||||
return $origin->teleport($lv->getSafeSpawn());
|
||||
@ -303,10 +302,10 @@ class PlayerAPI{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$player = $this->get($target);
|
||||
$player = Player::get($target);
|
||||
if(($player instanceof Player) and ($player->entity instanceof Entity)){
|
||||
$target = $player->username;
|
||||
$origin = $this->get($name);
|
||||
$origin = Player::get($name);
|
||||
if($origin instanceof Player){
|
||||
$name = $origin->username;
|
||||
return $origin->teleport($player->entity);
|
||||
@ -316,7 +315,7 @@ class PlayerAPI{
|
||||
}
|
||||
|
||||
public function tppos(&$name, &$x, &$y, &$z){
|
||||
$player = $this->get($name);
|
||||
$player = Player::get($name);
|
||||
if(($player instanceof Player) and ($player->entity instanceof Entity)){
|
||||
$name = $player->username;
|
||||
$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();
|
||||
private $id;
|
||||
|
||||
//public $passenger = null;
|
||||
//public $vehicle = null;
|
||||
public $passenger = null;
|
||||
public $vehicle = null;
|
||||
|
||||
public $chunkIndex;
|
||||
|
||||
@ -258,12 +258,14 @@ abstract class Entity extends Position{
|
||||
unset($this->level->chunkEntities[$this->chunkIndex][$this->id]);
|
||||
$this->despawnFromAll();
|
||||
if($this instanceof Player){
|
||||
foreach($this->chunksLoaded as $index => $boolean){
|
||||
$X = null;
|
||||
$Z = null;
|
||||
PMFLevel::getXZ($index, $X, $Z);
|
||||
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
||||
$entity->despawnFrom($this);
|
||||
foreach($this->chunksLoaded as $index => $Yndex){
|
||||
if($Yndex !== 0xff){
|
||||
$X = null;
|
||||
$Z = null;
|
||||
PMFLevel::getXZ($index, $X, $Z);
|
||||
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
||||
$entity->despawnFrom($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->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->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){
|
||||
@ -154,10 +152,8 @@ class MainServer{
|
||||
$info["tps"] = $this->getTPS();
|
||||
$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["entities"] = $this->query("SELECT count(EID) as count FROM entities;", true);
|
||||
$info["entities"] = $info["entities"]["count"];
|
||||
$info["players"] = $this->query("SELECT count(CID) as count FROM players;", true);
|
||||
$info["players"] = $info["players"]["count"];
|
||||
$info["entities"] = count(Entity::$list);
|
||||
$info["players"] = count(Player::$list);
|
||||
$info["events"] = count($this->eventsID);
|
||||
$info["handlers"] = $this->query("SELECT count(ID) as count FROM handlers;", true);
|
||||
$info["handlers"] = $info["handlers"]["count"];
|
||||
|
@ -181,7 +181,7 @@ class Player extends PlayerEntity{
|
||||
}
|
||||
|
||||
$newOrder = array();
|
||||
$lastLoaded = $this->chunksLoaded;
|
||||
$lastChunk = $this->chunksLoaded;
|
||||
$centerX = intval(($this->x - 0.5) / 16);
|
||||
$centerZ = intval(($this->z - 0.5) / 16);
|
||||
$startX = $centerX - $this->viewDistance;
|
||||
@ -191,21 +191,26 @@ class Player extends PlayerEntity{
|
||||
for($X = $startX; $X <= $finalX; ++$X){
|
||||
for($Z = $startZ; $Z <= $finalZ; ++$Z){
|
||||
$distance = abs($X - $centerX) + abs($Z - $centerZ);
|
||||
for($Y = 0; $Y < 8; ++$Y){
|
||||
$index = "$X:$Y:$Z";
|
||||
if(!isset($lastLoaded[$index])){
|
||||
$newOrder[$index] = $distance;
|
||||
}else{
|
||||
unset($lastLoaded[$index]);
|
||||
}
|
||||
$index = PMFLevel::getIndex($X, $Z);
|
||||
if(!isset($this->chunksLoaded[$index]) or $this->chunksLoaded[$index] !== 0){
|
||||
$newOrder[$index] = $distance;
|
||||
}
|
||||
unset($lastChunk[$index]);
|
||||
}
|
||||
}
|
||||
asort($newOrder);
|
||||
$this->chunksOrder = $newOrder;
|
||||
foreach($lastLoaded as $index => $distance){
|
||||
$id = explode(":", $index);
|
||||
$this->level->freeChunk($id[0], $id[2], $this);
|
||||
foreach($lastChunk as $index => $Yndex){
|
||||
if($Yndex !== 0xff){
|
||||
$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]);
|
||||
}
|
||||
}
|
||||
@ -235,6 +240,11 @@ class Player extends PlayerEntity{
|
||||
}
|
||||
|
||||
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){
|
||||
if($tile instanceof SpawnableTile){
|
||||
$tile->spawnTo($this);
|
||||
@ -243,29 +253,24 @@ class Player extends PlayerEntity{
|
||||
$this->lastChunk = false;
|
||||
}
|
||||
|
||||
$c = key($this->chunksOrder);
|
||||
$d = @$this->chunksOrder[$c];
|
||||
if($c === null or $d === null){
|
||||
$index = key($this->chunksOrder);
|
||||
$distance = @$this->chunksOrder[$index];
|
||||
if($index === null or $distance === null){
|
||||
if($this->chunkScheduled === 0){
|
||||
$this->server->schedule(40, array($this, "getNextChunk"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
unset($this->chunksOrder[$c]);
|
||||
$this->chunksLoaded[$c] = true;
|
||||
$id = explode(":", $c);
|
||||
$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;
|
||||
}
|
||||
unset($this->chunksOrder[$index]);
|
||||
if(!isset($this->chunksLoaded[$index])){
|
||||
$this->chunksLoaded[$index] = 0xff;
|
||||
}
|
||||
$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->chunkX = $X;
|
||||
$pk->chunkZ = $Z;
|
||||
|
@ -34,8 +34,8 @@ class UDPSocket{
|
||||
}else{
|
||||
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_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_SNDBUF, 1024 * 1024 * 2); //2MB
|
||||
@socket_set_option($this->sock, SOL_SOCKET, SO_RCVBUF, 1024 * 1024); //1MB
|
||||
$this->unblock();
|
||||
$this->connected = true;
|
||||
}else{
|
||||
|
@ -109,28 +109,37 @@ class Level{
|
||||
$now = microtime(true);
|
||||
|
||||
if($this->level->isGenerating === 0 and count($this->changedCount) > 0){
|
||||
arsort($this->changedCount);
|
||||
foreach($this->changedCount as $index => $count){
|
||||
if($count < 582){//Optimal value, calculated using the relation between minichunks and single packets
|
||||
break;
|
||||
foreach($this->changedCount as $index => $mini){
|
||||
for($Y = 0; $Y < 8; ++$Y){
|
||||
if(($mini & (1 << $Y)) === 0){
|
||||
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();
|
||||
|
||||
if(count($this->changedBlocks) > 0){
|
||||
foreach($this->changedBlocks as $blocks){
|
||||
foreach($blocks as $b){
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk->x = $b->x;
|
||||
$pk->y = $b->y;
|
||||
$pk->z = $b->z;
|
||||
$pk->block = $b->getID();
|
||||
$pk->meta = $b->getMetadata();
|
||||
$this->server->api->player->broadcastPacket($this->players, $pk);
|
||||
foreach($this->changedBlocks as $index => $mini){
|
||||
foreach($mini as $blocks){
|
||||
foreach($blocks as $b){
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk->x = $b->x;
|
||||
$pk->y = $b->y;
|
||||
$pk->z = $b->z;
|
||||
$pk->block = $b->getID();
|
||||
$pk->meta = $b->getMetadata();
|
||||
$this->server->api->player->broadcastPacket($this->players, $pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->changedBlocks = array();
|
||||
@ -251,16 +260,20 @@ class Level{
|
||||
$pos = new Position($pos->x, $pos->y, $pos->z, $this);
|
||||
}
|
||||
$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){
|
||||
Cache::remove("world:{$this->name}:".($pos->x >> 4).":".($pos->z >> 4));
|
||||
Cache::remove("world:{$this->name}:{$index}");
|
||||
}
|
||||
if(!isset($this->changedBlocks[$i])){
|
||||
$this->changedBlocks[$i] = array();
|
||||
$this->changedCount[$i] = 0;
|
||||
if(!isset($this->changedBlocks[$index])){
|
||||
$this->changedBlocks[$index] = array();
|
||||
$this->changedCount[$index] = 0;
|
||||
}
|
||||
$this->changedBlocks[$i][] = clone $block;
|
||||
++$this->changedCount[$i];
|
||||
$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;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
@ -287,16 +300,20 @@ class Level{
|
||||
$pk->meta = $block->getMetadata();
|
||||
$this->server->api->player->broadcastPacket($this->players, $pk);
|
||||
}else{
|
||||
$i = ($pos->x >> 4).":".($pos->y >> 4).":".($pos->z >> 4);
|
||||
if(!isset($this->changedBlocks[$i])){
|
||||
$this->changedBlocks[$i] = array();
|
||||
$this->changedCount[$i] = 0;
|
||||
}
|
||||
$index = PMFLevel::getIndex($pos->x >> 4, $pos->z >> 4);
|
||||
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;
|
||||
++$this->changedCount[$i];
|
||||
if(!isset($this->changedBlocks[$index])){
|
||||
$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){
|
||||
@ -440,8 +457,8 @@ class Level{
|
||||
if(!isset($this->level)){
|
||||
return false;
|
||||
}
|
||||
if(ADVANCED_CACHE == true and $Yndex == 0xff){
|
||||
$identifier = "world:{$this->name}:$X:$Z";
|
||||
if(ADVANCED_CACHE == true and $Yndex === 0xff){
|
||||
$identifier = "world:{$this->name}:".PMFLevel::getIndex($X, $Z);
|
||||
if(($cache = Cache::get($identifier)) !== false){
|
||||
return $cache;
|
||||
}
|
||||
@ -450,7 +467,7 @@ class Level{
|
||||
|
||||
$raw = array();
|
||||
for($Y = 0; $Y < 8; ++$Y){
|
||||
if(($Yndex & (1 << $Y)) > 0){
|
||||
if(($Yndex & (1 << $Y)) !== 0){
|
||||
$raw[$Y] = $this->level->getMiniChunk($X, $Z, $Y);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user