diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 8058cb3e4..85265c25a 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -794,10 +794,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ * @return boolean */ public function sleepOn(Vector3 $pos){ - foreach($this->level->getPlayers() as $p){ - if($p->sleeping instanceof Vector3){ - if($pos->distance($p->sleeping) <= 0.1){ - return false; + foreach($this->level->getNearbyEntities($this->boundingBox->grow(2, 1, 2), $this) as $p){ + if($p instanceof Player){ + if($p->sleeping instanceof Vector3){ + if($pos->distance($p->sleeping) <= 0.1){ + return false; + } } } } @@ -1150,6 +1152,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $pk->teleport = true; $this->directDataPacket($pk); $this->forceMovement = new Vector3($from->x, $from->y, $from->z); + $this->newPosition = null; }else{ $this->forceMovement = null; if($this->nextChunkOrderRun > 20){ @@ -2273,10 +2276,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ } } + foreach($this->windowIndex as $window){ + $this->removeWindow($window); + } + $this->interface->close($this, $reason); $this->level->freeAllChunks($this); - parent::close(); $this->loggedIn = false; @@ -2284,6 +2290,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ if(isset($ev) and $this->username != "" and $this->spawned !== false and $ev->getQuitMessage() != ""){ $this->server->broadcastMessage($ev->getQuitMessage()); } + $this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this); $this->spawned = false; $this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged out due to " . str_replace(["\n", "\r"], [" ", ""], $reason)); @@ -2291,6 +2298,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ $this->windowIndex = []; $this->usedChunks = []; $this->loadQueue = []; + $this->spawnPosition = null; unset($this->buffer); } @@ -2513,6 +2521,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ public function teleport(Vector3 $pos, $yaw = null, $pitch = null){ if(parent::teleport($pos, $yaw, $pitch)){ + + foreach($this->windowIndex as $window){ + if($window === $this->inventory){ + continue; + } + $this->removeWindow($window); + } + $this->airTicks = 300; $this->fallDistance = 0; $this->orderChunks(); diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 26fc04d52..1e3272ab3 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -643,7 +643,7 @@ class Server{ $result = $this->getPlayerExact($name); if($result === null){ - $result = new OfflinePlayer($this, $name); + return new OfflinePlayer($this, $name); } return $result; @@ -1083,7 +1083,7 @@ class Server{ return false; } - $seed = $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed; + $seed = $seed === null ? Binary::readInt(@Utils::getRandomBytes(4, false)) : (int) $seed; if($generator !== null and class_exists($generator) and is_subclass_of($generator, Generator::class)){ $generator = new $generator($options); @@ -1488,7 +1488,7 @@ class Server{ "level-type" => "DEFAULT", "enable-query" => true, "enable-rcon" => false, - "rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10), + "rcon.password" => substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10), "auto-save" => true, ]); @@ -1534,7 +1534,7 @@ class Server{ } $this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort()); - define("BOOTUP_RANDOM", Utils::getRandomBytes(16)); + define("BOOTUP_RANDOM", @Utils::getRandomBytes(16)); $this->serverID = Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . $this->getPort()), 0, 8)); $this->addInterface($this->mainInterface = new RakLibInterface($this)); diff --git a/src/pocketmine/block/TNT.php b/src/pocketmine/block/TNT.php index 76a2bd3f2..5dc758ac9 100644 --- a/src/pocketmine/block/TNT.php +++ b/src/pocketmine/block/TNT.php @@ -41,7 +41,7 @@ class TNT extends Solid{ public function onActivate(Item $item, Player $player = null){ if($item->getID() === Item::FLINT_STEEL){ $item->useOn($this); - $this->getLevel()->setBlock($this, new Air(), false, false, true); + $this->getLevel()->setBlock($this, new Air(), true); $mot = (new Random())->nextSignedFloat() * M_PI * 2; $tnt = new PrimedTNT($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [ diff --git a/src/pocketmine/entity/Arrow.php b/src/pocketmine/entity/Arrow.php index e43109707..5a010f211 100644 --- a/src/pocketmine/entity/Arrow.php +++ b/src/pocketmine/entity/Arrow.php @@ -85,7 +85,7 @@ class Arrow extends Projectile{ $this->motionY -= $this->gravity; - $this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); + $this->keepMovement = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); $moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ); diff --git a/src/pocketmine/entity/DroppedItem.php b/src/pocketmine/entity/DroppedItem.php index 0f8367a36..79d5b5ae8 100644 --- a/src/pocketmine/entity/DroppedItem.php +++ b/src/pocketmine/entity/DroppedItem.php @@ -93,7 +93,7 @@ class DroppedItem extends Entity{ $this->motionY -= $this->gravity; - $this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); + $this->keepMovement = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); $this->move($this->motionX, $this->motionY, $this->motionZ); $friction = 1 - $this->drag; @@ -126,7 +126,7 @@ class DroppedItem extends Entity{ $this->timings->stopTiming(); - return $hasUpdate or !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0); + return $hasUpdate or !$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0; } public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index ebf1bd73a..80209d80c 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -122,7 +122,7 @@ abstract class Entity extends Location implements Metadatable{ protected $ySize = 0; protected $stepHeight = 0; - public $keepMovement = true; + public $keepMovement = false; public $fallDistance; public $ticksLived; @@ -777,12 +777,11 @@ abstract class Entity extends Location implements Metadatable{ return true; } - //if($this->inBlock){ //TODO: noclip - // $this->boundingBox->offset($dx, $dy, $dz); - // $this->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2; - // $this->y = $this->boundingBox->minY/* + $this->height*/; - // $this->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2; - //}else{ + if($this->keepMovement){ + $this->boundingBox->offset($dx, $dy, $dz); + $pos = new Vector3(($this->boundingBox->minX + $this->boundingBox->maxX) / 2, $this->boundingBox->minY - $this->ySize, ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2); + $this->setPosition($pos); + }else{ Timings::$entityMoveTimer->startTiming(); @@ -841,7 +840,7 @@ abstract class Entity extends Location implements Metadatable{ $this->boundingBox->offset(0, $dy, 0); - if(!$this->keepMovement and $movY != $dy){ + if($movY != $dy){ $dx = 0; $dy = 0; $dz = 0; @@ -855,7 +854,7 @@ abstract class Entity extends Location implements Metadatable{ $this->boundingBox->offset($dx, 0, 0); - if(!$this->keepMovement and $movX != $dx){ + if($movX != $dx){ $dx = 0; $dy = 0; $dz = 0; @@ -867,7 +866,7 @@ abstract class Entity extends Location implements Metadatable{ $this->boundingBox->offset(0, 0, $dz); - if(!$this->keepMovement and $movZ != $dz){ + if($movZ != $dz){ $dx = 0; $dy = 0; $dz = 0; @@ -893,7 +892,7 @@ abstract class Entity extends Location implements Metadatable{ } $this->boundingBox->offset(0, $dy, 0); - if(!$this->keepMovement and $movY != $dy){ + if($movY != $dy){ $dx = 0; $dy = 0; $dz = 0; @@ -904,7 +903,7 @@ abstract class Entity extends Location implements Metadatable{ } $this->boundingBox->offset($dx, 0, 0); - if(!$this->keepMovement and $movX != $dx){ + if($movX != $dx){ $dx = 0; $dy = 0; $dz = 0; @@ -915,13 +914,13 @@ abstract class Entity extends Location implements Metadatable{ } $this->boundingBox->offset(0, 0, $dz); - if(!$this->keepMovement and $movZ != $dz){ + if($movZ != $dz){ $dx = 0; $dy = 0; $dz = 0; } - if(!$this->keepMovement and $movY != $dy){ + if($movY != $dy){ $dx = 0; $dy = 0; $dz = 0; @@ -956,16 +955,14 @@ abstract class Entity extends Location implements Metadatable{ }else{ if($this instanceof Player){ - if(($this->onGround and $movY != 0) or (!$this->onGround and $movY < 0)){ + if(!$this->onGround or $movY != 0){ $bb = clone $this->boundingBox; - $bb->maxY = $bb->minY + 0.5; + $bb->maxY = $bb->minY + 1; if(count($this->level->getCollisionBlocks($bb->expand(0.01, 0.01, 0.01))) > 0){ - $isColliding = true; + $this->onGround = true; }else{ - $isColliding = false; + $this->onGround = false; } - - $this->onGround = ($movY <= 0 and $isColliding); } }else{ $this->onGround = ($movY != $dy and $movY < 0); @@ -990,7 +987,7 @@ abstract class Entity extends Location implements Metadatable{ Timings::$entityMoveTimer->stopTiming(); return $result; - //} + } } protected function checkBlockCollision(){ @@ -1185,10 +1182,11 @@ abstract class Entity extends Location implements Metadatable{ if($this->chunk instanceof FullChunk){ $this->chunk->removeEntity($this); } - if(($level = $this->level) instanceof Level){ - $level->removeEntity($this); + if($this->level instanceof Level){ + $this->level->removeEntity($this); } $this->despawnFromAll(); + $this->level = null; } } diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index a23e8e46e..8393dbb41 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -226,4 +226,14 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ return $d; } + public function close(){ + if(!$this->closed){ + foreach($this->getInventory()->getViewers() as $player){ + $this->getInventory()->close($player); + } + $this->inventory = null; + parent::close(); + } + } + } diff --git a/src/pocketmine/inventory/ChestInventory.php b/src/pocketmine/inventory/ChestInventory.php index acd04533b..5ed416101 100644 --- a/src/pocketmine/inventory/ChestInventory.php +++ b/src/pocketmine/inventory/ChestInventory.php @@ -21,6 +21,7 @@ namespace pocketmine\inventory; +use pocketmine\level\Level; use pocketmine\network\protocol\TileEventPacket; use pocketmine\Player; use pocketmine\Server; @@ -48,7 +49,9 @@ class ChestInventory extends ContainerInventory{ $pk->z = $this->getHolder()->getZ(); $pk->case1 = 1; $pk->case2 = 2; - Server::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk); + if(($level = $this->getHolder()->getLevel()) instanceof Level){ + Server::broadcastPacket($level->getUsingChunk($this->getHolder()->getX() >> 4, $this->getHolder()->getZ() >> 4), $pk); + } } } @@ -60,7 +63,9 @@ class ChestInventory extends ContainerInventory{ $pk->z = $this->getHolder()->getZ(); $pk->case1 = 1; $pk->case2 = 0; - Server::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk); + if(($level = $this->getHolder()->getLevel()) instanceof Level){ + Server::broadcastPacket($level->getUsingChunk($this->getHolder()->getX() >> 4, $this->getHolder()->getZ() >> 4), $pk); + } } parent::onClose($who); } diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 24679a93c..309c3e40e 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -304,11 +304,20 @@ class Level implements ChunkManager, Metadatable{ } public function close(){ + if($this->getAutoSave()){ $this->save(); } - $this->unloadChunks(); + + foreach($this->chunks as $chunk){ + $this->unloadChunk($chunk->getX(), $chunk->getZ(), false); + } + + $this->server->getGenerationManager()->closeLevel($this); $this->provider->close(); + $this->provider = null; + $this->blockMetadata = null; + $this->blockCache = []; } /** @@ -355,11 +364,13 @@ class Level implements ChunkManager, Metadatable{ $player->teleport($this->server->getDefaultLevel()->getSafeSpawn()); } } - $this->close(); + if($this === $defaultLevel){ $this->server->setDefaultLevel(null); } + $this->close(); + return true; } @@ -1094,7 +1105,7 @@ class Level implements ChunkManager, Metadatable{ } } - if(!($player instanceof Player) or ($player->getGamemode() & 0x01) === 0){ + if(!($player instanceof Player) or $player->isSurvival()){ foreach($drops as $drop){ if($drop[2] > 0){ $this->dropItem($vector->add(0.5, 0.5, 0.5), Item::get(...$drop)); @@ -2071,18 +2082,18 @@ class Level implements ChunkManager, Metadatable{ } public function setMetadata($metadataKey, MetadataValue $metadataValue){ - $this->server->getPlayerMetadata()->setMetadata($this, $metadataKey, $metadataValue); + $this->server->getLevelMetadata()->setMetadata($this, $metadataKey, $metadataValue); } public function getMetadata($metadataKey){ - return $this->server->getPlayerMetadata()->getMetadata($this, $metadataKey); + return $this->server->getLevelMetadata()->getMetadata($this, $metadataKey); } public function hasMetadata($metadataKey){ - return $this->server->getPlayerMetadata()->hasMetadata($this, $metadataKey); + return $this->server->getLevelMetadata()->hasMetadata($this, $metadataKey); } public function removeMetadata($metadataKey, Plugin $plugin){ - $this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $plugin); + $this->server->getLevelMetadata()->removeMetadata($this, $metadataKey, $plugin); } } diff --git a/src/pocketmine/level/format/generic/BaseFullChunk.php b/src/pocketmine/level/format/generic/BaseFullChunk.php index b17bd465e..f4b674294 100644 --- a/src/pocketmine/level/format/generic/BaseFullChunk.php +++ b/src/pocketmine/level/format/generic/BaseFullChunk.php @@ -294,6 +294,7 @@ abstract class BaseFullChunk implements FullChunk{ foreach($this->getTiles() as $tile){ $tile->close(); } + $this->provider = null; return true; } diff --git a/src/pocketmine/level/format/mcregion/McRegion.php b/src/pocketmine/level/format/mcregion/McRegion.php index ec700a056..4b6f5c09f 100644 --- a/src/pocketmine/level/format/mcregion/McRegion.php +++ b/src/pocketmine/level/format/mcregion/McRegion.php @@ -191,9 +191,7 @@ class McRegion extends BaseLevelProvider{ public function unloadChunk($x, $z, $safe = true){ $chunk = $this->getChunk($x, $z, false); if($chunk instanceof FullChunk and $chunk->unload(false, $safe)){ - $this->chunks[$index = Level::chunkHash($x, $z)] = null; - - unset($this->chunks[$index]); + unset($this->chunks[Level::chunkHash($x, $z)]); } return true; @@ -299,5 +297,6 @@ class McRegion extends BaseLevelProvider{ $region->close(); unset($this->regions[$index]); } + $this->level = null; } } \ No newline at end of file diff --git a/src/pocketmine/level/format/mcregion/RegionLoader.php b/src/pocketmine/level/format/mcregion/RegionLoader.php index d6c4159f1..64a0eb13d 100644 --- a/src/pocketmine/level/format/mcregion/RegionLoader.php +++ b/src/pocketmine/level/format/mcregion/RegionLoader.php @@ -198,6 +198,7 @@ class RegionLoader{ public function close(){ $this->writeLocationTable(); fclose($this->filePointer); + $this->levelProvider = null; } public function doSlowCleanUp(){ diff --git a/src/pocketmine/network/query/QueryHandler.php b/src/pocketmine/network/query/QueryHandler.php index 155e6c1a9..750f5e0ca 100644 --- a/src/pocketmine/network/query/QueryHandler.php +++ b/src/pocketmine/network/query/QueryHandler.php @@ -66,7 +66,7 @@ class QueryHandler{ public function regenerateToken(){ $this->lastToken = $this->token; - $this->token = Utils::getRandomBytes(16, false); + $this->token = @Utils::getRandomBytes(16, false); } public static function getTokenString($token, $salt){ diff --git a/src/pocketmine/tile/Tile.php b/src/pocketmine/tile/Tile.php index 4e735e488..2444e6b33 100644 --- a/src/pocketmine/tile/Tile.php +++ b/src/pocketmine/tile/Tile.php @@ -121,6 +121,7 @@ abstract class Tile extends Position{ if(($level = $this->getLevel()) instanceof Level){ $level->removeTile($this); } + $this->level = null; } } diff --git a/src/pocketmine/wizard/Installer.php b/src/pocketmine/wizard/Installer.php index 7842eb946..b9c10cab3 100644 --- a/src/pocketmine/wizard/Installer.php +++ b/src/pocketmine/wizard/Installer.php @@ -175,7 +175,7 @@ LICENSE; echo "[?] " . $this->lang->rcon_enable . " (y/N): "; if(strtolower($this->getInput("n")) === "y"){ $config->set("enable-rcon", true); - $password = substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10); + $password = substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10); $config->set("rcon.password", $password); echo "[*] " . $this->lang->rcon_password . ": " . $password . "\n"; }else{