Fix entity unloading after teleporting, closes #3136

This commit is contained in:
Shoghi Cervantes 2015-06-08 15:02:00 +02:00
parent 4fd5e9ba7d
commit fdcddcc04b
3 changed files with 22 additions and 17 deletions

View File

@ -594,6 +594,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
Level::getXZ($index, $X, $Z); Level::getXZ($index, $X, $Z);
$this->unloadChunk($X, $Z, $oldLevel); $this->unloadChunk($X, $Z, $oldLevel);
} }
$this->usedChunks = [];
$pk = new SetTimePacket();
$pk->time = $this->level->getTime();
$pk->started = $this->level->stopTime == false;
$this->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_EVENTS));
} }
} }
@ -1717,6 +1723,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($this->server->getAutoSave()){ if($this->server->getAutoSave()){
$this->server->saveOfflinePlayerData($this->username, $nbt, true); $this->server->saveOfflinePlayerData($this->username, $nbt, true);
} }
parent::__construct($this->level->getChunk($nbt["Pos"][0] >> 4, $nbt["Pos"][2] >> 4, true), $nbt); parent::__construct($this->level->getChunk($nbt["Pos"][0] >> 4, $nbt["Pos"][2] >> 4, true), $nbt);
$this->loggedIn = true; $this->loggedIn = true;
@ -1797,9 +1804,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}else{ }else{
$pk = new ContainerSetContentPacket(); $pk = new ContainerSetContentPacket();
$pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE; $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE;
foreach(Item::getCreativeItems() as $item){ $pk->slots = Item::getCreativeItems();
$pk->slots[] = clone $item;
}
$this->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY)); $this->dataPacket($pk->setChannel(Network::CHANNEL_PRIORITY));
} }
@ -3158,6 +3163,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if(!$this->justCreated){ if(!$this->justCreated){
$newChunk = $this->level->getChunkPlayers($this->x >> 4, $this->z >> 4); $newChunk = $this->level->getChunkPlayers($this->x >> 4, $this->z >> 4);
unset($newChunk[$this->getLoaderId()]);
/** @var Player[] $reload */ /** @var Player[] $reload */
$reload = []; $reload = [];
foreach($this->hasSpawned as $player){ foreach($this->hasSpawned as $player){
@ -3169,9 +3176,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
} }
} }
//TODO HACK: Minecraft: PE does not like moving a player from old chunks. if($this->chunk !== null and $this->spawned){
//Player entities get stuck in unloaded chunks and the client does not accept position updates. //TODO HACK: Minecraft: PE does not like moving a player from old chunks.
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET, Network::CHANNEL_MOVEMENT, $reload); //Player entities get stuck in unloaded chunks and the client does not accept position updates.
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET, Network::CHANNEL_MOVEMENT, $reload);
}
foreach($newChunk as $player){ foreach($newChunk as $player){
$this->spawnTo($player); $this->spawnTo($player);

View File

@ -1021,13 +1021,6 @@ abstract class Entity extends Location implements Metadatable{
$this->setLevel($targetLevel); $this->setLevel($targetLevel);
$this->level->addEntity($this); $this->level->addEntity($this);
if($this instanceof Player){
$this->usedChunks = [];
$pk = new SetTimePacket();
$pk->time = $this->level->getTime();
$pk->started = $this->level->stopTime == false;
$this->dataPacket($pk->setChannel(Network::CHANNEL_WORLD_EVENTS));
}
$this->chunk = null; $this->chunk = null;
return true; return true;

View File

@ -59,7 +59,9 @@ class RegionLoader{
$this->levelProvider = $level; $this->levelProvider = $level;
$this->filePath = $this->levelProvider->getPath() . "region/r.$regionX.$regionZ.mcr"; $this->filePath = $this->levelProvider->getPath() . "region/r.$regionX.$regionZ.mcr";
$exists = file_exists($this->filePath); $exists = file_exists($this->filePath);
touch($this->filePath); if(!$exists){
touch($this->filePath);
}
$this->filePointer = fopen($this->filePath, "r+b"); $this->filePointer = fopen($this->filePath, "r+b");
stream_set_read_buffer($this->filePointer, 1024 * 16); //16KB stream_set_read_buffer($this->filePointer, 1024 * 16); //16KB
stream_set_write_buffer($this->filePointer, 1024 * 16); //16KB stream_set_write_buffer($this->filePointer, 1024 * 16); //16KB
@ -263,10 +265,11 @@ class RegionLoader{
protected function loadLocationTable(){ protected function loadLocationTable(){
fseek($this->filePointer, 0); fseek($this->filePointer, 0);
$this->lastSector = 1; $this->lastSector = 1;
$table = fread($this->filePointer, 4 * 1024 * 2); //1024 records * 4 bytes * 2 times
$data = unpack("N*", fread($this->filePointer, 4 * 1024 * 2)); //1024 records * 4 bytes * 2 times
for($i = 0; $i < 1024; ++$i){ for($i = 0; $i < 1024; ++$i){
$index = unpack("N", substr($table, $i << 2, 4))[1]; $index = $data[$i + 1];
$this->locationTable[$i] = [$index >> 8, $index & 0xff, unpack("N", substr($table, 4096 + ($i << 2), 4))[1]]; $this->locationTable[$i] = [$index >> 8, $index & 0xff, $data[1024 + $i + 1]];
if(($this->locationTable[$i][0] + $this->locationTable[$i][1] - 1) > $this->lastSector){ if(($this->locationTable[$i][0] + $this->locationTable[$i][1] - 1) > $this->lastSector){
$this->lastSector = $this->locationTable[$i][0] + $this->locationTable[$i][1] - 1; $this->lastSector = $this->locationTable[$i][0] + $this->locationTable[$i][1] - 1;
} }