diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index d163ee128..527b9a1fb 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -28,7 +28,6 @@ use pocketmine\event\player\PlayerAchievementAwardedEvent; use pocketmine\event\player\PlayerChatEvent; use pocketmine\event\player\PlayerCommandPreprocessEvent; use pocketmine\event\player\PlayerGameModeChangeEvent; -use pocketmine\event\player\PlayerItemHeldEvent; use pocketmine\event\player\PlayerJoinEvent; use pocketmine\event\player\PlayerKickEvent; use pocketmine\event\player\PlayerLoginEvent; @@ -37,7 +36,10 @@ use pocketmine\event\player\PlayerQuitEvent; use pocketmine\event\player\PlayerRespawnEvent; use pocketmine\event\server\DataPacketReceiveEvent; use pocketmine\event\server\DataPacketSendEvent; +use pocketmine\inventory\Inventory; +use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; +use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\Level; use pocketmine\level\Position; use pocketmine\math\Vector3; @@ -48,9 +50,6 @@ use pocketmine\nbt\tag\Compound; use pocketmine\nbt\tag\String; use pocketmine\network\protocol\AdventureSettingsPacket; use pocketmine\network\protocol\ChunkDataPacket; -use pocketmine\network\protocol\ContainerClosePacket; -use pocketmine\network\protocol\ContainerSetContentPacket; -use pocketmine\network\protocol\ContainerSetSlotPacket; use pocketmine\network\protocol\DataPacket; use pocketmine\network\protocol\DisconnectPacket; use pocketmine\network\protocol\Info as ProtocolInfo; @@ -61,7 +60,6 @@ use pocketmine\network\protocol\ServerHandshakePacket; use pocketmine\network\protocol\SetSpawnPositionPacket; use pocketmine\network\protocol\SetTimePacket; use pocketmine\network\protocol\StartGamePacket; -use pocketmine\network\protocol\TileEventPacket; use pocketmine\network\protocol\UnknownPacket; use pocketmine\network\protocol\UpdateBlockPacket; use pocketmine\network\raknet\Info; @@ -69,11 +67,8 @@ use pocketmine\network\raknet\Packet; use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissionAttachment; use pocketmine\plugin\Plugin; -use pocketmine\level\format\pmf\LevelFormat; use pocketmine\recipes\Crafting; use pocketmine\scheduler\CallbackTask; -use pocketmine\tile\Chest; -use pocketmine\tile\Furnace; use pocketmine\tile\Sign; use pocketmine\tile\Spawnable; use pocketmine\tile\Tile; @@ -84,7 +79,7 @@ use pocketmine\utils\TextFormat; * Main class that handles networking, recovery, and packet sending to the server part * TODO: Move reliability layer */ -class Player extends Human implements CommandSender, IPlayer{ +class Player extends Human implements CommandSender, InventoryHolder, IPlayer{ const SURVIVAL = 0; const CREATIVE = 1; @@ -102,8 +97,13 @@ class Player extends Human implements CommandSender, IPlayer{ public $loggedIn = false; public $gamemode; public $lastBreak; - public $windowCnt = 2; - public $windows = []; + + protected $windowCnt = 2; + /** @var \SplObjectStorage */ + protected $windows; + /** @var Inventory[] */ + protected $windowIndex = []; + public $blocked = true; public $achievements = []; public $chunksLoaded = []; @@ -358,6 +358,7 @@ class Player extends Human implements CommandSender, IPlayer{ * @param integer $MTU */ public function __construct($clientID, $ip, $port, $MTU){ + $this->windows = new \SplObjectStorage(); $this->perm = new PermissibleBase($this); $this->namedtag = new Compound(); $this->bigCnt = 0; @@ -1322,6 +1323,7 @@ class Player extends Human implements CommandSender, IPlayer{ if($p !== $this and strtolower($p->getName()) === strtolower($this->getName())){ if($p->kick("logged in from another location") === false){ $this->close($this->getName() . " has left the game", "already logged in"); + return; }else{ break; @@ -1432,9 +1434,9 @@ class Player extends Human implements CommandSender, IPlayer{ $this->spawned = true; $this->spawnToAll(); - $this->sendInventory(); $this->sendSettings(); - $this->sendArmor(); + $this->getInventory()->sendContents($this); + $this->getInventory()->sendArmorContents($this); $this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask(array($this, "orderChunks")), 30); $this->blocked = false; @@ -1510,26 +1512,13 @@ class Player extends Human implements CommandSender, IPlayer{ } } }else{ - $item = $this->getSlot($packet->slot); + $item = $this->inventory->getItem($packet->slot); } if(!isset($item) or $packet->slot === false){ - $this->sendInventorySlot($packet->slot); + $this->inventory->sendSlot($packet->slot, $this); }else{ - $this->server->getPluginManager()->callEvent($ev = new PlayerItemHeldEvent($this, $item, $packet->slot, 0)); - if($ev->isCancelled()){ - $this->sendInventorySlot($packet->slot); - }elseif($item instanceof Item){ - $this->setEquipmentSlot(0, $packet->slot); - $this->setCurrentEquipmentSlot(0); - if(($this->gamemode & 0x01) === 0){ - if(!in_array($this->slot, $this->hotbar)){ - array_pop($this->hotbar); - array_unshift($this->hotbar, $this->slot); - } - } - - } + $this->inventory->setHeldItemSlot($packet->slot); } if($this->inAction === true){ @@ -1576,18 +1565,21 @@ class Player extends Human implements CommandSender, IPlayer{ if($blockVector->distance($this) > 10){ }elseif(($this->gamemode & 0x01) === 1){ - $item = Item::get(Block::$creative[$this->getCurrentEquipment()][0], Block::$creative[$this->getCurrentEquipment()][1], 1); + $item = Item::get( + Block::$creative[$this->inventory->getHeldItemSlot()][0], + Block::$creative[$this->inventory->getHeldItemSlot()][1], + 1 + ); if($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){ break; } - }elseif($this->getSlot($this->getCurrentEquipment())->getID() !== $packet->item or ($this->getSlot($this->getCurrentEquipment())->isTool() === false and $this->getSlot($this->getCurrentEquipment())->getDamage() !== $packet->meta)){ - $this->sendInventorySlot($this->getCurrentEquipment()); + }elseif($this->inventory->getItemInHand()->getID() !== $packet->item or ($this->inventory->getItemInHand()->isTool() === false and $this->inventory->getItemInHand()->getDamage() !== $packet->meta)){ + $this->inventory->sendHeldItem($this); }else{ - $item = clone $this->getSlot($this->getCurrentEquipment()); + $item = clone $this->inventory->getItemInHand(); //TODO: Implement adventure mode checks if($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){ - $this->setSlot($this->getCurrentEquipment(), $item); - $this->sendInventorySlot($this->getCurrentEquipment()); + $this->inventory->setItemInHand($item); break; } } @@ -1704,15 +1696,19 @@ class Player extends Human implements CommandSender, IPlayer{ if(($this->gamemode & 0x01) === 1){ - $item = Item::get(Block::$creative[$this->getCurrentEquipment()][0], Block::$creative[$this->getCurrentEquipment()][1], 1); + $item = Item::get( + Block::$creative[$this->inventory->getHeldItemSlot()][0], + Block::$creative[$this->inventory->getHeldItemSlot()][1], + 1 + ); }else{ - $item = clone $this->getSlot($this->getCurrentEquipment()); + $item = clone $this->inventory->getItemInHand(); } if(($drops = $this->getLevel()->useBreakOn($vector, $item)) !== true){ if(($this->gamemode & 0x01) === 0){ //TODO: drop items - $this->setSlot($this->getCurrentEquipment(), $item); + $this->inventory->setItemInHand($item); } break; } @@ -1739,33 +1735,22 @@ class Player extends Human implements CommandSender, IPlayer{ }else{ $s = Item::get($s + 256, 0, 1); } - $slot = $this->getArmorSlot($i); + $slot = $this->inventory->getArmorItem($i); if($slot->getID() !== Item::AIR and $s->getID() === Item::AIR){ - if($this->setArmorSlot($i, Item::get(Item::AIR, 0, 0)) === false){ - $this->sendArmor(); - $this->sendInventory(); + $this->inventory->setArmorItem($i, Item::get(Item::AIR, 0, 0)); + }elseif($s->getID() !== Item::AIR and $slot->getID() === Item::AIR and ($sl = $this->inventory->first($s)) !== -1){ + if($this->inventory->setArmorItem($i, $this->inventory->getItem($sl)) === false){ + $this->inventory->sendContents($this); }else{ - $this->addItem($slot); - $packet->slots[$i] = 255; + $this->inventory->setItem($sl, Item::get(Item::AIR, 0, 0)); } - }elseif($s->getID() !== Item::AIR and $slot->getID() === Item::AIR and ($sl = $this->hasItem($s, false)) !== false){ - if($this->setArmorSlot($i, $this->getSlot($sl)) === false){ - $this->sendArmor(); - $this->sendInventory(); + }elseif($s->getID() !== Item::AIR and $slot->getID() !== Item::AIR and ($slot->getID() !== $s->getID() or $slot->getDamage() !== $s->getDamage()) and ($sl = $this->inventory->first($s)) !== -1){ + if($this->inventory->setArmorItem($i, $this->inventory->getItem($sl)) === false){ + $this->inventory->sendContents($this); }else{ - $this->setSlot($sl, Item::get(Item::AIR, 0, 0)); + $this->inventory->setItem($sl, $slot); } - }elseif($s->getID() !== Item::AIR and $slot->getID() !== Item::AIR and ($slot->getID() !== $s->getID() or $slot->getDamage() !== $s->getDamage()) and ($sl = $this->hasItem($s, false)) !== false){ - if($this->setArmorSlot($i, $this->getSlot($sl)) === false){ - $this->sendArmor(); - $this->sendInventory(); - }else{ - $this->setSlot($sl, $slot); - } - }else{ - $packet->slots[$i] = 255; } - } if($this->inAction === true){ @@ -1884,7 +1869,10 @@ class Player extends Human implements CommandSender, IPlayer{ //$this->entity->setHealth(20, "respawn", true); //$this->entity->updateMetadata(); - $this->sendInventory(); + $this->sendSettings(); + $this->inventory->sendContents($this); + $this->inventory->sendArmorContents($this); + $this->blocked = false; break; case ProtocolInfo::SET_HEALTH_PACKET: //Not used @@ -1989,37 +1977,16 @@ class Player extends Human implements CommandSender, IPlayer{ } break; case ProtocolInfo::CONTAINER_CLOSE_PACKET: - if($this->spawned === false){ + if($this->spawned === false or $packet->windowid === 0){ break; } $this->craftingItems = []; $this->toCraft = []; - if(isset($this->windows[$packet->windowid])){ - if(is_array($this->windows[$packet->windowid])){ - foreach($this->windows[$packet->windowid] as $ob){ - $pk = new TileEventPacket; - $pk->x = $ob->x; - $pk->y = $ob->y; - $pk->z = $ob->z; - $pk->case1 = 1; - $pk->case2 = 0; - Player::broadcastPacket($this->getLevel()->players, $pk); - } - }elseif($this->windows[$packet->windowid] instanceof Chest){ - $pk = new TileEventPacket; - $pk->x = $this->windows[$packet->windowid]->x; - $pk->y = $this->windows[$packet->windowid]->y; - $pk->z = $this->windows[$packet->windowid]->z; - $pk->case1 = 1; - $pk->case2 = 0; - Player::broadcastPacket($this->getLevel()->players, $pk); - } + if(isset($this->windowIndex[$packet->windowid])){ + $this->removeWindow($this->windowIndex[$packet->windowid]); + }else{ + unset($this->windowIndex[$packet->windowid]); } - unset($this->windows[$packet->windowid]); - - $pk = new ContainerClosePacket; - $pk->windowid = $packet->windowid; - $this->dataPacket($pk); break; case ProtocolInfo::CONTAINER_SET_SLOT_PACKET: if($this->spawned === false or $this->blocked === true){ @@ -2035,9 +2002,9 @@ class Player extends Human implements CommandSender, IPlayer{ $this->craftingItems = []; } - if($packet->windowid === 0){ + if($packet->windowid === 0){ //Crafting! $craft = false; - $slot = $this->getSlot($packet->slot); + $slot = $this->inventory->getItem($packet->slot); if($slot->getCount() >= $packet->item->getCount() and (($slot->getID() === $packet->item->getID() and $slot->getDamage() === $packet->item->getDamage()) or ($packet->item->getID() === Item::AIR and $packet->item->getCount() === 0)) and !isset($this->craftingItems[$packet->slot])){ //Crafting recipe $use = Item::get($slot->getID(), $slot->getDamage(), $slot->getCount() - $packet->item->getCount()); $this->craftingItems[$packet->slot] = $use; @@ -2066,7 +2033,7 @@ class Player extends Human implements CommandSender, IPlayer{ if($craft === true and count($this->craftingItems) > 0 and count($this->toCraft) > 0 and ($recipe = $this->craftItems($this->toCraft, $this->craftingItems, $this->toCraft[-1])) !== true){ if($recipe === false){ - $this->sendInventory(); + $this->inventory->sendContents($this); $this->toCraft = []; }else{ $this->toCraft = array(-1 => $this->toCraft[-1]); @@ -2077,129 +2044,57 @@ class Player extends Human implements CommandSender, IPlayer{ $this->toCraft = []; $this->craftingItems = []; } - if(!isset($this->windows[$packet->windowid])){ + if(!isset($this->windowIndex[$packet->windowid])){ break; } - if(is_array($this->windows[$packet->windowid])){ - /** @var \pocketmine\tile\Container[] $tiles */ - $tiles = $this->windows[$packet->windowid]; - if($packet->slot >= 0 and $packet->slot < Chest::SLOTS){ - $tile = $tiles[0]; - $slotn = $packet->slot; - $offset = 0; - }elseif($packet->slot >= Chest::SLOTS and $packet->slot <= (Chest::SLOTS << 1)){ - $tile = $tiles[1]; - $slotn = $packet->slot - Chest::SLOTS; - $offset = Chest::SLOTS; - }else{ - break; - } - $item = Item::get($packet->item->getID(), $packet->item->getDamage(), $packet->item->getCount()); + $inv = $this->windowIndex[$packet->windowid]; + if($packet->slot < 0 or $packet->slot >= $inv->getSize()){ + break; + } - $slot = $tile->getSlot($slotn); - //TODO: container access events? - /*if($this->server->api->dhandle("player.container.slot", array( - "tile" => $tile, - "slot" => $packet->slot, - "offset" => $offset, - "slotdata" => $slot, - "itemdata" => $item, - "player" => $this, - )) === false - ){ - $pk = new ContainerSetSlotPacket; - $pk->windowid = $packet->windowid; - $pk->slot = $packet->slot; - $pk->item = $slot; - $this->dataPacket($pk); - break; - }*/ - if($item->getID() !== Item::AIR and $slot->getID() == $item->getID()){ - if($slot->getCount() < $item->getCount()){ - $it = clone $item; - $it->setCount($item->getCount() - $slot->getCount()); - if($this->removeItem($it) === false){ - $this->sendInventory(); - break; - } - }elseif($slot->getCount() > $item->getCount()){ - $it = clone $item; - $it->setCount($slot->getCount() - $item->getCount()); - $this->addItem($it); + /** @var Item $item */ + $item = clone $packet->item; + + $slot = $inv->getItem($packet->slot); + + if($item->getID() !== Item::AIR and $slot->equals($item, true)){ + if($slot->getCount() < $item->getCount()){ + $it = clone $item; + $it->setCount($item->getCount() - $slot->getCount()); + $remaining = $this->inventory->removeItem($it); + if(count($remaining) > 0){ + /** @var Item $it */ + $it = array_pop($remaining); + $item->setCount($item->getCount() - $it->getCount()); } - }else{ - if($this->removeItem($item) === false){ - $this->sendInventory(); - break; + }elseif($slot->getCount() > $item->getCount()){ + $it = clone $item; + $it->setCount($slot->count - $item->count); + $remaining = $this->inventory->addItem($it); + if(count($remaining) > 0){ + /** @var Item $it */ + $it = array_pop($remaining); + $item->setCount($item->getCount() + $it->getCount()); } - $this->addItem($slot); } - $tile->setSlot($slotn, $item, true, $offset); - }else{ - $tile = $this->windows[$packet->windowid]; - if( - !($tile instanceof Chest or $tile instanceof Furnace) - or $packet->slot < 0 - or ( - $tile instanceof Chest - and $packet->slot >= Chest::SLOTS - ) or ( - $tile instanceof Furnace and $packet->slot >= Furnace::SLOTS - ) - ){ - break; - } - $item = Item::get($packet->item->getID(), $packet->item->getDamage(), $packet->item->getCount()); - - $slot = $tile->getSlot($packet->slot); - //TODO: container access events? - /*if($this->server->api->dhandle("player.container.slot", array( - "tile" => $tile, - "slot" => $packet->slot, - "slotdata" => $slot, - "itemdata" => $item, - "player" => $this, - )) === false - ){ - $pk = new ContainerSetSlotPacket; - $pk->windowid = $packet->windowid; - $pk->slot = $packet->slot; - $pk->item = $slot; - $this->dataPacket($pk); - break; - }*/ - - if($tile instanceof Furnace and $packet->slot == 2){ + if($inv->getType()->getDefaultTitle() === "Furnace" and $packet->slot == 2){ switch($slot->getID()){ case Item::IRON_INGOT: $this->awardAchievement("acquireIron"); break; } } - - if($item->getID() !== Item::AIR and $slot->getID() == $item->getID()){ - if($slot->getCount() < $item->getCount()){ - $it = clone $item; - $it->setCount($item->getCount() - $slot->getCount()); - if($this->removeItem($it) === false){ - $this->sendInventory(); - break; - } - }elseif($slot->getCount() > $item->getCount()){ - $it = clone $item; - $it->setCount($slot->count - $item->count); - $this->addItem($it); - } - }else{ - if($this->removeItem($item) === false){ - $this->sendInventory(); - break; - } - $this->addItem($slot); + }else{ //TODO: check this. I don't know what is this for + $remaining = $this->inventory->removeItem($item); + if(count($remaining) > 0){ + $this->inventory->removeItem(); + break; } - $tile->setSlot($packet->slot, $item); + $this->inventory->addItem($slot); } + $inv->setItem($packet->slot, $item); + break; case ProtocolInfo::SEND_INVENTORY_PACKET: //TODO, Mojang, enable this ยด^_^` if($this->spawned === false){ @@ -2323,9 +2218,8 @@ class Player extends Human implements CommandSender, IPlayer{ $this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this); $this->spawned = false; console("[INFO] " . TextFormat::AQUA . $this->username . TextFormat::RESET . "[/" . $this->ip . ":" . $this->port . "] logged out due to " . $reason); - $this->windows = []; - $this->armor = []; - $this->inventory = []; + $this->windows = new \SplObjectStorage(); + $this->windowIndex = []; $this->chunksLoaded = []; $this->chunksOrder = []; $this->chunkCount = []; @@ -2465,18 +2359,18 @@ class Player extends Human implements CommandSender, IPlayer{ //} foreach($recipe as $slot => $item){ - $s = $this->getSlot($slot); + $s = $this->inventory->getItem($slot); $s->setCount($s->getCount() - $item->getCount()); if($s->getCount() <= 0){ - $this->setSlot($slot, Item::get(Item::AIR, 0, 0)); + $this->inventory->setItem($slot, Item::get(Item::AIR, 0, 0)); } } foreach($craft as $slot => $item){ - $s = $this->getSlot($slot); + $s = $this->inventory->getItem($slot); if($s->getCount() <= 0 or $s->getID() === Item::AIR){ - $this->setSlot($slot, Item::get($item->getID(), $item->getDamage(), $item->getCount())); + $this->inventory->setItem($slot, Item::get($item->getID(), $item->getDamage(), $item->getCount())); }else{ - $this->setSlot($slot, Item::get($item->getID(), $item->getDamage(), $s->getCount() + $item->getCount())); + $this->inventory->setItem($slot, Item::get($item->getID(), $item->getDamage(), $s->getCount() + $item->getCount())); } switch($item->getID()){ @@ -2497,7 +2391,7 @@ class Player extends Human implements CommandSender, IPlayer{ break; case Item::CAKE: $this->awardAchievement("bakeCake"); - $this->addItem(Item::get(Item::BUCKET, 0, 3)); + $this->inventory->addItem(Item::get(Item::BUCKET, 0, 3)); break; case Item::STONE_PICKAXE: case Item::GOLD_PICKAXE: @@ -2519,59 +2413,46 @@ class Player extends Human implements CommandSender, IPlayer{ return $res; } - public function setSlot($slot, Item $item){ - parent::setSlot($slot, $item); - $this->sendInventorySlot($slot); + + /** + * @param Inventory $inventory + * + * @return int + */ + public function getWindowId(Inventory $inventory){ + if($this->windows->contains($inventory)){ + return $this->windows[$inventory]; + } + + return -1; } /** - * Sends a single slot - * TODO: Check if Mojang has implemented this on Minecraft: PE 0.9.0 + * Returns the created/existing window id * - * @param int $s + * @param Inventory $inventory * - * @return bool + * @return int */ - public function sendInventorySlot($s){ - $this->sendInventory(); - - return; //TODO: Check if Mojang adds this - $s = (int) $s; - if(!isset($this->inventory[$s])){ - $pk = new ContainerSetSlotPacket; - $pk->windowid = 0; - $pk->slot = (int) $s; - $pk->item = Item::get(Item::AIR, 0, 0); - $this->dataPacket($pk); + public function addWindow(Inventory $inventory){ + if($this->windows->contains($inventory)){ + return $this->windows[$inventory]; } + $this->windowCnt = $cnt = max(2, ++$this->windowCnt % 99); + $this->windowIndex[$cnt] = $inventory; + $this->windows->attach($inventory, $cnt); + $this->inventory->onOpen($this); - $slot = $this->inventory[$s]; - $pk = new ContainerSetSlotPacket; - $pk->windowid = 0; - $pk->slot = (int) $s; - $pk->item = $slot; - $this->dataPacket($pk); - - return true; + return $cnt; } - /** - * Sends the full inventory - */ - public function sendInventory(){ - if(($this->gamemode & 0x01) === 1){ - return; + public function removeWindow(Inventory $inventory){ + $inventory->onClose($this); + if($this->windows->contains($inventory)){ + $inventory->onClose($this); + $id = $this->windows[$inventory]; + unset($this->windowIndex[$id]); } - $hotbar = []; - foreach($this->hotbar as $slot){ - $hotbar[] = $slot <= -1 ? -1 : $slot + 9; - } - - $pk = new ContainerSetContentPacket; - $pk->windowid = 0; - $pk->slots = $this->inventory; - $pk->hotbar = $hotbar; - $this->dataPacket($pk); } public function setMetadata($metadataKey, MetadataValue $metadataValue){ diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index fa275ece8..aac6477b2 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -89,7 +89,7 @@ namespace pocketmine { const PHP_VERSION = "5.5"; if(\Phar::running(true) !== ""){ - @define("pocketmine\\PATH", \Phar::running(true)."/"); + @define("pocketmine\\PATH", \Phar::running(true) . "/"); }else{ @define("pocketmine\\PATH", \getcwd() . DIRECTORY_SEPARATOR); } diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 7bfcb88e2..384ba13ea 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -31,7 +31,6 @@ use pocketmine\block\Furnace; use pocketmine\command\CommandReader; use pocketmine\command\CommandSender; use pocketmine\command\ConsoleCommandSender; -use pocketmine\command\PluginCommand; use pocketmine\command\PluginIdentifiableCommand; use pocketmine\command\SimpleCommandMap; use pocketmine\entity\Entity; @@ -41,6 +40,7 @@ use pocketmine\event\server\PacketSendEvent; use pocketmine\event\server\ServerCommandEvent; use pocketmine\inventory\InventoryType; use pocketmine\item\Item; +use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\generator\Flat; use pocketmine\level\generator\Generator; use pocketmine\level\generator\Normal; @@ -73,7 +73,6 @@ use pocketmine\permission\DefaultPermissions; use pocketmine\plugin\Plugin; use pocketmine\plugin\PluginLoadOrder; use pocketmine\plugin\PluginManager; -use pocketmine\level\format\pmf\LevelFormat; use pocketmine\recipes\Crafting; use pocketmine\scheduler\CallbackTask; use pocketmine\scheduler\SendUsageTask; @@ -795,6 +794,7 @@ class Server{ return true; }elseif(!$this->isLevelGenerated($name)){ console("[NOTICE] Level \"" . $name . "\" not found"); + return false; } @@ -1830,7 +1830,7 @@ class Server{ } $this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", array( - "serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() .":". $this->getPort()), 0, 8)), + "serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)), "port" => $this->getPort(), "os" => Utils::getOS(), "memory_total" => $this->getConfigString("memory-limit"), diff --git a/src/pocketmine/block/Bed.php b/src/pocketmine/block/Bed.php index 87ea7dca6..26be10a25 100644 --- a/src/pocketmine/block/Bed.php +++ b/src/pocketmine/block/Bed.php @@ -24,7 +24,6 @@ namespace pocketmine\block; use pocketmine\item\Item; use pocketmine\network\protocol\ChatPacket; use pocketmine\Player; -use pocketmine\Server; class Bed extends Transparent{ public function __construct($type = 0){ diff --git a/src/pocketmine/block/Block.php b/src/pocketmine/block/Block.php index 67b9d6e62..2927ede3f 100644 --- a/src/pocketmine/block/Block.php +++ b/src/pocketmine/block/Block.php @@ -25,7 +25,6 @@ namespace pocketmine\block; use pocketmine\item\Item; -use pocketmine\level\Level; use pocketmine\level\Position; use pocketmine\metadata\Metadatable; use pocketmine\metadata\MetadataValue; @@ -753,11 +752,11 @@ abstract class Block extends Position implements Metadatable{ } public function getMetadata($metadataKey){ - return null;//return $this->server->getPlayerMetadata()->getMetadata($this, $metadataKey); + return null; //return $this->server->getPlayerMetadata()->getMetadata($this, $metadataKey); } public function hasMetadata($metadataKey){ - return false;//return $this->server->getPlayerMetadata()->hasMetadata($this, $metadataKey); + return false; //return $this->server->getPlayerMetadata()->hasMetadata($this, $metadataKey); } public function removeMetadata($metadataKey, Plugin $plugin){ diff --git a/src/pocketmine/block/BurningFurnace.php b/src/pocketmine/block/BurningFurnace.php index 90ba81808..3c10002a0 100644 --- a/src/pocketmine/block/BurningFurnace.php +++ b/src/pocketmine/block/BurningFurnace.php @@ -118,8 +118,8 @@ class BurningFurnace extends Solid{ } $t = $this->getLevel()->getTile($this); if($t instanceof Furnace){ - for($s = 0; $s < Furnace::SLOTS; ++$s){ - $slot = $t->getSlot($s); + for($s = 0; $s < $t->getInventory()->getSize(); ++$s){ + $slot = $t->getInventory()->getItem($s); if($slot->getID() > Item::AIR and $slot->getCount() > 0){ $drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount()); } diff --git a/src/pocketmine/block/Chest.php b/src/pocketmine/block/Chest.php index dc77a987a..4aaa15c2b 100644 --- a/src/pocketmine/block/Chest.php +++ b/src/pocketmine/block/Chest.php @@ -59,8 +59,9 @@ class Chest extends Transparent{ continue; } $c = $this->getSide($side); - if(($c instanceof TileChest) and $c->getDamage() === $this->meta){ - if((($tile = $this->getLevel()->getTile($c)) instanceof TileChest) and !$tile->isPaired()){ + if($c instanceof Chest and $c->getDamage() === $this->meta){ + $tile = $this->getLevel()->getTile($c); + if($tile instanceof TileChest and !$tile->isPaired()){ $chest = $tile; break; } @@ -104,7 +105,7 @@ class Chest extends Transparent{ } $t = $this->getLevel()->getTile($this); - $chest = false; + $chest = null; if($t instanceof TileChest){ $chest = $t; }else{ @@ -123,8 +124,7 @@ class Chest extends Transparent{ if(($player->gamemode & 0x01) === 0x01){ return true; } - - $chest->openInventory($player); + $player->addWindow($chest->getInventory()); } return true; @@ -135,9 +135,9 @@ class Chest extends Transparent{ array($this->id, 0, 1), ); $t = $this->getLevel()->getTile($this); - if($t instanceof Chest){ - for($s = 0; $s < Chest::SLOTS; ++$s){ - $slot = $t->getSlot($s); + if($t instanceof TileChest){ + for($s = 0; $s < $t->getInventory()->getSize(); ++$s){ + $slot = $t->getInventory()->getItem($s); if($slot->getID() > Item::AIR and $slot->getCount() > 0){ $drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount()); } diff --git a/src/pocketmine/command/Command.php b/src/pocketmine/command/Command.php index 50f16f4ba..538571b96 100644 --- a/src/pocketmine/command/Command.php +++ b/src/pocketmine/command/Command.php @@ -301,7 +301,7 @@ abstract class Command{ } } } - + /** * @return string */ diff --git a/src/pocketmine/command/RemoteConsoleCommandSender.php b/src/pocketmine/command/RemoteConsoleCommandSender.php index 3651be843..852fe8f15 100644 --- a/src/pocketmine/command/RemoteConsoleCommandSender.php +++ b/src/pocketmine/command/RemoteConsoleCommandSender.php @@ -28,7 +28,7 @@ class RemoteConsoleCommandSender extends ConsoleCommandSender{ private $messages = ""; public function sendMessage($message){ - $this->messages .= trim($message, "\r\n")."\n"; + $this->messages .= trim($message, "\r\n") . "\n"; } public function getMessage(){ diff --git a/src/pocketmine/command/SimpleCommandMap.php b/src/pocketmine/command/SimpleCommandMap.php index c5457511c..205962966 100644 --- a/src/pocketmine/command/SimpleCommandMap.php +++ b/src/pocketmine/command/SimpleCommandMap.php @@ -50,10 +50,10 @@ use pocketmine\command\defaults\StatusCommand; use pocketmine\command\defaults\StopCommand; use pocketmine\command\defaults\TeleportCommand; use pocketmine\command\defaults\TellCommand; +use pocketmine\command\defaults\TimeCommand; use pocketmine\command\defaults\VanillaCommand; use pocketmine\command\defaults\VersionCommand; use pocketmine\command\defaults\WhitelistCommand; -use pocketmine\command\defaults\TimeCommand; use pocketmine\Server; class SimpleCommandMap implements CommandMap{ diff --git a/src/pocketmine/command/defaults/KillCommand.php b/src/pocketmine/command/defaults/KillCommand.php index ec9a97fbd..92d42d708 100644 --- a/src/pocketmine/command/defaults/KillCommand.php +++ b/src/pocketmine/command/defaults/KillCommand.php @@ -21,10 +21,8 @@ namespace pocketmine\command\defaults; -use pocketmine\command\Command; use pocketmine\command\CommandSender; use pocketmine\Player; -use pocketmine\Server; use pocketmine\utils\TextFormat; class KillCommand extends VanillaCommand{ diff --git a/src/pocketmine/command/defaults/ReloadCommand.php b/src/pocketmine/command/defaults/ReloadCommand.php index 652f165f4..c87c85ed2 100644 --- a/src/pocketmine/command/defaults/ReloadCommand.php +++ b/src/pocketmine/command/defaults/ReloadCommand.php @@ -23,7 +23,6 @@ namespace pocketmine\command\defaults; use pocketmine\command\Command; use pocketmine\command\CommandSender; -use pocketmine\event\HandlerList; use pocketmine\Server; use pocketmine\utils\TextFormat; diff --git a/src/pocketmine/command/defaults/SetWorldSpawnCommand.php b/src/pocketmine/command/defaults/SetWorldSpawnCommand.php index 43a148999..10a4b4428 100644 --- a/src/pocketmine/command/defaults/SetWorldSpawnCommand.php +++ b/src/pocketmine/command/defaults/SetWorldSpawnCommand.php @@ -23,8 +23,6 @@ namespace pocketmine\command\defaults; use pocketmine\command\Command; use pocketmine\command\CommandSender; -use pocketmine\command\ConsoleCommandSender; -use pocketmine\level\Position; use pocketmine\math\Vector3; use pocketmine\Player; use pocketmine\Server; @@ -52,19 +50,22 @@ class SetWorldSpawnCommand extends VanillaCommand{ $pos = $sender->round(); }else{ $sender->sendMessage(TextFormat::RED . "You can only perform this command as a player"); + return true; } }elseif(count($args) === 3){ $level = Server::getInstance()->getDefaultLevel(); $pos = new Vector3($this->getInteger($sender, $args[0]), $this->getInteger($sender, $args[1]), $this->getInteger($sender, $args[2])); }else{ - $sender->sendMessage(TextFormat::RED . "Usage: ".$this->usageMessage); + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + return true; } $level->setSpawn($pos); - Command::broadcastCommandMessage($sender, "Set world ".$level->getName()."'s spawnpoint to ".$pos->x.", ".$pos->y.", ".$pos->z); + Command::broadcastCommandMessage($sender, "Set world " . $level->getName() . "'s spawnpoint to " . $pos->x . ", " . $pos->y . ", " . $pos->z); + return true; } } diff --git a/src/pocketmine/command/defaults/SpawnpointCommand.php b/src/pocketmine/command/defaults/SpawnpointCommand.php index dd47cfe32..08e45729e 100644 --- a/src/pocketmine/command/defaults/SpawnpointCommand.php +++ b/src/pocketmine/command/defaults/SpawnpointCommand.php @@ -51,12 +51,14 @@ class SpawnpointCommand extends VanillaCommand{ $target = $sender; }else{ $sender->sendMessage(TextFormat::RED . "Please provide a player!"); + return true; } }else{ $target = Server::getInstance()->getPlayer($args[0]); if($target === null){ - $sender->sendMessage(TextFormat::RED . "Can't find player ".$args[0]); + $sender->sendMessage(TextFormat::RED . "Can't find player " . $args[0]); + return true; } } @@ -69,22 +71,26 @@ class SpawnpointCommand extends VanillaCommand{ $y = (int) $this->getRelativeDouble($sender->y, $sender, $args[2], 0, 128); $z = (int) $this->getRelativeDouble($sender->z, $sender, $args[3]); $target->setSpawn(new Position($x, $y, $z, $level)); - Command::broadcastCommandMessage($sender, "Set ".$target->getName()."'s spawnpoint to ".$x.", ".$y.", ".$z); + Command::broadcastCommandMessage($sender, "Set " . $target->getName() . "'s spawnpoint to " . $x . ", " . $y . ", " . $z); + return true; } }elseif(count($args) <= 1){ - if($sender instanceof Player) { + if($sender instanceof Player){ $pos = new Position((int) $sender->x, (int) $sender->y, (int) $sender->z, $sender->getLevel()); $target->setSpawn($pos); - Command::broadcastCommandMessage($sender, "Set ".$target->getName()."'s spawnpoint to ".$pos->x.", ".$pos->y.", ".$pos->z); + Command::broadcastCommandMessage($sender, "Set " . $target->getName() . "'s spawnpoint to " . $pos->x . ", " . $pos->y . ", " . $pos->z); + return true; }else{ $sender->sendMessage(TextFormat::RED . "Please provide a player!"); + return true; } } - $sender->sendMessage(TextFormat::RED . "Usage: ".$this->usageMessage); + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + return true; } } diff --git a/src/pocketmine/command/defaults/StatusCommand.php b/src/pocketmine/command/defaults/StatusCommand.php index 83dfc8706..3f0ede59d 100644 --- a/src/pocketmine/command/defaults/StatusCommand.php +++ b/src/pocketmine/command/defaults/StatusCommand.php @@ -22,7 +22,6 @@ namespace pocketmine\command\defaults; use pocketmine\command\CommandSender; -use pocketmine\Player; use pocketmine\Server; use pocketmine\utils\TextFormat; @@ -43,11 +42,12 @@ class StatusCommand extends VanillaCommand{ } $server = Server::getInstance(); - $sender->sendMessage(TextFormat::GREEN . "---- ".TextFormat::WHITE . "Server status".TextFormat::GREEN. " ----"); - $sender->sendMessage(TextFormat::GOLD . "TPS: ".TextFormat::WHITE.$server->getTicksPerSecond()); - $sender->sendMessage(TextFormat::GOLD . "Upload: ".TextFormat::WHITE . round($server->getNetwork()->getUploadSpeed() / 1024, 2) . " kB/s"); - $sender->sendMessage(TextFormat::GOLD . "Download: ".TextFormat::WHITE . round($server->getNetwork()->getDownloadSpeed() / 1024, 2) . " kB/s"); - $sender->sendMessage(TextFormat::GOLD . "Memory: ".TextFormat::WHITE . round((memory_get_usage() / 1024) / 1024, 2) . TextFormat::YELLOW . "/" . TextFormat::WHITE . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB"); + $sender->sendMessage(TextFormat::GREEN . "---- " . TextFormat::WHITE . "Server status" . TextFormat::GREEN . " ----"); + $sender->sendMessage(TextFormat::GOLD . "TPS: " . TextFormat::WHITE . $server->getTicksPerSecond()); + $sender->sendMessage(TextFormat::GOLD . "Upload: " . TextFormat::WHITE . round($server->getNetwork()->getUploadSpeed() / 1024, 2) . " kB/s"); + $sender->sendMessage(TextFormat::GOLD . "Download: " . TextFormat::WHITE . round($server->getNetwork()->getDownloadSpeed() / 1024, 2) . " kB/s"); + $sender->sendMessage(TextFormat::GOLD . "Memory: " . TextFormat::WHITE . round((memory_get_usage() / 1024) / 1024, 2) . TextFormat::YELLOW . "/" . TextFormat::WHITE . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB"); + return true; } } \ No newline at end of file diff --git a/src/pocketmine/command/defaults/TeleportCommand.php b/src/pocketmine/command/defaults/TeleportCommand.php index 9b2acb93c..ca60ec49f 100644 --- a/src/pocketmine/command/defaults/TeleportCommand.php +++ b/src/pocketmine/command/defaults/TeleportCommand.php @@ -46,7 +46,8 @@ class TeleportCommand extends VanillaCommand{ } if(count($args) < 1 or count($args) > 4){ - $sender->sendMessage(TextFormat::RED . "Usage: ".$this->usageMessage); + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + return true; } @@ -58,19 +59,22 @@ class TeleportCommand extends VanillaCommand{ $target = $sender; }else{ $sender->sendMessage(TextFormat::RED . "Please provide a player!"); + return true; } }else{ $target = Server::getInstance()->getPlayer($args[0]); if($target === null){ - $sender->sendMessage(TextFormat::RED . "Can't find player ".$args[0]); + $sender->sendMessage(TextFormat::RED . "Can't find player " . $args[0]); + return true; } if(count($args) === 2){ $origin = $target; $target = Server::getInstance()->getPlayer($args[1]); if($target === null){ - $sender->sendMessage(TextFormat::RED . "Can't find player ".$args[1]); + $sender->sendMessage(TextFormat::RED . "Can't find player " . $args[1]); + return true; } } @@ -79,19 +83,22 @@ class TeleportCommand extends VanillaCommand{ if(count($args) < 3){ $pos = new Position($target->x, $target->y, $target->z, $target->getLevel()); $origin->teleport($pos); - Command::broadcastCommandMessage($sender, "Teleported ".$origin->getName()." to ".$target->getName()); + Command::broadcastCommandMessage($sender, "Teleported " . $origin->getName() . " to " . $target->getName()); + return true; }elseif($target->getLevel() !== null){ - $pos = count($args) === 4 ? 1:0; + $pos = count($args) === 4 ? 1 : 0; $x = $this->getRelativeDouble($target->x, $sender, $args[$pos++]); $y = $this->getRelativeDouble($target->y, $sender, $args[$pos++], 0, 128); $z = $this->getRelativeDouble($target->z, $sender, $args[$pos]); $target->teleport(new Vector3($x, $y, $z)); - Command::broadcastCommandMessage($sender, "Teleported ".$target->getName()." to ".round($x, 2).", ".round($y, 2).", ".round($z, 2)); + Command::broadcastCommandMessage($sender, "Teleported " . $target->getName() . " to " . round($x, 2) . ", " . round($y, 2) . ", " . round($z, 2)); + return true; } - $sender->sendMessage(TextFormat::RED . "Usage: ".$this->usageMessage); + $sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage); + return true; } } diff --git a/src/pocketmine/command/defaults/TimeCommand.php b/src/pocketmine/command/defaults/TimeCommand.php index 0aac0c5dd..65d13aa0d 100644 --- a/src/pocketmine/command/defaults/TimeCommand.php +++ b/src/pocketmine/command/defaults/TimeCommand.php @@ -6,7 +6,6 @@ use pocketmine\command\Command; use pocketmine\command\CommandSender; use pocketmine\Server; use pocketmine\utils\TextFormat; -use pocketmine\network\protocol\SetTimePacket; class TimeCommand extends VanillaCommand{ public function __construct($name){ @@ -17,20 +16,22 @@ class TimeCommand extends VanillaCommand{ ); $this->setPermission("pocketmine.command.time.add;pocketmine.command.set;"); } - + public function execute(CommandSender $sender, $label, array $args){ - if (count($args) < 2) { - $sender->sendMessage(TextFormat::RED."Incorrect usage. Correct usage:\n".$this->getUsage()); + if(count($args) < 2){ + $sender->sendMessage(TextFormat::RED . "Incorrect usage. Correct usage:\n" . $this->getUsage()); + return false; } - + switch(strtolower($args[0])){ case "set": if(!$sender->hasPermission("pocketmine.command.time.add")){ - $sender->sendMessage(TextFormat::RED."You don't have permission to set the time"); + $sender->sendMessage(TextFormat::RED . "You don't have permission to set the time"); + return true; } - + if($args[1] === "day"){ $value = 0; }elseif($args[1] === "night"){ @@ -38,30 +39,31 @@ class TimeCommand extends VanillaCommand{ }else{ $value = $this->getInteger($sender, $args[1], 0); } - + foreach(Server::getInstance()->getLevels() as $level){ $level->setTime($value); } - Command::broadcastCommandMessage($sender, "Set time to ".$value); - - return true; + Command::broadcastCommandMessage($sender, "Set time to " . $value); + + return true; case "add": - if (!$sender->hasPermission("pocketmine.command.time.add")){ - $sender->sendMessage(TextFormat::RED."You don't have permission to set the time"); + if(!$sender->hasPermission("pocketmine.command.time.add")){ + $sender->sendMessage(TextFormat::RED . "You don't have permission to set the time"); + return true; } $value = $this->getInteger($sender, $args[1], 0); - + foreach(Server::getInstance()->getLevels() as $level){ $level->setTime($level->getTime() + $value); } - - Command::broadcastCommandMessage($sender, "Added ".$value." to time"); - - return true; + + Command::broadcastCommandMessage($sender, "Added " . $value . " to time"); + + return true; default: - $sender->sendMessage("Unknown method. Usage: ".$this->getUsage()); + $sender->sendMessage("Unknown method. Usage: " . $this->getUsage()); } } } \ No newline at end of file diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index d34a6e3fb..ee6c461bb 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -29,6 +29,7 @@ use pocketmine\event\entity\EntityLevelChangeEvent; use pocketmine\event\entity\EntityMotionEvent; use pocketmine\event\entity\EntityMoveEvent; use pocketmine\event\entity\EntitySpawnEvent; +use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\Level; use pocketmine\level\Position; use pocketmine\math\AxisAlignedBB; @@ -36,14 +37,13 @@ use pocketmine\math\Vector3 as Vector3; use pocketmine\metadata\Metadatable; use pocketmine\metadata\MetadataValue; use pocketmine\nbt\tag\Compound; +use pocketmine\Network; use pocketmine\network\protocol\MoveEntityPacket_PosRot; use pocketmine\network\protocol\MovePlayerPacket; use pocketmine\network\protocol\RemoveEntityPacket; use pocketmine\network\protocol\SetEntityMotionPacket; use pocketmine\network\protocol\SetTimePacket; -use pocketmine\Network; use pocketmine\Player; -use pocketmine\level\format\pmf\LevelFormat; use pocketmine\plugin\Plugin; use pocketmine\Server; @@ -176,6 +176,10 @@ abstract class Entity extends Position implements Metadatable{ protected abstract function initEntity(); + public function getViewers(){ + return $this->hasSpawned; + } + public function spawnTo(Player $player){ if(!isset($this->hasSpawned[$player->getID()]) and $player->chunksLoaded[$this->chunkIndex] !== 0xff){ $this->hasSpawned[$player->getID()] = $player; diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 476f9985f..65d9896af 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -21,54 +21,46 @@ namespace pocketmine\entity; -use pocketmine\event\entity\EntityArmorChangeEvent; -use pocketmine\event\entity\EntityInventoryChangeEvent; +use pocketmine\inventory\InventoryHolder; +use pocketmine\inventory\PlayerInventory; use pocketmine\item\Item; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\Byte; use pocketmine\nbt\tag\Compound; use pocketmine\nbt\tag\Enum; use pocketmine\nbt\tag\Short; +use pocketmine\Network; use pocketmine\network\protocol\AddPlayerPacket; -use pocketmine\network\protocol\ContainerSetContentPacket; -use pocketmine\network\protocol\PlayerArmorEquipmentPacket; -use pocketmine\network\protocol\PlayerEquipmentPacket; use pocketmine\network\protocol\RemovePlayerPacket; use pocketmine\network\protocol\SetEntityMotionPacket; -use pocketmine\Network; use pocketmine\Player; -use pocketmine\Server; -class Human extends Creature implements ProjectileSource, InventorySource{ +class Human extends Creature implements ProjectileSource, InventoryHolder{ protected $nameTag = "TESTIFICATE"; - protected $inventory = []; - public $slot; - protected $hotbar = []; - protected $armor = []; + /** @var PlayerInventory */ + protected $inventory; + + public function getInventory(){ + return $this->inventory; + } protected function initEntity(){ + $this->inventory = new PlayerInventory($this); + if(isset($this->namedtag->NameTag)){ $this->nameTag = $this->namedtag["NameTag"]; } - $this->hotbar = array(-1, -1, -1, -1, -1, -1, -1, -1, -1); - $this->armor = array( - 0 => Item::get(Item::AIR, 0, 0), - 1 => Item::get(Item::AIR, 0, 0), - 2 => Item::get(Item::AIR, 0, 0), - 3 => Item::get(Item::AIR, 0, 0) - ); foreach($this->namedtag->Inventory as $item){ if($item["Slot"] >= 0 and $item["Slot"] < 9){ //Hotbar - $this->hotbar[$item["Slot"]] = isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1; + $this->inventory->setHotbarSlotIndex($item["Slot"], isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1); }elseif($item["Slot"] >= 100 and $item["Slot"] < 104){ //Armor - $this->armor[$item["Slot"] - 100] = Item::get($item["id"], $item["Damage"], $item["Count"]); + $this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, Item::get($item["id"], $item["Damage"], $item["Count"])); }else{ - $this->inventory[$item["Slot"] - 9] = Item::get($item["id"], $item["Damage"], $item["Count"]); + $this->inventory->setItem($item["Slot"] - 9, Item::get($item["id"], $item["Damage"], $item["Count"])); } } - $this->slot = $this->hotbar[0]; $this->height = 1.8; //Or 1.62? $this->width = 0.6; @@ -79,14 +71,15 @@ class Human extends Creature implements ProjectileSource, InventorySource{ $this->namedtag->Inventory = new Enum("Inventory", []); $this->namedtag->Inventory->setTagType(NBT::TAG_Compound); for($slot = 0; $slot < 9; ++$slot){ - if(isset($this->hotbar[$slot]) and $this->hotbar[$slot] !== -1){ - $item = $this->getSlot($this->hotbar[$slot]); + $hotbarSlot = $this->inventory->getHotbarSlotIndex($slot); + if($hotbarSlot !== -1){ + $item = $this->inventory->getItem($hotbarSlot); if($item->getID() !== 0 and $item->getCount() > 0){ $this->namedtag->Inventory[$slot] = new Compound(false, array( new Byte("Count", $item->getCount()), new Short("Damage", $item->getDamage()), new Byte("Slot", $slot), - new Byte("TrueSlot", $this->hotbar[$slot]), + new Byte("TrueSlot", $hotbarSlot), new Short("id", $item->getID()), )); continue; @@ -105,7 +98,7 @@ class Human extends Creature implements ProjectileSource, InventorySource{ $slotCount = Player::SURVIVAL_SLOTS + 9; //$slotCount = (($this instanceof Player and ($this->gamemode & 0x01) === 1) ? Player::CREATIVE_SLOTS : Player::SURVIVAL_SLOTS) + 9; for($slot = 9; $slot < $slotCount; ++$slot){ - $item = $this->getSlot($slot - 9); + $item = $this->inventory->getItem($slot - 9); $this->namedtag->Inventory[$slot] = new Compound(false, array( new Byte("Count", $item->getCount()), new Short("Damage", $item->getDamage()), @@ -116,8 +109,8 @@ class Human extends Creature implements ProjectileSource, InventorySource{ //Armor for($slot = 100; $slot < 104; ++$slot){ - $item = $this->armor[$slot - 100]; - if($item instanceof Item){ + $item = $this->inventory->getItem($this->inventory->getSize() + $slot - 100); + if($item instanceof Item and $item->getID() !== Item::AIR){ $this->namedtag->Inventory[$slot] = new Compound(false, array( new Byte("Count", $item->getCount()), new Short("Damage", $item->getDamage()), @@ -135,7 +128,7 @@ class Human extends Creature implements ProjectileSource, InventorySource{ $pk = new AddPlayerPacket; $pk->clientID = 0; $pk->username = $this->nameTag; - $pk->eid = $this->id; + $pk->eid = $this->getID(); $pk->x = $this->x; $pk->y = $this->y; $pk->z = $this->z; @@ -147,15 +140,15 @@ class Human extends Creature implements ProjectileSource, InventorySource{ $player->dataPacket($pk); $pk = new SetEntityMotionPacket; - $pk->eid = $this->id; + $pk->eid = $this->getID(); $pk->speedX = $this->motionX; $pk->speedY = $this->motionY; $pk->speedZ = $this->motionZ; $player->dataPacket($pk); - $this->sendCurrentEquipmentSlot($player); + $this->inventory->sendHeldItem($player); - $this->sendArmor($player); + $this->inventory->sendArmorContents($player); } } @@ -169,104 +162,6 @@ class Human extends Creature implements ProjectileSource, InventorySource{ } } - public function setEquipmentSlot($equipmentSlot, $inventorySlot){ - $this->hotbar[$equipmentSlot] = $inventorySlot; - if($equipmentSlot === $this->slot){ - foreach($this->hasSpawned as $p){ - $this->sendCurrentEquipmentSlot($p); - } - } - } - - public function getEquipmentSlot($equipmentSlot){ - if(isset($this->hotbar[$equipmentSlot])){ - return $this->hotbar[$equipmentSlot]; - } - - return -1; - } - - public function setCurrentEquipmentSlot($slot){ - if(isset($this->hotbar[$slot])){ - $this->slot = (int) $slot; - foreach($this->hasSpawned as $p){ - $this->sendCurrentEquipmentSlot($p); - } - } - } - - public function getCurrentEquipmentSlot(){ - return $this->slot; - } - - public function getCurrentEquipment(){ - if($this->slot > -1) { - return $this->hotbar[$this->slot]; - } - } - - public function sendCurrentEquipmentSlot(Player $player){ - $pk = new PlayerEquipmentPacket; - $pk->eid = $this->id; - $pk->item = $this->getSlot($this->slot)->getID(); - $pk->meta = $this->getSlot($this->slot)->getDamage(); - $pk->slot = 0; - $player->dataPacket($pk); - } - - public function setArmorSlot($slot, Item $item){ - Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this, $this->getArmorSlot($slot), $item, $slot)); - if($ev->isCancelled()){ - return false; - } - $this->armor[(int) $slot] = $ev->getNewItem(); - foreach($this->hasSpawned as $p){ - $this->sendArmor($p); - } - if($this instanceof Player){ - $this->sendArmor(); - } - - return true; - } - - /** - * @param int $slot - * - * @return Item - */ - public function getArmorSlot($slot){ - $slot = (int) $slot; - if(!isset($this->armor[$slot])){ - $this->armor[$slot] = Item::get(Item::AIR, 0, 0); - } - - return $this->armor[$slot]; - } - - public function sendArmor($player = null){ - $slots = []; - for($i = 0; $i < 4; ++$i){ - if(isset($this->armor[$i]) and ($this->armor[$i] instanceof Item) and $this->armor[$i]->getID() > Item::AIR){ - $slots[$i] = $this->armor[$i]->getID() !== Item::AIR ? $this->armor[$i]->getID() - 256 : 0; - }else{ - $this->armor[$i] = Item::get(Item::AIR, 0, 0); - $slots[$i] = 255; - } - } - if($player instanceof Player){ - $pk = new PlayerArmorEquipmentPacket(); - $pk->eid = $this->id; - $pk->slots = $slots; - $player->dataPacket($pk); - }elseif($this instanceof Player){ - $pk = new ContainerSetContentPacket; - $pk->windowid = 0x78; //Armor window id - $pk->slots = $this->armor; - $this->dataPacket($pk); - } - } - public function getData(){ //TODO $flags = 0; $flags |= $this->fireTicks > 0 ? 1 : 0; @@ -305,132 +200,4 @@ class Human extends Creature implements ProjectileSource, InventorySource{ } - public function hasItem(Item $item, $checkDamage = true){ - foreach($this->inventory as $s => $i){ - if($i->equals($item, $checkDamage)){ - return $i; - } - } - - return false; - } - - public function canAddItem(Item $item){ - $inv = $this->inventory; - while($item->getCount() > 0){ - $add = 0; - foreach($inv as $s => $i){ - if($i->getID() === Item::AIR){ - $add = min($i->getMaxStackSize(), $item->getCount()); - $inv[$s] = clone $item; - $inv[$s]->setCount($add); - break; - }elseif($i->equals($item)){ - $add = min($i->getMaxStackSize() - $i->getCount(), $item->getCount()); - if($add <= 0){ - continue; - } - $inv[$s] = clone $item; - $inv[$s]->setCount($i->getCount() + $add); - break; - } - } - if($add <= 0){ - return false; - } - $item->setCount($item->getCount() - $add); - } - - return true; - } - - public function addItem(Item $item){ - while($item->getCount() > 0){ - $add = 0; - foreach($this->inventory as $s => $i){ - if($i->getID() === Item::AIR){ - $add = min($i->getMaxStackSize(), $item->getCount()); - $i2 = clone $item; - $i2->setCount($add); - $this->setSlot($s, $i2); - break; - }elseif($i->equals($item)){ - $add = min($i->getMaxStackSize() - $i->getCount(), $item->getCount()); - if($add <= 0){ - continue; - } - $i2 = clone $item; - $i2->setCount($i->getCount() + $add); - $this->setSlot($s, $i2); - break; - } - } - if($add <= 0){ - return false; - } - $item->setCount($item->getCount() - $add); - } - - return true; - } - - public function canRemoveItem(Item $item, $checkDamage = true){ - return $this->hasItem($item, $checkDamage); - } - - public function removeItem(Item $item, $checkDamage = true){ - while($item->getCount() > 0){ - $remove = 0; - foreach($this->inventory as $s => $i){ - if($i->equals($item, $checkDamage)){ - $remove = min($item->getCount(), $i->getCount()); - if($item->getCount() < $i->getCount()){ - $i->setCount($i->getCount() - $item->getCount()); - $this->setSlot($s, $i); - }else{ - $this->setSlot($s, Item::get(Item::AIR, 0, 0)); - } - break; - } - } - if($remove <= 0){ - return false; - } - $item->setCount($item->getCount() - $remove); - } - - return true; - } - - public function setSlot($slot, Item $item){ - Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($this, $this->getSlot($slot), $item, $slot)); - if($ev->isCancelled()){ - return false; - } - $this->inventory[(int) $slot] = $ev->getNewItem(); - - return true; - } - - /** - * @param int $slot - * - * @return Item - */ - public function getSlot($slot){ - $slot = (int) $slot; - if(!isset($this->inventory[$slot])){ - $this->inventory[$slot] = Item::get(Item::AIR, 0, 0); - } - - return $this->inventory[$slot]; - } - - public function getAllSlots(){ - return $this->inventory; - } - - public function getSlotCount(){ - return count($this->inventory); - } } diff --git a/src/pocketmine/event/player/PlayerItemHeldEvent.php b/src/pocketmine/event/player/PlayerItemHeldEvent.php index 2802e5492..fb359ecb5 100644 --- a/src/pocketmine/event/player/PlayerItemHeldEvent.php +++ b/src/pocketmine/event/player/PlayerItemHeldEvent.php @@ -21,8 +21,8 @@ namespace pocketmine\event\player; -use pocketmine\event\Cancellable; use pocketmine\Event; +use pocketmine\event\Cancellable; use pocketmine\item\Item; use pocketmine\Player; diff --git a/src/pocketmine/event/server/DataPacketReceiveEvent.php b/src/pocketmine/event/server/DataPacketReceiveEvent.php index b8bc6392a..7de47696c 100644 --- a/src/pocketmine/event/server/DataPacketReceiveEvent.php +++ b/src/pocketmine/event/server/DataPacketReceiveEvent.php @@ -21,8 +21,8 @@ namespace pocketmine\event\server; -use pocketmine\event; use pocketmine\event\Cancellable; +use pocketmine\event; use pocketmine\network\protocol\DataPacket; use pocketmine\Player; diff --git a/src/pocketmine/event/server/DataPacketSendEvent.php b/src/pocketmine/event/server/DataPacketSendEvent.php index eefaa0ee7..805354abb 100644 --- a/src/pocketmine/event/server/DataPacketSendEvent.php +++ b/src/pocketmine/event/server/DataPacketSendEvent.php @@ -21,8 +21,8 @@ namespace pocketmine\event\server; -use pocketmine\event; use pocketmine\event\Cancellable; +use pocketmine\event; use pocketmine\network\protocol\DataPacket; use pocketmine\Player; diff --git a/src/pocketmine/event/tile/TileEvent.php b/src/pocketmine/event/tile/TileEvent.php deleted file mode 100644 index 5ac9eab6e..000000000 --- a/src/pocketmine/event/tile/TileEvent.php +++ /dev/null @@ -1,35 +0,0 @@ -tile; - } -} \ No newline at end of file diff --git a/src/pocketmine/event/tile/TileInventoryChangeEvent.php b/src/pocketmine/event/tile/TileInventoryChangeEvent.php deleted file mode 100644 index 30d7c21e1..000000000 --- a/src/pocketmine/event/tile/TileInventoryChangeEvent.php +++ /dev/null @@ -1,60 +0,0 @@ -tile = $tile; - $this->oldItem = $oldItem; - $this->newItem = $newItem; - $this->slot = (int) $slot; - } - - public function getSlot(){ - return $this->slot; - } - - public function getNewItem(){ - return $this->newItem; - } - - public function setNewItem(Item $item){ - $this->newItem = $item; - } - - public function getOldItem(){ - return $this->oldItem; - } - - -} \ No newline at end of file diff --git a/src/pocketmine/inventory/BaseInventory.php b/src/pocketmine/inventory/BaseInventory.php index 681b42e86..746eada30 100644 --- a/src/pocketmine/inventory/BaseInventory.php +++ b/src/pocketmine/inventory/BaseInventory.php @@ -21,9 +21,13 @@ namespace pocketmine\inventory; +use pocketmine\entity\Entity; +use pocketmine\event\entity\EntityInventoryChangeEvent; +use pocketmine\item\Item; +use pocketmine\network\protocol\ContainerSetContentPacket; use pocketmine\network\protocol\ContainerSetSlotPacket; use pocketmine\Player; -use pocketmine\item\Item; +use pocketmine\Server; abstract class BaseInventory implements Inventory{ @@ -57,7 +61,7 @@ abstract class BaseInventory implements Inventory{ //A holder can be a plugin, or an entity if($this->holder instanceof Player){ - $this->viewers->attach($this->holder); + $this->holder->addWindow($this, 0); } @@ -123,18 +127,34 @@ abstract class BaseInventory implements Inventory{ } public function setItem($index, Item $item){ - if($index < 0 or $index >= $this->size or $item->getID() === 0){ - return; + if($index < 0 or $index >= $this->size){ + return false; + }elseif($item->getID() === 0){ + $this->clear($index); } + + $holder = $this->getHolder(); + if($holder instanceof Entity){ + Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($holder, $this->getItem($index), $item, $index)); + if($ev->isCancelled()){ + $this->sendContents($this->getViewers()); + + return false; + } + $item = $ev->getNewItem(); + } + $old = $this->slots[$index]; $this->slots[$index] = clone $item; $this->onSlotChange($index, $old); + + return true; } public function contains(Item $item){ $count = max(1, $item->getCount()); $checkDamage = $item->getDamage() === null ? false : true; - foreach($this->slots as $i){ + foreach($this->getContents() as $i){ if($item->equals($i, $checkDamage)){ $count -= $i->getCount(); if($count <= 0){ @@ -149,7 +169,7 @@ abstract class BaseInventory implements Inventory{ public function all(Item $item){ $slots = []; $checkDamage = $item->getDamage() === null ? false : true; - foreach($this->slots as $index => $i){ + foreach($this->getContents() as $index => $i){ if($item->equals($i, $checkDamage)){ $slots[$index] = $i; } @@ -160,7 +180,7 @@ abstract class BaseInventory implements Inventory{ public function remove(Item $item){ $checkDamage = $item->getDamage() === null ? false : true; - foreach($this->slots as $index => $i){ + foreach($this->getContents() as $index => $i){ if($item->equals($i, $checkDamage)){ $this->clear($index); } @@ -170,7 +190,7 @@ abstract class BaseInventory implements Inventory{ public function first(Item $item){ $count = max(1, $item->getCount()); $checkDamage = $item->getDamage() === null ? false : true; - foreach($this->slots as $index => $i){ + foreach($this->getContents() as $index => $i){ if($item->equals($i, $checkDamage) and $i->getCount() >= $count){ return $index; } @@ -181,10 +201,7 @@ abstract class BaseInventory implements Inventory{ public function firstEmpty(){ for($i = 0; $i < $this->size; ++$i){ - if(!isset($this->slots[$i])){ - return $i; - }elseif(!($this->slots[$i] instanceof Item) or $this->slots[$i]->getID() === 0 or $this->slots[$i]->getCount() <= 0){ - unset($this->slots[$i]); + if($this->getItem($i)->getID() === Item::AIR){ return $i; } } @@ -196,11 +213,10 @@ abstract class BaseInventory implements Inventory{ /** @var Item[] $slots */ $slots = func_get_args(); for($i = 0; $i < $this->size; ++$i){ - if(!isset($this->slots[$i])){ - $item = $this->slots[$i] = array_shift($slots); - $this->onSlotChange($i, null); - }else{ - $item = $this->slots[$i]; + $item = $this->getItem($i); + if($item->getID() === Item::AIR){ + $item = array_shift($slots); + $this->setItem($i, $item); } foreach($slots as $index => $slot){ @@ -230,10 +246,9 @@ abstract class BaseInventory implements Inventory{ /** @var Item[] $slots */ $slots = func_get_args(); for($i = 0; $i < $this->size; ++$i){ - if(!isset($this->slots[$i])){ + $item = $this->getItem($i); + if($item->getID() === Item::AIR){ continue; - }else{ - $item = $this->slots[$i]; } foreach($slots as $index => $slot){ @@ -263,14 +278,32 @@ abstract class BaseInventory implements Inventory{ public function clear($index){ if(isset($this->slots[$index])){ + $item = Item::get(Item::AIR, null, 0); $old = $this->slots[$index]; - unset($this->slots[$index]); + $holder = $this->getHolder(); + if($holder instanceof Entity){ + Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($holder, $old, $item, $index)); + if($ev->isCancelled()){ + $this->sendContents($this->getViewers()); + + return false; + } + $item = $ev->getNewItem(); + } + if($item->getID() !== Item::AIR){ + $this->slots[$index] = clone $item; + }else{ + unset($this->slots[$index]); + } + $this->onSlotChange($index, $old); } + + return true; } public function clearAll(){ - foreach($this->slots as $index => $i){ + foreach($this->getContents() as $index => $i){ $this->clear($index); } } @@ -280,6 +313,7 @@ abstract class BaseInventory implements Inventory{ foreach($this->viewers as $viewer){ $viewers[] = $viewer; } + return $viewers; } @@ -300,12 +334,44 @@ abstract class BaseInventory implements Inventory{ } public function onSlotChange($index, $before){ + $this->sendSlot($index, $this->getViewers()); + } + + + /** + * @param Player|Player[] $target + */ + public function sendContents($target){ + if($target instanceof Player){ + $target = [$target]; + } + + $pk = new ContainerSetContentPacket(); + $pk->slots = []; + for($i = 0; $i < $this->getSize(); ++$i){ + $pk->slots[$i] = $this->getItem($i); + } + + foreach($target as $player){ + $pk->windowid = $player->getWindowId($this); + $player->dataPacket(clone $pk); + } + } + + /** + * @param int $index + * @param Player|Player[] $target + */ + public function sendSlot($index, $target){ + if($target instanceof Player){ + $target = [$target]; + } + $pk = new ContainerSetSlotPacket; $pk->slot = $index; $pk->item = clone $this->getItem($index); - /** @var Player $player */ - foreach($this->getViewers() as $player){ + foreach($target as $player){ $pk->windowid = $player->getWindowId($this); $player->dataPacket(clone $pk); } diff --git a/src/pocketmine/inventory/ChestInventory.php b/src/pocketmine/inventory/ChestInventory.php new file mode 100644 index 000000000..f44edd101 --- /dev/null +++ b/src/pocketmine/inventory/ChestInventory.php @@ -0,0 +1,67 @@ +holder; + } + + public function onOpen(Player $who){ + parent::onOpen($who); + + if(count($this->getViewers()) === 1){ + $pk = new TileEventPacket; + $pk->x = $this->getHolder()->getX(); + $pk->y = $this->getHolder()->getY(); + $pk->z = $this->getHolder()->getZ(); + $pk->case1 = 1; + $pk->case2 = 2; + Player::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk); + } + } + + public function onClose(Player $who){ + parent::onClose($who); + + if(count($this->getViewers()) === 1){ + $pk = new TileEventPacket; + $pk->x = $this->getHolder()->getX(); + $pk->y = $this->getHolder()->getY(); + $pk->z = $this->getHolder()->getZ(); + $pk->case1 = 1; + $pk->case2 = 0; + Player::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk); + } + } +} \ No newline at end of file diff --git a/src/pocketmine/inventory/ContainerInventory.php b/src/pocketmine/inventory/ContainerInventory.php new file mode 100644 index 000000000..907db93fb --- /dev/null +++ b/src/pocketmine/inventory/ContainerInventory.php @@ -0,0 +1,55 @@ +holder; + } + + public function onOpen(Player $who){ + $pk = new ContainerOpenPacket; + $pk->windowid = $who->getWindowId($this); + $pk->type = 0; + $pk->slots = $this->getSize(); + $pk->x = $this->getHolder()->getX(); + $pk->y = $this->getHolder()->getY(); + $pk->z = $this->getHolder()->getZ(); + $who->dataPacket($pk); + } + + public function onClose(Player $who){ + $pk = new ContainerClosePacket; + $pk->windowid = $who->getWindowId($this); + $who->dataPacket($pk); + } +} \ No newline at end of file diff --git a/src/pocketmine/inventory/DoubleChestInventory.php b/src/pocketmine/inventory/DoubleChestInventory.php new file mode 100644 index 000000000..b52765761 --- /dev/null +++ b/src/pocketmine/inventory/DoubleChestInventory.php @@ -0,0 +1,101 @@ +left = $left->getRealInventory(); + $this->right = $right->getRealInventory(); + BaseInventory::__construct($this, InventoryType::get(InventoryType::DOUBLE_CHEST)); + } + + //TODO + public function getInventory(){ + return $this; + } + + //TODO + public function getHolder(){ + return $this->left; + } + + public function getItem($index){ + return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->right->getSize()); + } + + public function setItem($index, Item $item){ + return $index < $this->left->getSize() ? $this->left->setItem($index, $item) : $this->right->setItem($index - $this->right->getSize(), $item); + } + + public function clear($index){ + return $index < $this->left->getSize() ? $this->left->clear($index) : $this->right->clear($index - $this->right->getSize()); + } + + public function getContents(){ + $contents = []; + for($i = 0; $i < $this->getSize(); ++$i){ + $contents[$i] = $this->getItem($i); + } + + return $contents; + } + + /** + * @param Item[] $items + */ + public function setContents(array $items){ + if(count($items) > $this->size){ + $items = array_slice($items, 0, $this->size, true); + } + + parent::setContents($items); + + $leftItems = array_slice($items, 0, $this->left->getSize(), true); + $this->left->setContents($leftItems); + if(count($items) > $this->left->getSize()){ + $rightItems = array_slice($items, $this->left->getSize() - 1, $this->right->getSize(), true); + $this->right->setContents($rightItems); + } + } + + /** + * @return ChestInventory + */ + public function getLeftSide(){ + return $this->left; + } + + /** + * @return ChestInventory + */ + public function getRightSide(){ + return $this->right; + } +} \ No newline at end of file diff --git a/src/pocketmine/inventory/FurnaceInventory.php b/src/pocketmine/inventory/FurnaceInventory.php new file mode 100644 index 000000000..7c6219b4e --- /dev/null +++ b/src/pocketmine/inventory/FurnaceInventory.php @@ -0,0 +1,92 @@ +holder; + } + + /** + * @return Item + */ + public function getResult(){ + return $this->getItem(2); + } + + /** + * @return Item + */ + public function getFuel(){ + return $this->getItem(1); + } + + /** + * @return Item + */ + public function getSmelting(){ + return $this->getItem(0); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setResult(Item $item){ + return $this->setItem(2, $item); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setFuel(Item $item){ + return $this->setItem(1, $item); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setSmelting(Item $item){ + return $this->setItem(0, $item); + } + + public function onSlotChange($index, $before){ + parent::onSlotChange($index, $before); + //TODO: implement Furnace scheduled update + } +} \ No newline at end of file diff --git a/src/pocketmine/inventory/Inventory.php b/src/pocketmine/inventory/Inventory.php index d602a5974..69819acfc 100644 --- a/src/pocketmine/inventory/Inventory.php +++ b/src/pocketmine/inventory/Inventory.php @@ -50,6 +50,15 @@ interface Inventory{ */ public function getItem($index); + /** + * Puts an Item in a slot. + * If a plugin refuses the update or $index is invalid, it'll return false + * + * @param int $index + * @param Item $item + * + * @return bool + */ public function setItem($index, Item $item); /** @@ -127,6 +136,8 @@ interface Inventory{ * Will clear a specific slot * * @param int $index + * + * @return bool */ public function clear($index); @@ -164,7 +175,7 @@ interface Inventory{ public function onClose(Player $who); /** - * @param int $index + * @param int $index * @param Item|null $before */ public function onSlotChange($index, $before); diff --git a/src/pocketmine/inventory/InventoryType.php b/src/pocketmine/inventory/InventoryType.php index 0904de1a1..e10b50ec9 100644 --- a/src/pocketmine/inventory/InventoryType.php +++ b/src/pocketmine/inventory/InventoryType.php @@ -26,10 +26,11 @@ namespace pocketmine\inventory; */ class InventoryType{ const CHEST = 0; - const PLAYER = 1; - const FURNACE = 2; - const CRAFTING = 3; - const WORKBENCH = 4; + const DOUBLE_CHEST = 1; + const PLAYER = 2; + const FURNACE = 3; + const CRAFTING = 4; + const WORKBENCH = 5; private static $default = []; @@ -46,6 +47,7 @@ class InventoryType{ } static::$default[static::CHEST] = new InventoryType(27, "Chest"); + static::$default[static::DOUBLE_CHEST] = new InventoryType(27 + 27, "Double Chest"); static::$default[static::PLAYER] = new InventoryType(31, "Player"); //27 CONTAINER, 4 ARMOR (9 reference HOTBAR slots) static::$default[static::FURNACE] = new InventoryType(3, "Furnace"); static::$default[static::CRAFTING] = new InventoryType(5, "Crafting"); //4 CRAFTING slots, 1 RESULT @@ -53,7 +55,7 @@ class InventoryType{ } /** - * @param int $defaultSize + * @param int $defaultSize * @param string $defaultTitle */ private function __construct($defaultSize, $defaultTitle){ diff --git a/src/pocketmine/inventory/PlayerInventory.php b/src/pocketmine/inventory/PlayerInventory.php index 306eb8d82..ad78d5f27 100644 --- a/src/pocketmine/inventory/PlayerInventory.php +++ b/src/pocketmine/inventory/PlayerInventory.php @@ -22,11 +22,15 @@ namespace pocketmine\inventory; use pocketmine\entity\Human; +use pocketmine\event\entity\EntityArmorChangeEvent; +use pocketmine\event\player\PlayerItemHeldEvent; use pocketmine\item\Item; use pocketmine\network\protocol\ContainerSetContentPacket; +use pocketmine\network\protocol\ContainerSetSlotPacket; use pocketmine\network\protocol\PlayerArmorEquipmentPacket; use pocketmine\network\protocol\PlayerEquipmentPacket; use pocketmine\Player; +use pocketmine\Server; class PlayerInventory extends BaseInventory{ @@ -83,8 +87,13 @@ class PlayerInventory extends BaseInventory{ } } + /** + * @param Item $item + * + * @return bool + */ public function setItemInHand(Item $item){ - $this->setItem($this->getHeldItemSlot(), $item); + return $this->setItem($this->getHeldItemSlot(), $item); } public function getHeldItemSlot(){ @@ -93,16 +102,47 @@ class PlayerInventory extends BaseInventory{ public function setHeldItemSlot($slot){ if($slot >= 0 and $slot < $this->getSize()){ + $item = $this->getItem($slot); + if($this->getHolder() instanceof Player){ + Server::getInstance()->getPluginManager()->callEvent($ev = new PlayerItemHeldEvent($this->getHolder(), $item, $slot, 0)); + if($ev->isCancelled()){ + $this->sendHeldItem($this->getHolder()); + + return; + } + } + $this->setHotbarSlotIndex($this->itemInHandIndex, $slot); - $item = $this->getItemInHand(); + $this->sendHeldItem($this->getHolder()->getViewers()); - $pk = new PlayerEquipmentPacket; - $pk->eid = $this->getHolder()->getID(); - $pk->item = $item->getID(); - $pk->meta = $item->getDamage(); - $pk->slot = 0; + if($this->getHolder() instanceof Player){ + $this->sendHeldItem($this->getHolder()); + } + } + } - foreach($this->getHolder()->getViewers() as $player){ + /** + * @param Player|Player[] $target + */ + public function sendHeldItem($target){ + if($target instanceof Player){ + $target = [$target]; + } + + $item = $this->getItemInHand(); + + $pk = new PlayerEquipmentPacket; + $pk->eid = $this->getHolder()->getID(); + $pk->item = $item->getID(); + $pk->meta = $item->getDamage(); + $pk->slot = 0; + + foreach($target as $player){ + if($player === $this->getHolder()){ + //TODO: Check if Mojang enabled sending a single slot this + //$this->sendSlot($this->getHeldItemSlot()); + $this->sendContents($this->getHolder()); + }else{ $player->dataPacket(clone $pk); } } @@ -112,34 +152,11 @@ class PlayerInventory extends BaseInventory{ parent::onSlotChange($index, $before); if($index >= $this->getSize()){ - $armor = $this->getArmorContents(); - $slots = []; + $this->sendArmorContents($this->getHolder()->getViewers()); + } - foreach($armor as $i => $slot){ - if($slot->getID() === Item::AIR){ - $slots[$i] = 255; - }else{ - $slots[$i] = $slot->getID(); - } - } - - $pk = new PlayerArmorEquipmentPacket; - $pk->eid = $this->getHolder()->getID(); - $pk->slots = $slots; - - if($index >= $this->getSize()){ //Armor change - foreach($this->getHolder()->getViewers() as $player){ - if($player === $this->getHolder()){ - /** @var Player $player */ - $pk2 = new ContainerSetContentPacket; - $pk2->windowid = 0x78; //Armor window id constant - $pk2->slots = $armor; - $player->dataPacket($pk2); - }else{ - $player->dataPacket(clone $pk); - } - } - } + if($this->getHolder() instanceof Player){ + $this->sendArmorContents($this->getHolder()); } } @@ -147,6 +164,14 @@ class PlayerInventory extends BaseInventory{ return 9; } + public function getArmorItem($index){ + return $this->getItem($this->getSize() + $index); + } + + public function setArmorItem($index, Item $item){ + return $this->setItem($this->getSize() + $index, $item); + } + public function getHelmet(){ return $this->getItem($this->getSize() + 3); } @@ -164,19 +189,66 @@ class PlayerInventory extends BaseInventory{ } public function setHelmet(Item $helmet){ - $this->setItem($this->getSize() + 3, $helmet); + return $this->setItem($this->getSize() + 3, $helmet); } public function setChestplate(Item $chestplate){ - $this->setItem($this->getSize() + 2, $chestplate); + return $this->setItem($this->getSize() + 2, $chestplate); } public function setLeggings(Item $leggings){ - $this->setItem($this->getSize() + 1, $leggings); + return $this->setItem($this->getSize() + 1, $leggings); } public function setBoots(Item $boots){ - $this->setItem($this->getSize(), $boots); + return $this->setItem($this->getSize(), $boots); + } + + public function setItem($index, Item $item){ + if($index < 0 or $index >= $this->size){ + return false; + } + + if($index >= $this->getSize()){ //Armor change + Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $item, $index)); + if($ev->isCancelled()){ + $this->sendArmorContents($this); + $this->sendContents($this); + + return false; + } + $item = $ev->getNewItem(); + } + + $old = $this->slots[$index]; + $this->slots[$index] = clone $item; + $this->onSlotChange($index, $old); + + return true; + } + + public function clear($index){ + if(isset($this->slots[$index])){ + $item = Item::get(Item::AIR, null, 0); + $old = $this->slots[$index]; + if($index >= $this->getSize() and $index < $this->size){ //Armor change + Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $old, $item, $index)); + if($ev->isCancelled()){ + $this->sendArmorContents($this); + $this->sendContents($this); + + return; + } + $item = $ev->getNewItem(); + } + if($item->getID() !== Item::AIR){ + $this->slots[$index] = clone $item; + }else{ + unset($this->slots[$index]); + } + + $this->onSlotChange($index, $old); + } } /** @@ -192,6 +264,41 @@ class PlayerInventory extends BaseInventory{ return $armor; } + /** + * @param Player|Player[] $target + */ + public function sendArmorContents($target){ + if($target instanceof Player){ + $target = [$target]; + } + $armor = $this->getArmorContents(); + $slots = []; + + foreach($armor as $i => $slot){ + if($slot->getID() === Item::AIR){ + $slots[$i] = 255; + }else{ + $slots[$i] = $slot->getID(); + } + } + + $pk = new PlayerArmorEquipmentPacket; + $pk->eid = $this->getHolder()->getID(); + $pk->slots = $slots; + + foreach($target as $player){ + if($player === $this->getHolder()){ + /** @var Player $player */ + $pk2 = new ContainerSetContentPacket; + $pk2->windowid = 0x78; //Armor window id constant + $pk2->slots = $armor; + $player->dataPacket($pk2); + }else{ + $player->dataPacket(clone $pk); + } + } + } + /** * @param Item[] $items */ @@ -209,6 +316,62 @@ class PlayerInventory extends BaseInventory{ } } + /** + * @param Player|Player[] $target + */ + public function sendContents($target){ + if($target instanceof Player){ + $target = [$target]; + } + + $holder = $this->getHolder(); + if($holder instanceof Player and ($holder->getGamemode() & 0x01) === 1){ + return; + } + + $pk = new ContainerSetContentPacket(); + $pk->slots = []; + for($i = 0; $i < $this->getSize(); ++$i){ //Do not send armor by error here + $pk->slots[$i] = $this->getItem($i); + } + + foreach($target as $player){ + $pk->hotbar = []; + if($player === $this->getHolder()){ + for($i = 0; $i < $this->getHotbarSize(); ++$i){ + $index = $this->getHotbarSlotIndex($i); + $pk->hotbar[] = $index <= -1 ? -1 : $index + 9; + } + } + $pk->windowid = $player->getWindowId($this); + $player->dataPacket(clone $pk); + } + } + + /** + * @param int $index + * @param Player|Player[] $target + */ + public function sendSlot($index, $target){ + if($target instanceof Player){ + $target = [$target]; + } + + $pk = new ContainerSetSlotPacket; + $pk->slot = $index; + $pk->item = clone $this->getItem($index); + + foreach($target as $player){ + if($player === $this->getHolder()){ + //TODO: Check if Mojang has implemented this (for the player inventory) on Minecraft: PE 0.9.0 + $this->sendContents($player); + }else{ + $pk->windowid = $player->getWindowId($this); + $player->dataPacket(clone $pk); + } + } + } + /** * @return Human */ diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index 50beb49c5..620771963 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -31,6 +31,7 @@ use pocketmine\event\block\BlockBreakEvent; use pocketmine\event\block\BlockPlaceEvent; use pocketmine\event\player\PlayerInteractEvent; use pocketmine\item\Item; +use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\generator\Generator; use pocketmine\math\Vector2; use pocketmine\math\Vector3 as Vector3; @@ -42,7 +43,6 @@ use pocketmine\nbt\tag\String; use pocketmine\network\protocol\SetTimePacket; use pocketmine\network\protocol\UpdateBlockPacket; use pocketmine\Player; -use pocketmine\level\format\pmf\LevelFormat; use pocketmine\Server; use pocketmine\tile\Chest; use pocketmine\tile\Furnace; diff --git a/src/pocketmine/level/LevelImport.php b/src/pocketmine/level/LevelImport.php index f0efee7ab..c71d90695 100644 --- a/src/pocketmine/level/LevelImport.php +++ b/src/pocketmine/level/LevelImport.php @@ -21,9 +21,9 @@ namespace pocketmine\level; +use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\format\PocketChunkParser; use pocketmine\nbt\NBT; -use pocketmine\level\format\pmf\LevelFormat; use pocketmine\utils\Config; class LevelImport{ diff --git a/src/pocketmine/level/Position.php b/src/pocketmine/level/Position.php index 36b2563cf..9fbd21f50 100644 --- a/src/pocketmine/level/Position.php +++ b/src/pocketmine/level/Position.php @@ -106,6 +106,7 @@ class Position extends Vector3{ if(!$this->isValid()){ throw new \RuntimeException("Undefined Level reference"); } + return Position::fromObject(parent::getSide($side, $step), $this->getLevel()); } diff --git a/src/pocketmine/level/WorldGenerator.php b/src/pocketmine/level/WorldGenerator.php index fb9a617ba..4d62dbd24 100644 --- a/src/pocketmine/level/WorldGenerator.php +++ b/src/pocketmine/level/WorldGenerator.php @@ -21,8 +21,8 @@ namespace pocketmine\level; -use pocketmine\level\generator\Generator; use pocketmine\level\format\pmf\LevelFormat; +use pocketmine\level\generator\Generator; use pocketmine\Server; use pocketmine\utils\Binary; use pocketmine\utils\Random; diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index dd3cbdcfd..3cd286490 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -52,11 +52,11 @@ interface Chunk{ public function getBlock($x, $y, $z, &$blockId, &$meta = null); /** - * @param int $x 0-15 - * @param int $y 0-127 - * @param int $z 0-15 - * @param int $blockId, if null, do not change - * @param int $meta 0-15, if null, do not change + * @param int $x 0-15 + * @param int $y 0-127 + * @param int $z 0-15 + * @param int $blockId , if null, do not change + * @param int $meta 0-15, if null, do not change */ public function setBlock($x, $y, $z, $blockId = null, $meta = null); @@ -70,9 +70,9 @@ interface Chunk{ public function getBlockId($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-127 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-127 + * @param int $z 0-15 * @param int $id 0-255 */ public function setBlockId($x, $y, $z, $id); @@ -87,9 +87,9 @@ interface Chunk{ public function getBlockData($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-127 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-127 + * @param int $z 0-15 * @param int $data 0-15 */ public function setBlockData($x, $y, $z, $data); @@ -104,9 +104,9 @@ interface Chunk{ public function getBlockSkyLight($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-127 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-127 + * @param int $z 0-15 * @param int $level 0-15 */ public function setBlockSkyLight($x, $y, $z, $level); @@ -121,9 +121,9 @@ interface Chunk{ public function getBlockLight($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-127 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-127 + * @param int $z 0-15 * @param int $level 0-15 */ public function setBlockLight($x, $y, $z, $level); diff --git a/src/pocketmine/level/format/ChunkSection.php b/src/pocketmine/level/format/ChunkSection.php index 0ac13c401..ad8ad16af 100644 --- a/src/pocketmine/level/format/ChunkSection.php +++ b/src/pocketmine/level/format/ChunkSection.php @@ -33,9 +33,9 @@ interface ChunkSection{ public function getBlockId($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-15 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-15 + * @param int $z 0-15 * @param int $id 0-255 */ public function setBlockId($x, $y, $z, $id); @@ -50,9 +50,9 @@ interface ChunkSection{ public function getBlockData($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-15 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-15 + * @param int $z 0-15 * @param int $data 0-15 */ public function setBlockData($x, $y, $z, $data); @@ -69,11 +69,11 @@ interface ChunkSection{ public function getBlock($x, $y, $z, &$blockId, &$meta = null); /** - * @param int $x 0-15 - * @param int $y 0-15 - * @param int $z 0-15 - * @param int $blockId, if null, do not change - * @param int $meta 0-15, if null, do not change + * @param int $x 0-15 + * @param int $y 0-15 + * @param int $z 0-15 + * @param int $blockId , if null, do not change + * @param int $meta 0-15, if null, do not change */ public function setBlock($x, $y, $z, $blockId = null, $meta = null); @@ -87,9 +87,9 @@ interface ChunkSection{ public function getBlockSkyLight($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-15 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-15 + * @param int $z 0-15 * @param int $level 0-15 */ public function setBlockSkyLight($x, $y, $z, $level); @@ -104,9 +104,9 @@ interface ChunkSection{ public function getBlockLight($x, $y, $z); /** - * @param int $x 0-15 - * @param int $y 0-15 - * @param int $z 0-15 + * @param int $x 0-15 + * @param int $y 0-15 + * @param int $z 0-15 * @param int $level 0-15 */ public function setBlockLight($x, $y, $z, $level); diff --git a/src/pocketmine/level/format/LevelFormat.php b/src/pocketmine/level/format/LevelFormat.php index eb74325f8..3d525986f 100644 --- a/src/pocketmine/level/format/LevelFormat.php +++ b/src/pocketmine/level/format/LevelFormat.php @@ -20,8 +20,9 @@ */ namespace pocketmine\level\format; -use pocketmine\Server; + use pocketmine\math\Vector3; +use pocketmine\Server; /** * All Level formats must implement this interface @@ -48,8 +49,8 @@ interface LevelFormat{ * Gets the Chunk object * This method must be implemented by all the level formats. * - * @param int $X absolute Chunk X value - * @param int $Z absolute Chunk Z value + * @param int $X absolute Chunk X value + * @param int $Z absolute Chunk Z value * @param bool $create Whether to generate the chunk if it does not exist * * @return ChunkSnapshot diff --git a/src/pocketmine/level/format/PocketChunkParser.php b/src/pocketmine/level/format/PocketChunkParser.php index 4743ef387..ee03c9fb4 100644 --- a/src/pocketmine/level/format/PocketChunkParser.php +++ b/src/pocketmine/level/format/PocketChunkParser.php @@ -22,7 +22,6 @@ namespace pocketmine\level\format; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; /** * WARNING: This code is old, and only supports the file format partially (reverse engineering) diff --git a/src/pocketmine/level/format/anvil/ChunkSection.php b/src/pocketmine/level/format/anvil/ChunkSection.php index 2241782f6..c3db84e25 100644 --- a/src/pocketmine/level/format/anvil/ChunkSection.php +++ b/src/pocketmine/level/format/anvil/ChunkSection.php @@ -138,6 +138,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ for($y = 15; $y >= 0; --$y){ $column{15 - $y} = $this->blocks{($y << 8) + $i}; } + return $column; } @@ -147,6 +148,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ for($y = 7; $y >= 0; --$y){ $column{7 - $y} = $this->data{($y << 7) + $i}; } + return $column; } diff --git a/src/pocketmine/level/format/anvil/RegionLoader.php b/src/pocketmine/level/format/anvil/RegionLoader.php index 08f7f524e..9af563397 100644 --- a/src/pocketmine/level/format/anvil/RegionLoader.php +++ b/src/pocketmine/level/format/anvil/RegionLoader.php @@ -21,7 +21,6 @@ namespace pocketmine\level\format\anvil; -use pocketmine\level\Level; use pocketmine\nbt\NBT; use pocketmine\nbt\tag\Byte; use pocketmine\nbt\tag\ByteArray; @@ -45,10 +44,12 @@ class RegionLoader{ protected $lastSector; protected $locationTable = []; - public function __construct($path,/*Level $level, */$regionX, $regionZ){ + public function __construct($path, /*Level $level, */ + $regionX, $regionZ){ $this->x = $regionX; $this->z = $regionZ; - $this->filePath = /*$level->getPath()*/$path . "region/r.$regionX.$regionZ.mca"; + $this->filePath = /*$level->getPath()*/ + $path . "region/r.$regionX.$regionZ.mca"; touch($this->filePath); $this->filePointer = fopen($this->filePath, "r+b"); flock($this->filePointer, LOCK_EX); @@ -103,6 +104,7 @@ class RegionLoader{ $this->writeLocationIndex($index); }elseif($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){ trigger_error("Invalid compression type", E_USER_WARNING); + return false; } @@ -113,6 +115,7 @@ class RegionLoader{ if(!$chunk instanceof Compound){ return false; } + return $chunk; //$chunk = new Chunk($level, $chunk); } @@ -183,6 +186,7 @@ class RegionLoader{ $this->writeLocationTable(); $n = $this->cleanGarbage(); $this->writeLocationTable(); + return $n; } diff --git a/src/pocketmine/level/format/generic/BaseChunk.php b/src/pocketmine/level/format/generic/BaseChunk.php index 489e6604b..5e968124c 100644 --- a/src/pocketmine/level/format/generic/BaseChunk.php +++ b/src/pocketmine/level/format/generic/BaseChunk.php @@ -20,6 +20,7 @@ */ namespace pocketmine\level\format\generic; + use pocketmine\level\format\Chunk; use pocketmine\level\format\ChunkSection; use pocketmine\level\Level; @@ -34,9 +35,9 @@ abstract class BaseChunk implements Chunk{ protected $z; /** - * @param Level $level - * @param int $x - * @param int $z + * @param Level $level + * @param int $x + * @param int $z * @param ChunkSection[] $sections */ public function __construct(Level $level, $x, $z, array $sections){ @@ -48,11 +49,13 @@ abstract class BaseChunk implements Chunk{ $this->sections[$Y] = $section; }else{ trigger_error("Received invalid ChunkSection instance", E_USER_ERROR); + return; } if($section >= self::SECTION_COUNT){ trigger_error("Invalid amount of chunks", E_USER_WARNING); + return; } } diff --git a/src/pocketmine/level/format/generic/EmptyChunkSection.php b/src/pocketmine/level/format/generic/EmptyChunkSection.php index c99c3df6f..bb4a143ba 100644 --- a/src/pocketmine/level/format/generic/EmptyChunkSection.php +++ b/src/pocketmine/level/format/generic/EmptyChunkSection.php @@ -20,6 +20,7 @@ */ namespace pocketmine\level\format\generic; + use pocketmine\level\format\ChunkSection; /** diff --git a/src/pocketmine/level/format/pmf/ChunkSection.php b/src/pocketmine/level/format/pmf/ChunkSection.php index acb073894..db5018c62 100644 --- a/src/pocketmine/level/format/pmf/ChunkSection.php +++ b/src/pocketmine/level/format/pmf/ChunkSection.php @@ -32,6 +32,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{ if($section !== null){ if(strlen($section) !== 8192){ trigger_error("Invalid ChunkSection generated", E_USER_WARNING); + return; } $this->section = $section; diff --git a/src/pocketmine/level/format/pmf/LevelFormat.php b/src/pocketmine/level/format/pmf/LevelFormat.php index add37e013..22e129e9d 100644 --- a/src/pocketmine/level/format/pmf/LevelFormat.php +++ b/src/pocketmine/level/format/pmf/LevelFormat.php @@ -26,7 +26,6 @@ use pocketmine\nbt\NBT; use pocketmine\nbt\tag\Compound; use pocketmine\nbt\tag\Enum; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class LevelFormat extends PMF{ const VERSION = 2; diff --git a/src/pocketmine/metadata/MetadataStore.php b/src/pocketmine/metadata/MetadataStore.php index bb991cf66..adf25363d 100644 --- a/src/pocketmine/metadata/MetadataStore.php +++ b/src/pocketmine/metadata/MetadataStore.php @@ -33,7 +33,7 @@ abstract class MetadataStore{ /** * Adds a metadata value to an object. * - * @param mixed $subject + * @param mixed $subject * @param string $metadataKey * @param MetadataValue $newMetadataValue */ @@ -41,6 +41,7 @@ abstract class MetadataStore{ $owningPlugin = $newMetadataValue->getOwningPlugin(); if($owningPlugin === null){ trigger_error("Plugin cannot be null", E_USER_WARNING); + return; } @@ -58,7 +59,7 @@ abstract class MetadataStore{ * Returns all metadata values attached to an object. If multiple * have attached metadata, each will value will be included. * - * @param mixed $subject + * @param mixed $subject * @param string $metadataKey * * @return MetadataValue[] @@ -75,7 +76,7 @@ abstract class MetadataStore{ /** * Tests to see if a metadata attribute has been set on an object. * - * @param mixed $subject + * @param mixed $subject * @param string $metadataKey * * @return bool @@ -87,7 +88,7 @@ abstract class MetadataStore{ /** * Removes a metadata item owned by a plugin from a subject. * - * @param mixed $subject + * @param mixed $subject * @param string $metadataKey * @param Plugin $owningPlugin */ @@ -121,7 +122,7 @@ abstract class MetadataStore{ * Creates a unique name for the object receiving metadata by combining * unique data from the subject with a metadataKey. * - * @param mixed $subject + * @param mixed $subject * @param string $metadataKey * * @return string diff --git a/src/pocketmine/nbt/NBT.php b/src/pocketmine/nbt/NBT.php index 814f59d53..612a98f32 100644 --- a/src/pocketmine/nbt/NBT.php +++ b/src/pocketmine/nbt/NBT.php @@ -39,7 +39,6 @@ use pocketmine\nbt\tag\Short; use pocketmine\nbt\tag\String; use pocketmine\nbt\tag\Tag; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; /** * Named Binary Tag encoder/decoder diff --git a/src/pocketmine/network/protocol/AddMobPacket.php b/src/pocketmine/network/protocol/AddMobPacket.php index 6babe301e..a430cda05 100644 --- a/src/pocketmine/network/protocol/AddMobPacket.php +++ b/src/pocketmine/network/protocol/AddMobPacket.php @@ -22,7 +22,6 @@ namespace pocketmine\network\protocol; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class AddMobPacket extends DataPacket{ public $eid; diff --git a/src/pocketmine/network/protocol/AddPlayerPacket.php b/src/pocketmine/network/protocol/AddPlayerPacket.php index e6b4c5fac..f615e05ef 100644 --- a/src/pocketmine/network/protocol/AddPlayerPacket.php +++ b/src/pocketmine/network/protocol/AddPlayerPacket.php @@ -22,7 +22,6 @@ namespace pocketmine\network\protocol; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class AddPlayerPacket extends DataPacket{ public $clientID; diff --git a/src/pocketmine/network/protocol/DataPacket.php b/src/pocketmine/network/protocol/DataPacket.php index 8ed37f9f1..951c7fcec 100644 --- a/src/pocketmine/network/protocol/DataPacket.php +++ b/src/pocketmine/network/protocol/DataPacket.php @@ -23,7 +23,6 @@ namespace pocketmine\network\protocol; use pocketmine\item\Item; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; abstract class DataPacket extends \stdClass{ private $offset = 0; diff --git a/src/pocketmine/network/protocol/SetEntityDataPacket.php b/src/pocketmine/network/protocol/SetEntityDataPacket.php index b8da893ad..f1abadac7 100644 --- a/src/pocketmine/network/protocol/SetEntityDataPacket.php +++ b/src/pocketmine/network/protocol/SetEntityDataPacket.php @@ -22,7 +22,6 @@ namespace pocketmine\network\protocol; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class SetEntityDataPacket extends DataPacket{ public $eid; diff --git a/src/pocketmine/network/query/QueryPacket.php b/src/pocketmine/network/query/QueryPacket.php index 8c560e3d9..9ecfb7a4d 100644 --- a/src/pocketmine/network/query/QueryPacket.php +++ b/src/pocketmine/network/query/QueryPacket.php @@ -23,7 +23,6 @@ namespace pocketmine\network\query; use pocketmine\network\Packet; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class QueryPacket extends Packet{ const HANDSHAKE = 9; diff --git a/src/pocketmine/network/raknet/Packet.php b/src/pocketmine/network/raknet/Packet.php index ef9798bfe..153f6bc21 100644 --- a/src/pocketmine/network/raknet/Packet.php +++ b/src/pocketmine/network/raknet/Packet.php @@ -79,7 +79,6 @@ use pocketmine\network\protocol\UnknownPacket; use pocketmine\network\protocol\UpdateBlockPacket; use pocketmine\network\protocol\UseItemPacket; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class Packet extends NetworkPacket{ private $packetID; diff --git a/src/pocketmine/network/rcon/RCONInstance.php b/src/pocketmine/network/rcon/RCONInstance.php index cb7ec7197..ee2dc8946 100644 --- a/src/pocketmine/network/rcon/RCONInstance.php +++ b/src/pocketmine/network/rcon/RCONInstance.php @@ -22,7 +22,6 @@ namespace pocketmine\network\rcon; use pocketmine\utils\Binary; -use pocketmine\utils\Utils; class RCONInstance extends \Thread{ public $stop; diff --git a/src/pocketmine/plugin/Plugin.php b/src/pocketmine/plugin/Plugin.php index ba79bb48c..ff90009b4 100644 --- a/src/pocketmine/plugin/Plugin.php +++ b/src/pocketmine/plugin/Plugin.php @@ -23,6 +23,7 @@ * Plugin related classes */ namespace pocketmine\plugin; + use pocketmine\command\CommandExecutor; @@ -71,7 +72,7 @@ interface Plugin extends CommandExecutor{ * Saves an embedded resource to its relative location in the data folder * * @param string $filename - * @param bool $replace + * @param bool $replace */ public function saveResource($filename, $replace = false); diff --git a/src/pocketmine/plugin/PluginLogger.php b/src/pocketmine/plugin/PluginLogger.php index 398bbb11f..02ec36535 100644 --- a/src/pocketmine/plugin/PluginLogger.php +++ b/src/pocketmine/plugin/PluginLogger.php @@ -30,7 +30,7 @@ class PluginLogger{ */ public function __construct(Plugin $context){ $prefix = $context->getDescription()->getPrefix(); - $this->pluginName = $prefix != null ? "[$prefix] " : "[".$context->getDescription()->getName()."] "; + $this->pluginName = $prefix != null ? "[$prefix] " : "[" . $context->getDescription()->getName() . "] "; } /** diff --git a/src/pocketmine/plugin/PluginManager.php b/src/pocketmine/plugin/PluginManager.php index b81f44979..0edf171f1 100644 --- a/src/pocketmine/plugin/PluginManager.php +++ b/src/pocketmine/plugin/PluginManager.php @@ -148,6 +148,7 @@ class PluginManager{ if(count($pluginCommands) > 0){ $this->commandMap->registerAll($plugin->getDescription()->getName(), $pluginCommands); } + return $plugin; } } @@ -159,7 +160,7 @@ class PluginManager{ /** * @param string $directory - * @param array $newLoaders + * @param array $newLoaders * * @return Plugin[] */ diff --git a/src/pocketmine/scheduler/AsyncTask.php b/src/pocketmine/scheduler/AsyncTask.php index 0dabcb9ce..a357badc5 100644 --- a/src/pocketmine/scheduler/AsyncTask.php +++ b/src/pocketmine/scheduler/AsyncTask.php @@ -52,8 +52,9 @@ abstract class AsyncTask extends \Threaded{ * @return mixed */ public function getResult(){ - return $this->synchronized(function(){ + return $this->synchronized(function (){ $this->finished = true; + return @unserialize($this->result); }); } diff --git a/src/pocketmine/scheduler/AsyncWorker.php b/src/pocketmine/scheduler/AsyncWorker.php index ecb9fbed5..a22559a50 100644 --- a/src/pocketmine/scheduler/AsyncWorker.php +++ b/src/pocketmine/scheduler/AsyncWorker.php @@ -26,6 +26,7 @@ class AsyncWorker extends \Worker{ public function start($options = PTHREADS_INHERIT_CLASSES){ $this->path = \pocketmine\PATH; + return parent::start($options & ~PTHREADS_INHERIT_CLASSES); } diff --git a/src/pocketmine/scheduler/ServerScheduler.php b/src/pocketmine/scheduler/ServerScheduler.php index a76b2c5de..d54e08e5e 100644 --- a/src/pocketmine/scheduler/ServerScheduler.php +++ b/src/pocketmine/scheduler/ServerScheduler.php @@ -205,11 +205,13 @@ class ServerScheduler{ } if($this->asyncTasks > 0){ //Garbage collector - $this->asyncPool->collect(function(AsyncTask $task){ + $this->asyncPool->collect(function (AsyncTask $task){ if($task->isCompleted() or ($task->isFinished() and !$task->hasResult())){ --$this->asyncTasks; + return true; } + return false; }); } diff --git a/src/pocketmine/tile/Chest.php b/src/pocketmine/tile/Chest.php index 8de27d671..b973b9103 100644 --- a/src/pocketmine/tile/Chest.php +++ b/src/pocketmine/tile/Chest.php @@ -21,23 +21,134 @@ namespace pocketmine\tile; +use pocketmine\inventory\ChestInventory; +use pocketmine\inventory\DoubleChestInventory; +use pocketmine\inventory\InventoryHolder; +use pocketmine\item\Item; use pocketmine\level\Level; use pocketmine\math\Vector3 as Vector3; use pocketmine\nbt\NBT; +use pocketmine\nbt\tag\Byte; use pocketmine\nbt\tag\Compound; use pocketmine\nbt\tag\Int; +use pocketmine\nbt\tag\Short; use pocketmine\nbt\tag\String; use pocketmine\network\protocol\EntityDataPacket; use pocketmine\Player; -class Chest extends Spawnable{ - use Container; +class Chest extends Spawnable implements InventoryHolder, Container{ - const SLOTS = 27; + /** @var ChestInventory */ + protected $inventory; + /** @var DoubleChestInventory */ + protected $doubleInventory = null; public function __construct(Level $level, Compound $nbt){ $nbt["id"] = Tile::CHEST; parent::__construct($level, $nbt); + $this->inventory = new ChestInventory($this); + for($i = 0; $i < $this->getSize(); ++$i){ + $this->inventory->setItem($i, $this->getItem($i)); + } + $this->checkPairing(); + } + + /** + * @return int + */ + public function getSize(){ + return 27; + } + + /** + * @param $index + * + * @return int + */ + protected function getSlotIndex($index){ + foreach($this->namedtag->Items as $i => $slot){ + if($slot["Slot"] === $s){ + return $i; + } + } + + return -1; + } + + /** + * This method should not be used by plugins, use the Inventory + * + * @param int $index + * + * @return Item + */ + public function getItem($index){ + $i = $this->getSlotIndex($index); + if($i < 0){ + return Item::get(Item::AIR, 0, 0); + }else{ + return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]); + } + } + + /** + * This method should not be used by plugins, use the Inventory + * + * @param int $index + * @param Item $item + * + * @return bool + */ + public function setItem($index, Item $item){ + $i = $this->getSlotIndex($index); + if($i < 0){ + return false; + } + + $d = new Compound(false, array( + new Byte("Count", $item->getCount()), + new Byte("Slot", $index), + new Short("id", $item->getID()), + new Short("Damage", $item->getDamage()), + )); + + if($item->getID() === Item::AIR or $item->getCount() <= 0){ + if($i >= 0){ + unset($this->namedtag->Items[$i]); + } + }elseif($i < 0){ + $this->namedtag->Items[] = $d; + }else{ + $this->namedtag->Items[$i] = $d; + } + + return true; + } + + /** + * @return ChestInventory|DoubleChestInventory + */ + public function getInventory(){ + return $this->doubleInventory instanceof DoubleChestInventory ? $this->doubleInventory : $this->inventory; + } + + /** + * @return ChestInventory + */ + public function getRealInventory(){ + return $this->inventory; + } + + protected function checkPairing(){ + if(($pair = $this->getPair()) instanceof Chest){ + if(($pair->x + ($pair->z << 15)) > ($this->x + ($this->z << 15))){ //Order them correctly + $this->doubleInventory = new DoubleChestInventory($pair, $this); + }else{ + $this->doubleInventory = new DoubleChestInventory($this, $pair); + } + }else{ + $this->doubleInventory = null; + } } public function isPaired(){ @@ -48,12 +159,18 @@ class Chest extends Spawnable{ return true; } + /** + * @return Chest + */ public function getPair(){ if($this->isPaired()){ - return $this->getLevel()->getTile(new Vector3((int) $this->namedtag->pairx, $this->y, (int) $this->namedtag->pairz)); + $tile = $this->getLevel()->getTile(new Vector3((int) $this->namedtag->pairx, $this->y, (int) $this->namedtag->pairz)); + if($tile instanceof Chest){ + return $tile; + } } - return false; + return null; } public function pairWith(Chest $tile){ @@ -69,10 +186,11 @@ class Chest extends Spawnable{ $this->spawnToAll(); $tile->spawnToAll(); + $this->checkPairing(); //TODO: Update to new events - $this->server->handle("tile.update", $this); - $this->server->handle("tile.update", $tile); + //$this->server->handle("tile.update", $this); + //$this->server->handle("tile.update", $tile); return true; } @@ -86,10 +204,12 @@ class Chest extends Spawnable{ unset($this->namedtag->pairx, $this->namedtag->pairz, $tile->namedtag->pairx, $tile->namedtag->pairz); $this->spawnToAll(); - $this->server->handle("tile.update", $this); + $this->checkPairing(); + //TODO: tile update event + //$this->server->handle("tile.update", $this); if($tile instanceof Chest){ $tile->spawnToAll(); - $this->server->handle("tile.update", $tile); + //$this->server->handle("tile.update", $tile); } return true; diff --git a/src/pocketmine/tile/Container.php b/src/pocketmine/tile/Container.php index a7c59b158..75270751e 100644 --- a/src/pocketmine/tile/Container.php +++ b/src/pocketmine/tile/Container.php @@ -23,178 +23,12 @@ namespace pocketmine\tile; use pocketmine\event\tile\TileInventoryChangeEvent; use pocketmine\item\Item; -use pocketmine\nbt\tag\Byte; -use pocketmine\nbt\tag\Compound; -use pocketmine\nbt\tag\Short; use pocketmine\Network; -use pocketmine\network\protocol\ContainerOpenPacket; -use pocketmine\network\protocol\ContainerSetContentPacket; -use pocketmine\network\protocol\TileEventPacket; -use pocketmine\Player; -use pocketmine\Server; -trait Container{ - public function openInventory(Player $player){ - if($this instanceof Chest){ - $player->windowCnt++; - $player->windowCnt = $id = max(2, $player->windowCnt % 99); - if(($pair = $this->getPair()) !== false){ - if(($pair->x + ($pair->z << 13)) > ($this->x + ($this->z << 13))){ //Order them correctly - $player->windows[$id] = array( - $pair, - $this - ); - }else{ - $player->windows[$id] = array( - $this, - $pair - ); - } - }else{ - $player->windows[$id] = $this; - } +interface Container{ + public function getItem($index); - $pk = new ContainerOpenPacket(); - $pk->windowid = $id; - $pk->type = 0; - $pk->slots = is_array($player->windows[$id]) ? Chest::SLOTS << 1 : Chest::SLOTS; - $pk->x = $this->x; - $pk->y = $this->y; - $pk->z = $this->z; - $player->dataPacket($pk); - $slots = []; + public function setItem($index, Item $item); - if(is_array($player->windows[$id])){ - $all = $this->getLevel()->getPlayers(); - foreach($player->windows[$id] as $ob){ - $pk = new TileEventPacket(); - $pk->x = $ob->x; - $pk->y = $ob->y; - $pk->z = $ob->z; - $pk->case1 = 1; - $pk->case2 = 2; - Player::broadcastPacket($all, $pk); - for($s = 0; $s < Chest::SLOTS; ++$s){ - $slot = $ob->getSlot($s); - if($slot->getID() > Item::AIR and $slot->getCount() > 0){ - $slots[] = $slot; - }else{ - $slots[] = Item::get(Item::AIR, 0, 0); - } - } - } - }else{ - $pk = new TileEventPacket(); - $pk->x = $this->x; - $pk->y = $this->y; - $pk->z = $this->z; - $pk->case1 = 1; - $pk->case2 = 2; - Player::broadcastPacket($this->getLevel()->getPlayers(), $pk); - for($s = 0; $s < Chest::SLOTS; ++$s){ - $slot = $this->getSlot($s); - if($slot->getID() > Item::AIR and $slot->getCount() > 0){ - $slots[] = $slot; - }else{ - $slots[] = Item::get(Item::AIR, 0, 0); - } - } - } - - $pk = new ContainerSetContentPacket(); - $pk->windowid = $id; - $pk->slots = $slots; - $player->dataPacket($pk); - - return true; - }elseif($this instanceof Furnace){ - $player->windowCnt++; - $player->windowCnt = $id = max(2, $player->windowCnt % 99); - $player->windows[$id] = $this; - - $pk = new ContainerOpenPacket(); - $pk->windowid = $id; - $pk->type = 2; - $pk->slots = Furnace::SLOTS; - $pk->x = $this->x; - $pk->y = $this->y; - $pk->z = $this->z; - $player->dataPacket($pk); - - $slots = []; - for($s = 0; $s < Furnace::SLOTS; ++$s){ - $slot = $this->getSlot($s); - if($slot->getID() > Item::AIR and $slot->getCount() > 0){ - $slots[] = $slot; - }else{ - $slots[] = Item::get(Item::AIR, 0, 0); - } - } - $pk = new ContainerSetContentPacket(); - $pk->windowid = $id; - $pk->slots = $slots; - $player->dataPacket($pk); - - return true; - } - } - - public function getSlotIndex($s){ - foreach($this->namedtag->Items as $i => $slot){ - if($slot["Slot"] === $s){ - return $i; - } - } - - return -1; - } - - /** - * @param int $s - * - * @return Item - */ - public function getSlot($s){ - $i = $this->getSlotIndex($s); - if($i === false or $i < 0){ - return Item::get(Item::AIR, 0, 0); - }else{ - return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]); - } - } - - public function setSlot($s, Item $item, $update = true, $offset = 0){ - $i = $this->getSlotIndex($s); - if($i === false){ - return false; - } - Server::getInstance()->getPluginManager()->callEvent($ev = new TileInventoryChangeEvent($this, $this->getSlot($s), $item, $s, $offset)); - if($ev->isCancelled()){ - return false; - } - - $item = $ev->getNewItem(); - $d = new Compound(false, array( - new Byte("Count", $item->getCount()), - new Byte("Slot", $s), - new Short("id", $item->getID()), - new Short("Damage", $item->getDamage()), - )); - - if($item->getID() === Item::AIR or $item->getCount() <= 0){ - if($i >= 0){ - unset($this->namedtag->Items[$i]); - } - }elseif($i < 0){ - $this->namedtag->Items[] = $d; - }else{ - $this->namedtag->Items[$i] = $d; - } - - if($update === true){ - $this->scheduleUpdate(); - } - - return true; - } -} \ No newline at end of file + public function getSize(); +} diff --git a/src/pocketmine/tile/Furnace.php b/src/pocketmine/tile/Furnace.php index 0d245b901..788df6709 100644 --- a/src/pocketmine/tile/Furnace.php +++ b/src/pocketmine/tile/Furnace.php @@ -22,18 +22,26 @@ namespace pocketmine\tile; use pocketmine\block\Block; +use pocketmine\inventory\FurnaceInventory; +use pocketmine\inventory\InventoryHolder; use pocketmine\item\Item; use pocketmine\level\Level; +use pocketmine\nbt\tag\Byte; use pocketmine\nbt\tag\Compound; +use pocketmine\nbt\tag\Short; -class Furnace extends Tile{ - use Container; - - const SLOTS = 3; +class Furnace extends Tile implements InventoryHolder, Container{ + /** @var FurnaceInventory */ + protected $inventory; public function __construct(Level $level, Compound $nbt){ $nbt["id"] = Tile::FURNACE; parent::__construct($level, $nbt); + $this->inventory = new FurnaceInventory($this); + for($i = 0; $i < $this->getSize(); ++$i){ + $this->inventory->setItem($i, $this->getItem($i)); + } + if(!isset($this->namedtag->BurnTime) or $this->namedtag->BurnTime < 0){ $this->namedtag->BurnTime = 0; } @@ -49,6 +57,85 @@ class Furnace extends Tile{ } } + /** + * @return int + */ + public function getSize(){ + return 3; + } + + /** + * @param $index + * + * @return int + */ + protected function getSlotIndex($index){ + foreach($this->namedtag->Items as $i => $slot){ + if($slot["Slot"] === $s){ + return $i; + } + } + + return -1; + } + + /** + * This method should not be used by plugins, use the Inventory + * + * @param int $index + * + * @return Item + */ + public function getItem($index){ + $i = $this->getSlotIndex($index); + if($i < 0){ + return Item::get(Item::AIR, 0, 0); + }else{ + return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]); + } + } + + /** + * This method should not be used by plugins, use the Inventory + * + * @param int $index + * @param Item $item + * + * @return bool + */ + public function setItem($index, Item $item){ + $i = $this->getSlotIndex($index); + if($i < 0){ + return false; + } + + $d = new Compound(false, array( + new Byte("Count", $item->getCount()), + new Byte("Slot", $index), + new Short("id", $item->getID()), + new Short("Damage", $item->getDamage()), + )); + + if($item->getID() === Item::AIR or $item->getCount() <= 0){ + if($i >= 0){ + unset($this->namedtag->Items[$i]); + } + }elseif($i < 0){ + $this->namedtag->Items[] = $d; + }else{ + $this->namedtag->Items[$i] = $d; + } + + return true; + } + + /** + * @return FurnaceInventory + */ + public function getInventory(){ + return $this->inventory; + } + public function onUpdate(){ if($this->closed === true){ return false; @@ -56,9 +143,9 @@ class Furnace extends Tile{ $ret = false; - $fuel = $this->getSlot(1); - $raw = $this->getSlot(0); - $product = $this->getSlot(2); + $fuel = $this->inventory->getFuel(); + $raw = $this->inventory->getSmelting(); + $product = $this->inventory->getResult(); $smelt = $raw->getSmeltItem(); $canSmelt = ($smelt !== false and $raw->getCount() > 0 and (($product->getID() === $smelt->getID() and $product->getDamage() === $smelt->getDamage() and $product->getCount() < $product->getMaxStackSize()) or $product->getID() === Item::AIR)); if($this->namedtag->BurnTime <= 0 and $canSmelt and $fuel->getFuelTime() !== false and $fuel->getCount() > 0){ @@ -69,7 +156,7 @@ class Furnace extends Tile{ if($fuel->getCount() === 0){ $fuel = Item::get(Item::AIR, 0, 0); } - $this->setSlot(1, $fuel, false); + $this->inventory->setFuel($fuel); $current = $this->getLevel()->getBlock($this); if($current->getID() === Item::FURNACE){ $this->getLevel()->setBlock($this, Block::get(Item::BURNING_FURNACE, $current->getDamage()), true, false, true); @@ -83,12 +170,12 @@ class Furnace extends Tile{ $this->namedtag->CookTime += $ticks; if($this->namedtag->CookTime >= 200){ //10 seconds $product = Item::get($smelt->getID(), $smelt->getDamage(), $product->getCount() + 1); - $this->setSlot(2, $product, false); + $this->inventory->setResult($product); $raw->setCount($raw->getCount() - 1); if($raw->getCount() === 0){ $raw = Item::get(Item::AIR, 0, 0); } - $this->setSlot(0, $raw, false); + $this->inventory->setSmelting($raw); $this->namedtag->CookTime -= 200; } }elseif($this->namedtag->BurnTime <= 0){ @@ -109,8 +196,8 @@ class Furnace extends Tile{ $this->namedtag->BurnTicks = 0; } - - $this->server->handle("tile.update", $this); + //TODO: tile update event + //$this->server->handle("tile.update", $this); $this->lastUpdate = microtime(true); return $ret; diff --git a/src/pocketmine/tile/Spawnable.php b/src/pocketmine/tile/Spawnable.php index 512218f47..77d53d968 100644 --- a/src/pocketmine/tile/Spawnable.php +++ b/src/pocketmine/tile/Spawnable.php @@ -28,7 +28,7 @@ abstract class Spawnable extends Tile{ public function spawnToAll(){ foreach($this->getLevel()->getPlayers() as $player){ - if($player->eid !== false or $player->spawned !== true){ + if($player->spawned === true){ $this->spawnTo($player); } } diff --git a/src/pocketmine/tile/Tile.php b/src/pocketmine/tile/Tile.php index 4a1918e06..2d453fbc3 100644 --- a/src/pocketmine/tile/Tile.php +++ b/src/pocketmine/tile/Tile.php @@ -25,10 +25,10 @@ */ namespace pocketmine\tile; +use pocketmine\level\format\pmf\LevelFormat; use pocketmine\level\Level; use pocketmine\level\Position; use pocketmine\nbt\tag\Compound; -use pocketmine\level\format\pmf\LevelFormat; use pocketmine\Server; abstract class Tile extends Position{ @@ -36,6 +36,8 @@ abstract class Tile extends Position{ const CHEST = "Chest"; const FURNACE = "Furnace"; + //TODO: pre-close step NBT data saving method + public static $tileCount = 1; /** @@ -89,8 +91,8 @@ abstract class Tile extends Position{ $index = LevelFormat::getIndex($this->x >> 4, $this->z >> 4); $this->chunkIndex = $index; - $this->level->tiles[$this->id] = $this; - $this->level->chunkTiles[$this->chunkIndex][$this->id] = $this; + $this->getLevel()->tiles[$this->id] = $this; + $this->getLevel()->chunkTiles[$this->chunkIndex][$this->id] = $this; } public function onUpdate(){ @@ -105,8 +107,8 @@ abstract class Tile extends Position{ if($this->closed === false){ $this->closed = true; unset(Tile::$needUpdate[$this->id]); - unset($this->level->tiles[$this->id]); - unset($this->level->chunkTiles[$this->chunkIndex][$this->id]); + unset($this->getLevel()->tiles[$this->id]); + unset($this->getLevel()->chunkTiles[$this->chunkIndex][$this->id]); unset(Tile::$list[$this->id]); } } diff --git a/src/pocketmine/utils/Binary.php b/src/pocketmine/utils/Binary.php index 901ad2dfd..38a15bbf6 100644 --- a/src/pocketmine/utils/Binary.php +++ b/src/pocketmine/utils/Binary.php @@ -171,6 +171,7 @@ class Binary{ return $m; } + /** * Reads a byte boolean * @@ -197,7 +198,7 @@ class Binary{ * Reads an unsigned/signed byte * * @param string $c - * @param bool $signed + * @param bool $signed * * @return int */ diff --git a/src/pocketmine/utils/Config.php b/src/pocketmine/utils/Config.php index dbb53bfd8..761ea6d53 100644 --- a/src/pocketmine/utils/Config.php +++ b/src/pocketmine/utils/Config.php @@ -262,12 +262,13 @@ class Config{ $currPath = null; } } + return $currPath; } /** * @param string $path - * @param mixed $value + * @param mixed $value */ public function &setPath($path, $value){ $currPath =& $this->config; diff --git a/src/pocketmine/utils/Random.php b/src/pocketmine/utils/Random.php index 4e082b61d..05cee865d 100644 --- a/src/pocketmine/utils/Random.php +++ b/src/pocketmine/utils/Random.php @@ -69,6 +69,7 @@ class Random{ if($t > 2147483647){ $t -= 4294967296; } + return (int) $t; } diff --git a/src/pocketmine/utils/TextFormat.php b/src/pocketmine/utils/TextFormat.php index 3eca7311b..4ef37ad65 100644 --- a/src/pocketmine/utils/TextFormat.php +++ b/src/pocketmine/utils/TextFormat.php @@ -274,6 +274,7 @@ class TextFormat{ break; } } + return $newString; } diff --git a/src/pocketmine/utils/Utils.php b/src/pocketmine/utils/Utils.php index 5c083e45d..81b4fec16 100644 --- a/src/pocketmine/utils/Utils.php +++ b/src/pocketmine/utils/Utils.php @@ -24,8 +24,6 @@ */ namespace pocketmine\utils; -use pocketmine\item\Item; - /** * Big collection of functions */