mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-11 14:05:35 +00:00
Buffered block changes and sending big changes with Chunk Packets
This commit is contained in:
parent
10ed95a469
commit
68855bdd4f
@ -324,6 +324,14 @@ class PlayerAPI{
|
||||
}
|
||||
return $this->server->clients;
|
||||
}
|
||||
|
||||
public function broadcastPacket(array $players, $id, $data = array()){
|
||||
$data = new CustomPacketHandler($id, "", $data, true);
|
||||
$packet = array("raw" => chr($id).$data->raw);
|
||||
foreach($players as $p){
|
||||
$p->dataPacket(false, $packet);
|
||||
}
|
||||
}
|
||||
|
||||
public function getByEID($eid){
|
||||
$eid = (int) $eid;
|
||||
|
@ -58,7 +58,7 @@ class Player{
|
||||
public $windowCnt = 0;
|
||||
public $windows = array();
|
||||
public $blocked = true;
|
||||
private $chunksLoaded = array();
|
||||
public $chunksLoaded = array();
|
||||
private $chunksOrder = array();
|
||||
private $lag = array(0, 0);
|
||||
private $spawnPosition;
|
||||
@ -410,18 +410,6 @@ class Player{
|
||||
}
|
||||
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data);
|
||||
|
||||
break;
|
||||
case "block.change":
|
||||
if($data["position"]->level !== $this->level){
|
||||
break;
|
||||
}
|
||||
$this->dataPacket(MC_UPDATE_BLOCK, array(
|
||||
"x" => $data["position"]->x,
|
||||
"y" => $data["position"]->y,
|
||||
"z" => $data["position"]->z,
|
||||
"block" => $data["block"]->getID(),
|
||||
"meta" => $data["block"]->getMetadata(),
|
||||
));
|
||||
break;
|
||||
case "entity.move":
|
||||
if($data->eid === $this->eid or $data->level !== $this->level){
|
||||
@ -938,7 +926,6 @@ class Player{
|
||||
$this->evid[] = $this->server->event("player.equipment.change", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.armor", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("player.pickup", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("block.change", array($this, "eventHandler"));
|
||||
$this->evid[] = $this->server->event("tile.container.slot", array($this, "eventHandler"));
|
||||
$this->server->schedule(40, array($this, "measureLag"), array(), true);
|
||||
console("[INFO] \x1b[33m".$this->username."\x1b[0m[/".$this->ip.":".$this->port."] logged in with entity id ".$this->eid." at (".$this->entity->level->getName().", ".round($this->entity->x, 2).", ".round($this->entity->y, 2).", ".round($this->entity->z, 2).")");
|
||||
@ -1376,7 +1363,7 @@ class Player{
|
||||
"raw" => "",
|
||||
);
|
||||
$size = $this->MTU - 31;
|
||||
$buffer = str_split(chr($id).$buffer, $size);
|
||||
$buffer = str_split(($id === false ? "":chr($id)).$buffer, $size);
|
||||
$h = Utils::writeInt(count($buffer)).Utils::writeShort($this->bigCnt);
|
||||
$this->bigCnt = ($this->bigCnt + 1) % 0x10000;
|
||||
foreach($buffer as $i => $buf){
|
||||
@ -1427,11 +1414,16 @@ class Player{
|
||||
if($queue === true){
|
||||
$this->queue[] = array(0, $data);
|
||||
}else{
|
||||
$data = new CustomPacketHandler($id, "", $data, true);
|
||||
$len = strlen($data->raw) + 1;
|
||||
if($id === false){
|
||||
$raw = $data["raw"];
|
||||
}else{
|
||||
$data = new CustomPacketHandler($id, "", $data, true);
|
||||
$raw = chr($id).$data->raw;
|
||||
}
|
||||
$len = strlen($raw);
|
||||
$MTU = $this->MTU - 21;
|
||||
if($len > $MTU){
|
||||
$this->directBigRawPacket($id, $data->raw);
|
||||
$this->directBigRawPacket(false, $raw);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1439,7 +1431,7 @@ class Player{
|
||||
$this->sendBuffer();
|
||||
}
|
||||
|
||||
$this->buffer .= ($this->buffer === "" ? "":"\x00").Utils::writeShort($len << 3) . chr($id) . $data->raw;
|
||||
$this->buffer .= ($this->buffer === "" ? "":"\x00").Utils::writeShort($len << 3).$raw;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,9 @@ class CustomPacketHandler{
|
||||
$this->data = $data;
|
||||
$this->offset = 0;
|
||||
$this->c = (bool) $create;
|
||||
if($pid === false){
|
||||
return;
|
||||
}
|
||||
switch($pid){
|
||||
case MC_PING:
|
||||
if($this->c === false){
|
||||
|
@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or
|
||||
|
||||
class Level{
|
||||
public $entities, $tileEntities;
|
||||
private $level, $time, $startCheck, $startTime, $server, $name, $usedChunks, $nextSave;
|
||||
private $level, $time, $startCheck, $startTime, $server, $name, $usedChunks, $nextSave, $changedBlocks, $changedCount;
|
||||
|
||||
public function __construct(PMFLevel $level, Config $entities, Config $tileEntities, $name){
|
||||
$this->server = ServerAPI::request();
|
||||
@ -41,6 +41,8 @@ class Level{
|
||||
$this->server->event("server.close", array($this, "save"));
|
||||
$this->name = $name;
|
||||
$this->usedChunks = array();
|
||||
$this->changedBlocks = array();
|
||||
$this->changedCount = array();
|
||||
}
|
||||
|
||||
public function useChunk($X, $Z, Player $player){
|
||||
@ -67,6 +69,37 @@ class Level{
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
if(count($this->changedCount) > 0){
|
||||
$players = $this->server->api->player->getAll($this);
|
||||
arsort($this->changedCount);
|
||||
$resendChunks = array();
|
||||
foreach($this->changedCount as $index => $count){
|
||||
if($count < 582){//Optimal value, calculated using the relation between minichunks and single packets
|
||||
break;
|
||||
}
|
||||
foreach($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){
|
||||
$this->server->api->player->broadcastPacket($players, MC_UPDATE_BLOCK, array(
|
||||
"x" => $b->x,
|
||||
"y" => $b->y,
|
||||
"z" => $b->z,
|
||||
"block" => $b->getID(),
|
||||
"meta" => $b->getMetadata(),
|
||||
));
|
||||
}
|
||||
}
|
||||
$this->changedBlocks = array();
|
||||
}
|
||||
}
|
||||
|
||||
if($this->nextSave < $now and $this->server->saveEnabled === true){
|
||||
foreach($this->usedChunks as $i => $c){
|
||||
if(count($c) === 0){
|
||||
@ -183,12 +216,21 @@ class Level{
|
||||
if(!($pos instanceof Position)){
|
||||
$pos = new Position($pos->x, $pos->y, $pos->z, $this);
|
||||
}
|
||||
$this->server->trigger("block.change", array(
|
||||
$block = $this->getBlock($pos);
|
||||
|
||||
$i = ($pos->x >> 4).":".($pos->y >> 4).":".($pos->z >> 4);
|
||||
if(!isset($this->changedBlocks[$i])){
|
||||
$this->changedBlocks[$i] = array();
|
||||
$this->changedCount[$i] = 0;
|
||||
}
|
||||
$this->changedBlocks[$i][] = $block;
|
||||
++$this->changedCount[$i];
|
||||
/*$this->server->trigger("block.change", array(
|
||||
"position" => $pos,
|
||||
"block" => $block,
|
||||
));
|
||||
));*/
|
||||
if($update === true){
|
||||
$this->server->api->block->blockUpdate($this->getBlock($pos), BLOCK_UPDATE_NORMAL); //????? water?
|
||||
$this->server->api->block->blockUpdate($block, BLOCK_UPDATE_NORMAL); //????? water?
|
||||
$this->server->api->block->blockUpdateAround($pos, BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
if($tiles === true){
|
||||
|
Loading…
x
Reference in New Issue
Block a user