From f14a8e46beb41fb5fd8146d9724ff0044650e242 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 6 Sep 2016 13:05:53 +0100 Subject: [PATCH] Inventory: Fix creative/spectator inventory sending --- src/pocketmine/Player.php | 51 +++++++------------- src/pocketmine/inventory/InventoryType.php | 2 +- src/pocketmine/inventory/PlayerInventory.php | 29 ++++++----- 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 260263e6c..ca253c2e0 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -1096,19 +1096,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->dataPacket($pk); $this->sendSettings(); - if($this->gamemode === Player::SPECTATOR){ - $pk = new ContainerSetContentPacket(); - $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE; - $this->dataPacket($pk); - }else{ - $pk = new ContainerSetContentPacket(); - $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE; - foreach(Item::getCreativeItems() as $item){ - $pk->slots[] = clone $item; - } - $this->dataPacket($pk); - } - $this->inventory->sendContents($this); $this->inventory->sendContents($this->getViewers()); $this->inventory->sendHeldItem($this->hasSpawned); @@ -1183,22 +1170,31 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->dataPacket($pk); } - public function isSurvival(){ + /** + * WARNING: This method does NOT return literal gamemode is survival, it will also return true for adventure mode players. + */ + public function isSurvival() : bool{ return ($this->gamemode & 0x01) === 0; } - public function isCreative(){ - return ($this->gamemode & 0x01) > 0; + /** + * WARNING: This method does NOT return literal gamemode is creative, it will also return true for creative mode players. + */ + public function isCreative() : bool{ + return ($this->gamemode & 0x01) === 1; } - public function isSpectator(){ - return $this->gamemode === 3; - } - - public function isAdventure(){ + /** + * WARNING: This method does NOT return literal gamemode is adventure, it will also return true for spectator mode players. + */ + public function isAdventure() : bool{ return ($this->gamemode & 0x02) > 0; } + public function isSpectator() : bool{ + return $this->gamemode === 3; + } + public function getDrops(){ if(!$this->isCreative()){ return parent::getDrops(); @@ -1632,7 +1628,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $nbt->playerGameType = new IntTag("playerGameType", $this->gamemode); } - $this->allowFlight = $this->isCreative(); + $this->allowFlight = (bool) $this->gamemode & 0x01; if(($level = $this->server->getLevelByName($nbt["Level"])) === null){ $this->setLevel($this->server->getDefaultLevel()); @@ -1737,17 +1733,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade $this->setRemoveFormat(false); } - if($this->gamemode === Player::SPECTATOR){ - $pk = new ContainerSetContentPacket(); - $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE; - $this->dataPacket($pk); - }else{ - $pk = new ContainerSetContentPacket(); - $pk->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE; - $pk->slots = Item::getCreativeItems(); - $this->dataPacket($pk); - } - $this->forceMovement = $this->teleportPosition = $this->getPosition(); $this->server->onPlayerLogin($this); diff --git a/src/pocketmine/inventory/InventoryType.php b/src/pocketmine/inventory/InventoryType.php index d4852fdda..85832a6f3 100644 --- a/src/pocketmine/inventory/InventoryType.php +++ b/src/pocketmine/inventory/InventoryType.php @@ -58,7 +58,7 @@ class InventoryType{ static::$default[static::CHEST] = new InventoryType(27, "Chest", 0); static::$default[static::DOUBLE_CHEST] = new InventoryType(27 + 27, "DoubleTag Chest", 0); - static::$default[static::PLAYER] = new InventoryType(49, "Player", 0); //36 CONTAINER, 4 ARMOR (9 reference HOTBAR slots) + static::$default[static::PLAYER] = new InventoryType(36 + 4, "Player", 0); //36 CONTAINER, 4 ARMOR static::$default[static::FURNACE] = new InventoryType(3, "Furnace", 2); static::$default[static::CRAFTING] = new InventoryType(5, "Crafting", 1); //4 CRAFTING slots, 1 RESULT static::$default[static::WORKBENCH] = new InventoryType(10, "Crafting", 1); //9 CRAFTING slots, 1 RESULT diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index c0e888111..013e91eb9 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -384,16 +384,14 @@ class PlayerInventory extends BaseInventory{ $pk = new ContainerSetContentPacket(); $pk->slots = []; - $holder = $this->getHolder(); - if($holder instanceof Player and $holder->isCreative()){ - //TODO: Remove this workaround because of broken client - foreach(Item::getCreativeItems() as $i => $item){ - $pk->slots[$i] = Item::getCreativeItem($i); - } - }else{ - for($i = 0; $i < $this->getSize(); ++$i){ //Do not send armor by error here - $pk->slots[$i] = $this->getItem($i); - } + + for($i = 0; $i < $this->getSize(); ++$i){ //Do not send armor by error here + $pk->slots[$i] = $this->getItem($i); + } + + //Because PE is stupid and shows 9 less slots than you send it, give it 9 dummy slots so it shows all the REAL slots. + for($i = $this->getSize(); $i < $this->getSize() + $this->getHotbarSize(); ++$i){ + $pk->slots[$i] = Item::get(Item::AIR, 0, 0); } foreach($target as $player){ @@ -401,7 +399,16 @@ class PlayerInventory extends BaseInventory{ if($player === $this->getHolder()){ for($i = 0; $i < $this->getHotbarSize(); ++$i){ $index = $this->getHotbarSlotIndex($i); - $pk->hotbar[] = $index <= -1 ? -1 : $index + 9; + $pk->hotbar[] = $index <= -1 ? -1 : $index + $this->getHotbarSize(); + } + + if($player->getGamemode() & 0x01 === 0x01){ //Send special inventory for creative or spectator + $pk2 = new ContainerSetContentPacket(); + $pk2->windowid = ContainerSetContentPacket::SPECIAL_CREATIVE; + if($player->getGamemode() === Player::CREATIVE){ + $pk2->slots = Item::getCreativeItems(); + } + $player->dataPacket($pk2); } } if(($id = $player->getWindowId($this)) === -1 or $player->spawned !== true){