Chunk unloading

This commit is contained in:
Shoghi Cervantes Pueyo 2013-05-15 22:43:12 +02:00
parent 3f532d419c
commit 244fde8143
4 changed files with 51 additions and 8 deletions

View File

@ -716,7 +716,6 @@ class BlockAPI{
public function blockUpdateAround(Position $pos, $type = BLOCK_UPDATE_NORMAL){
if(!($pos instanceof Block)){
$pos = $pos->floor();
$block = $pos->level->getBlock($pos);
}else{
$block = $pos;
@ -731,7 +730,6 @@ class BlockAPI{
public function blockUpdate(Position $pos, $type = BLOCK_UPDATE_NORMAL){
if(!($pos instanceof Block)){
$pos = $pos->floor();
$block = $pos->level->getBlock($pos);
}else{
$block = $pos;
@ -748,7 +746,7 @@ class BlockAPI{
if($delay < 0){
return false;
}
$pos = $pos->floor();
$index = $pos->x.".".$pos->y.".".$pos->z.".".$pos->level->getName();
$delay = microtime(true) + $delay * 0.05;
if(!isset($this->scheduledUpdates[$index])){

View File

@ -62,6 +62,7 @@ class Player{
private $chunksOrder = array();
private $lag = array(0, 0);
private $spawnPosition;
private $freedChunks = true;
public $itemEnforcement;
public $lastCorrect;
@ -118,7 +119,7 @@ class Player{
for($z = 0; $z < 16; ++$z){
for($y = 0; $y < 8; ++$y){
$d = $x.":".$y.":".$z;
if(!isset($this->chunksLoaded[$d])){
if(!isset($this->chunksLoaded[$d])){
$this->chunksOrder[$d] = $v->distance(new Vector3($x + 0.5, $y / 4, $z + 0.5));
}
}
@ -134,9 +135,19 @@ class Player{
$c = key($this->chunksOrder);
$d = $this->chunksOrder[$c];
if($c === null or $d > $this->server->api->getProperty("view-distance")){
if($this->freedChunks === false){
foreach($this->chunksOrder as $c => $d){
$id = explode(":", $c);
$X = $id[0];
$Z = $id[2];
$this->level->freeChunk($X, $Z, $this);
}
$this->freedChunks = true;
}
$this->server->schedule(50, array($this, "getNextChunk"));
return false;
}
$this->freedChunks = false;
array_shift($this->chunksOrder);
$this->chunksLoaded[$c] = true;
$id = explode(":", $c);
@ -147,6 +158,7 @@ class Player{
$z = $Z << 4;
$y = $Y << 4;
$MTU = $this->MTU - 16;
$this->level->useChunk($X, $Z, $this);
$chunk = $this->level->getOrderedMiniChunk($X, $Z, $Y, $MTU);
foreach($chunk as $d){
$this->dataPacket(MC_CHUNK_DATA, array(
@ -233,6 +245,7 @@ class Player{
$this->eventHandler(new Container("You have been kicked. Reason: ".$reason), "server.chat");
$this->directDataPacket(MC_DISCONNECT);
$this->sendBuffer();
$this->level->freeAllChunks($this);
$this->buffer = null;
unset($this->buffer);
$this->recovery = null;
@ -589,7 +602,7 @@ class Player{
$this->entity->setPosition($pos, $yaw, $pitch);
$this->entity->resetSpeed();
$this->entity->updateLast();
$this->entity->calculateVelocity();
$this->entity->calculateVelocity();
if($pos instanceof Position and $pos->level !== $this->level){
foreach($this->server->api->entity->getAll($this->level) as $e){
if($e !== $this->entity){
@ -603,6 +616,7 @@ class Player{
));
}
}
$this->level->freeAllChunks($this);
$this->level = $pos->level;
$this->chunksLoaded = array();
$this->server->api->entity->spawnToAll($this->level, $this->eid);

View File

@ -39,6 +39,24 @@ class Level{
$this->server->schedule(15, array($this, "checkThings"), array(), true);
$this->server->event("server.close", array($this, "save"));
$this->name = $name;
$this->usedChunks = array();
}
public function useChunk($X, $Z, Player $player){
if(!isset($this->usedChunks[$X.".".$Z])){
$this->usedChunks[$X.".".$Z] = array();
}
$this->usedChunks[$X.".".$Z][$player->CID] = true;
$this->level->loadChunk($X, $Z);
}
public function freeAllChunks(Player $player){
foreach($this->usedChunks as $i => $c){
unset($this->usedChunks[$i][$player->CID]);
}
}
public function freeChunk($X, $Z, Player $player){
unset($this->usedChunks[$X.".".$Z][$player->CID]);
}
public function checkThings(){
@ -47,6 +65,15 @@ class Level{
if($this->server->api->dhandle("time.change", array("level" => $this, "time" => $time)) !== false){
$this->time = $time;
}
foreach($this->usedChunks as $i => $c){
if(count($c) === 0){
unset($this->usedChunks[$i]);
$X = explode(".", $i);
$Z = array_pop($X);
$this->level->unloadChunk((int) $X, (int) $Z);
}
}
}
public function __destruct(){
@ -68,10 +95,14 @@ class Level{
return BlockAPI::get($b[0], $b[1], new Position($pos->x, $pos->y, $pos->z, $this));
}
public function setBlock(Position $pos, Block $block, $update = true, $tiles = false){
public function setBlock(Vector3 $pos, Block $block, $update = true, $tiles = false){
if((($pos instanceof Position) and $pos->level !== $this) or $pos->x < 0 or $pos->y < 0 or $pos->z < 0){
return false;
}elseif($this->server->api->dhandle("block.change", array(
}elseif(!($pos instanceof Position)){
$pos = new Position($pos->x, $pos->y, $pos->z, $this);
}
if($this->server->api->dhandle("block.change", array(
"position" => $pos,
"block" => $block,
)) !== false){

View File

@ -66,7 +66,7 @@ class SmallTreeObject extends TreeObject{
for($xx = -$xzRadius; $xx < ($xzRadius + 1); ++$xx){
for($zz = -$xzRadius; $zz < ($xzRadius + 1); ++$zz){
if((abs($xx) != $xzRadius or abs($zz) != $xzRadius) and $yRadius != 0){
$level->setBlock(new Vector3($x + $xx, $y + $yy, $z + $zz), new LeavesBlck($this->type));
$level->setBlock(new Vector3($x + $xx, $y + $yy, $z + $zz), new LeavesBlock($this->type));
}
}
}