Large improvement in chunk sending

This commit is contained in:
Shoghi Cervantes 2013-06-09 20:37:45 +02:00
parent 31490576d2
commit 4a5783b57b
3 changed files with 60 additions and 29 deletions

View File

@ -77,6 +77,7 @@ class Player{
public $craftingItems = array();
public $toCraft = array();
public $lastCraft = 0;
private $chunkCount = array();
public function __get($name){
if(isset($this->{$name})){
@ -155,6 +156,15 @@ class Player{
return false;
}
foreach($this->chunkCount as $i => $count){
if(isset($this->recoveryQueue[$count])){
$this->server->schedule(1, array($this, "getNextChunk"));
return;
}else{
unset($this->chunkCount[$i]);
}
}
$c = key($this->chunksOrder);
$d = @$this->chunksOrder[$c];
if($c === null or $d > $this->server->api->getProperty("view-distance")){
@ -171,13 +181,26 @@ class Player{
$z = $Z << 4;
$y = $Y << 4;
$this->level->useChunk($X, $Z, $this);
$this->dataPacket(MC_CHUNK_DATA, array(
$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;
}
}
$this->chunkCount = $this->dataPacket(MC_CHUNK_DATA, array(
"x" => $X,
"z" => $Z,
"data" => $this->level->getOrderedChunk($X, $Z, $Yndex),
));
/*$this->chunkCount = $this->dataPacket(MC_CHUNK_DATA, array(
"x" => $X,
"z" => $Z,
"data" => $this->level->getOrderedMiniChunk($X, $Z, $Y),
));
));*/
$tiles = $this->server->query("SELECT ID FROM tiles WHERE spawnable = 1 AND level = '".$this->level->getName()."' AND x >= ".($x - 1)." AND x < ".($x + 17)." AND z >= ".($z - 1)." AND z < ".($z + 17)." AND y >= ".($y - 1)." AND y < ".($y + 17).";");
$tiles = $this->server->query("SELECT ID FROM tiles WHERE spawnable = 1 AND level = '".$this->level->getName()."' AND x >= ".($x - 1)." AND x < ".($x + 17)." AND z >= ".($z - 1)." AND z < ".($z + 17).";");
if($tiles !== false and $tiles !== true){
while(($tile = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){
$tile = $this->server->api->tile->getByID($tile["ID"]);
@ -187,13 +210,6 @@ class Player{
}
}
if($repeat === false){
$r = (int) ((PLAYER_CHUNKS_PER_SECOND - 20) / 20);
for($i = 0; $i < $r; ++$i){
$this->getNextChunk(true);
}
}
$this->server->schedule(1, array($this, "getNextChunk"));
}
@ -239,8 +255,8 @@ class Player{
}
$reason = $reason == "" ? "server stop":$reason;
$this->eventHandler(new Container("You have been kicked. Reason: ".$reason), "server.chat");
$this->directDataPacket(MC_DISCONNECT);
$this->sendBuffer();
$this->directDataPacket(MC_DISCONNECT);
$this->connected = false;
$this->level->freeAllChunks($this);
$this->buffer = null;
@ -791,7 +807,7 @@ class Player{
return false;
}
if($this->packetStats[1] > 2){
$this->packetLoss = $this->packetStats[1] / max(1, $this->packetStats[0]);
$this->packetLoss = $this->packetStats[1] / max(1, $this->packetStats[0] + $this->packetStats[1]);
}else{
$this->packetLoss = 0;
}
@ -802,10 +818,6 @@ class Player{
$this->lagStat = array_sum($this->lag) / max(1, count($this->lag));
$this->lag = array();
$this->sendBuffer();
if($this->packetLoss >= PLAYER_MAX_PACKET_LOSS){
$this->sendChat("Your connection suffers a high packet loss of ".round($this->packetLoss * 100, 2)."%");
$this->close("packet loss");
}
$this->lastMeasure = microtime(true);
}
@ -907,8 +919,8 @@ class Player{
$this->resendQueue[$count] =& $this->recoveryQueue[$count];
$this->lag[] = microtime(true) - $this->recoveryQueue[$count]["sendtime"];
unset($this->recoveryQueue[$count]);
$this->packetStats[1]++;
}
++$this->packetStats[1];
}
break;
@ -917,8 +929,9 @@ class Player{
if(isset($this->recoveryQueue[$count])){
$this->lag[] = microtime(true) - $this->recoveryQueue[$count]["sendtime"];
unset($this->recoveryQueue[$count]);
unset($this->resendQueue[$count]);
unset($this->resendQueue[$count]);
}
++$this->packetStats[0];
}
break;
@ -1699,17 +1712,18 @@ class Player{
$buffer = str_split(($id === false ? "":chr($id)).$buffer, $size);
$h = Utils::writeInt(count($buffer)).Utils::writeShort($this->bigCnt);
$this->bigCnt = ($this->bigCnt + 1) % 0x10000;
$cnts = array();
foreach($buffer as $i => $buf){
$data["raw"] = Utils::writeShort(strlen($buf) << 3).strrev(Utils::writeTriad($this->counter[3]++)).$h.Utils::writeInt($i).$buf;
$count = $this->counter[0]++;
$cnts[] = $count = $this->counter[0]++;
$this->recoveryQueue[$count] = $data;
$this->send(0x80, array(
$count,
0x50, //0b01010000
$data,
));
++$this->packetStats[0];
}
return $cnts;
}
public function directDataPacket($id, $data = array(), $pid = 0x00, $recover = true){
@ -1728,7 +1742,7 @@ class Player{
$pid,
$data,
));
++$this->packetStats[0];
return array($count);
}
public function dataPacket($id, $data = array()){
@ -1742,15 +1756,14 @@ class Player{
$len = strlen($raw);
$MTU = $this->MTU - 24;
if($len > $MTU){
$this->directBigRawPacket(false, $raw);
return;
return $this->directBigRawPacket(false, $raw);
}
if((strlen($this->buffer) + $len) >= $MTU){
$this->sendBuffer();
}
$this->buffer .= ($this->buffer === "" ? "":"\x40").Utils::writeShort($len << 3).strrev(Utils::writeTriad($this->counter[3]++)).$raw;
return array();
}
function __toString(){

View File

@ -37,10 +37,6 @@ define("VIEWER", 3);
//Players
define("PLAYER_CHUNKS_PER_SECOND", 60);
define("PLAYER_RECOVERY_BUFFER", 1024);
define("PLAYER_MAX_PACKET_LOSS", 0.20);
define("PLAYER_SURVIVAL_SLOTS", 36);
define("PLAYER_CREATIVE_SLOTS", 111);

View File

@ -375,7 +375,29 @@ class Level{
}
return $this->level->unloadChunk($X, $Z);
}
public function getOrderedChunk($X, $Z, $Yndex){
if(!isset($this->level)){
return false;
}
$raw = array();
for($Y = 0; $Y < 8; ++$Y){
if(($Yndex & (1 << $Y)) > 0){
$raw[$Y] = $this->level->getMiniChunk($X, $Z, $Y);
}
}
$ordered = "";
$flag = chr($Yndex);
for($j = 0; $j < 256; ++$j){
$ordered .= $flag;
foreach($raw as $mini){
$ordered .= substr($mini, $j << 5, 24); //16 + 8
}
}
return $ordered;
}
public function getOrderedMiniChunk($X, $Z, $Y){
if(!isset($this->level)){
return false;