Buffered block changes and sending big changes with Chunk Packets

This commit is contained in:
Shoghi Cervantes Pueyo 2013-05-19 19:27:55 +02:00
parent 10ed95a469
commit 68855bdd4f
4 changed files with 68 additions and 23 deletions

View File

@ -324,6 +324,14 @@ class PlayerAPI{
} }
return $this->server->clients; 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){ public function getByEID($eid){
$eid = (int) $eid; $eid = (int) $eid;

View File

@ -58,7 +58,7 @@ class Player{
public $windowCnt = 0; public $windowCnt = 0;
public $windows = array(); public $windows = array();
public $blocked = true; public $blocked = true;
private $chunksLoaded = array(); public $chunksLoaded = array();
private $chunksOrder = array(); private $chunksOrder = array();
private $lag = array(0, 0); private $lag = array(0, 0);
private $spawnPosition; private $spawnPosition;
@ -410,18 +410,6 @@ class Player{
} }
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data); $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; break;
case "entity.move": case "entity.move":
if($data->eid === $this->eid or $data->level !== $this->level){ 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.equipment.change", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.armor", 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("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->evid[] = $this->server->event("tile.container.slot", array($this, "eventHandler"));
$this->server->schedule(40, array($this, "measureLag"), array(), true); $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).")"); 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" => "", "raw" => "",
); );
$size = $this->MTU - 31; $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); $h = Utils::writeInt(count($buffer)).Utils::writeShort($this->bigCnt);
$this->bigCnt = ($this->bigCnt + 1) % 0x10000; $this->bigCnt = ($this->bigCnt + 1) % 0x10000;
foreach($buffer as $i => $buf){ foreach($buffer as $i => $buf){
@ -1427,11 +1414,16 @@ class Player{
if($queue === true){ if($queue === true){
$this->queue[] = array(0, $data); $this->queue[] = array(0, $data);
}else{ }else{
$data = new CustomPacketHandler($id, "", $data, true); if($id === false){
$len = strlen($data->raw) + 1; $raw = $data["raw"];
}else{
$data = new CustomPacketHandler($id, "", $data, true);
$raw = chr($id).$data->raw;
}
$len = strlen($raw);
$MTU = $this->MTU - 21; $MTU = $this->MTU - 21;
if($len > $MTU){ if($len > $MTU){
$this->directBigRawPacket($id, $data->raw); $this->directBigRawPacket(false, $raw);
return; return;
} }
@ -1439,7 +1431,7 @@ class Player{
$this->sendBuffer(); $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;
} }
} }

View File

@ -52,6 +52,9 @@ class CustomPacketHandler{
$this->data = $data; $this->data = $data;
$this->offset = 0; $this->offset = 0;
$this->c = (bool) $create; $this->c = (bool) $create;
if($pid === false){
return;
}
switch($pid){ switch($pid){
case MC_PING: case MC_PING:
if($this->c === false){ if($this->c === false){

View File

@ -27,7 +27,7 @@ the Free Software Foundation, either version 3 of the License, or
class Level{ class Level{
public $entities, $tileEntities; 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){ public function __construct(PMFLevel $level, Config $entities, Config $tileEntities, $name){
$this->server = ServerAPI::request(); $this->server = ServerAPI::request();
@ -41,6 +41,8 @@ class Level{
$this->server->event("server.close", array($this, "save")); $this->server->event("server.close", array($this, "save"));
$this->name = $name; $this->name = $name;
$this->usedChunks = array(); $this->usedChunks = array();
$this->changedBlocks = array();
$this->changedCount = array();
} }
public function useChunk($X, $Z, Player $player){ public function useChunk($X, $Z, Player $player){
@ -67,6 +69,37 @@ class Level{
$this->time = $time; $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){ if($this->nextSave < $now and $this->server->saveEnabled === true){
foreach($this->usedChunks as $i => $c){ foreach($this->usedChunks as $i => $c){
if(count($c) === 0){ if(count($c) === 0){
@ -183,12 +216,21 @@ class Level{
if(!($pos instanceof Position)){ if(!($pos instanceof Position)){
$pos = new Position($pos->x, $pos->y, $pos->z, $this); $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, "position" => $pos,
"block" => $block, "block" => $block,
)); ));*/
if($update === true){ 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); $this->server->api->block->blockUpdateAround($pos, BLOCK_UPDATE_NORMAL);
} }
if($tiles === true){ if($tiles === true){