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;
}
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;

View File

@ -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;
}
}

View File

@ -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){

View File

@ -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){