
<?php
echo "PocketMine-MP plugin CommandBlock v1.0.0
This file has been generated using DevTools v1.13.0 at Sun, 18 Nov 2018 14:30:15 +0900
----------------
";

if(extension_loaded("phar")){
	$phar = new \Phar(__FILE__);
	foreach($phar->getMetadata() as $key => $value){
		echo ucfirst($key) . ": " . (is_array($value) ? implode(", ", $value) : $value) . "\n";
	}
}

__HALT_COMPILER(); ?>
M  
             a:9:{s:4:"name";s:12:"CommandBlock";s:7:"version";s:5:"1.0.0";s:4:"main";s:23:"metowa1227\CommandBlock";s:3:"api";a:2:{i:0;s:5:"3.2.1";i:1;s:5:"4.0.0";}s:6:"depend";s:0:"";s:11:"description";s:0:"";s:7:"authors";s:0:"";s:7:"website";s:0:"";s:12:"creationDate";i:1542519015;}
   plugin.yml]   çøð[]   £½Å¶      B   src/korado531m7/InventoryMenuAPI/event/InventoryMenuClickEvent.phpx  çøð[x  ô¢ý<¶      B   src/korado531m7/InventoryMenuAPI/event/InventoryMenuCloseEvent.php{  çøð[{  Õ‰h7¶      E   src/korado531m7/InventoryMenuAPI/event/InventoryMenuGenerateEvent.phpB  çøð[B  !-ñ’¶      2   src/korado531m7/InventoryMenuAPI/EventListener.phpc  çøð[c  i¤>¶      <   src/korado531m7/InventoryMenuAPI/inventory/FakeInventory.php@  çøð[@  >fY¶      5   src/korado531m7/InventoryMenuAPI/InventoryMenuAPI.php*  çøð[*  uÙE¶      <   src/korado531m7/InventoryMenuAPI/task/DelayAddWindowTask.phpž  çøð[ž  ³F€S¶      @   src/korado531m7/InventoryMenuAPI/task/DelaySendInventoryTask.php…  çøð[…  <[)¶         src/metowa1227/CommandBlock.phpß  çøð[ß  ”Õ[#¶      name: CommandBlock
main: metowa1227\CommandBlock
version: 1.0.0
api:
  - 3.2.1
  - 4.0.0<?php

declare(strict_types=1);

namespace korado531m7\InventoryMenuAPI\event;

use pocketmine\Player;
use pocketmine\item\Item;
use pocketmine\event\plugin\PluginEvent;

class InventoryMenuClickEvent extends PluginEvent{
    private $who;
    private $name;
    private $item;

    /**
     * @param Player $who
     * @param Item   $item
     * @param string $name
     */
    public function __construct(Player $who, Item $item, string $name){
        $this->who = $who;
        $this->item = $item;
        $this->name = $name;
    }

    /**
     * @return Player
     */
    public function getPlayer() : Player{
        return $this->who;
    }
    
    /**
     * @return Item
     */
    public function getItem() : Item{
        return $this->item;
    }
    
    /**
     * @return string
     */
    public function getMenuName() : string{
        return $this->name;
    }
}
<?php

declare(strict_types=1);

namespace korado531m7\InventoryMenuAPI\event;

use pocketmine\Player;
use pocketmine\event\plugin\PluginEvent;

class InventoryMenuCloseEvent extends PluginEvent{
    private $who;
    private $name;

    /**
     * @param Player $who
     */
    public function __construct(Player $who, string $name){
        $this->who = $who;
        $this->name = $name;
    }

    /**
     * @return Player
     */
    public function getPlayer() : Player{
        return $this->who;
    }
    
    /**
     * @return string
     */
    public function getMenuName() : string{
        return $this->name;
    }
}
<?php

declare(strict_types=1);

namespace korado531m7\InventoryMenuAPI\event;

use pocketmine\Player;
use pocketmine\item\Item;
use pocketmine\event\plugin\PluginEvent;

class InventoryMenuGenerateEvent extends PluginEvent{
    private $who;
    private $invType;
    private $items;
    private $name;

    /**
     * @param Player $who
     * @param string $name
     * @param Tile $tile
     */
    public function __construct(Player $who, array $items,int $invType, string $name){
        $this->who = $who;
        $this->items = $items;
        $this->invType = $invType;
        $this->name = $name;
    }

    /**
     * @return Player
     */
    public function getPlayer() : Player{
        return $this->who;
    }
    
    /**
     * @return int
     */
    public function getInventoryType() : int{
        return $this->invType;
    }
    
    /**
     * @return Item
     */
    public function getItems() : array{
        return $this->items;
    }
    
    /**
     * @return string
     */
    public function getMenuName() : string{
        return $this->name;
    }
}
<?php
namespace korado531m7\InventoryMenuAPI;

use korado531m7\InventoryMenuAPI\event\InventoryMenuClickEvent;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\event\Listener;
use pocketmine\event\inventory\InventoryTransactionEvent;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\math\Vector3;

class EventListener implements Listener{
    private $plugin;
    
    public function __construct(InventoryMenuAPI $plugin){
        $this->plugin = $plugin;
    }
    
    public function onTransactionInventory(InventoryTransactionEvent $event){
        $object = $event->getTransaction()->getSource();
        if($object instanceof Player){
            if($this->plugin->isOpeningInventoryMenu($object)){
                $event->setCancelled();
                $this->plugin->restoreInventory($object);
            }
        }
    }
    
    public function onReceive(DataPacketReceiveEvent $event){
        $pk = $event->getPacket();
        $player = $event->getPlayer();
        switch(\get_class($pk)){
            case 'pocketmine\network\mcpe\protocol\ContainerClosePacket':
                $this->plugin->closeInventoryMenu($player);
            break;
                
            case 'pocketmine\network\mcpe\protocol\InventoryTransactionPacket':
                if($this->plugin->isOpeningInventoryMenu($player) && array_key_exists(0,$pk->actions)){
                    $action = $pk->actions[0];
                    $data = $this->plugin->getData($player);
                    $itemresult = $action->oldItem;
                    if($action->oldItem->getId() == 0) $itemresult = $action->newItem;
                    Server::getInstance()->getPluginManager()->callEvent(new InventoryMenuClickEvent($player, $itemresult,$data[4]));
                    $this->plugin->closeInventoryMenu($player);
                }
            break;
        }
    }
}<?php
namespace korado531m7\InventoryMenuAPI\inventory; 

use pocketmine\math\Vector3;
use pocketmine\inventory\CustomInventory;

class FakeInventory extends CustomInventory{

    /** @var int */
    protected $network_type;
    protected $title;
    protected $size;

    public function __construct(int $network_type, Vector3 $holder, array $items = [], int $size = null, string $title = 'Inventory Menu'){
        $this->network_type = $network_type;
        $this->title = $title;
        $this->size = $size;
        parent::__construct($holder, $items, $size, $title);
    }

    public function getNetworkType() : int{
        return $this->network_type;
    }
    
    public function getName() : string{
        return $this->title;
    }
    
    public function getDefaultSize() : int{
        return $this->size;
    }
}<?php
namespace korado531m7\InventoryMenuAPI;

use korado531m7\InventoryMenuAPI\event\InventoryMenuCloseEvent;
use korado531m7\InventoryMenuAPI\event\InventoryMenuGenerateEvent;
use korado531m7\InventoryMenuAPI\task\DelayAddWindowTask;
use korado531m7\InventoryMenuAPI\task\DelaySendInventoryTask;
use korado531m7\InventoryMenuAPI\inventory\FakeInventory;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\block\BlockFactory;
use pocketmine\block\BlockIds;
use pocketmine\item\Item;
use pocketmine\level\Position;
use pocketmine\math\Vector3;
use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\types\WindowTypes;
use pocketmine\plugin\PluginBase;

class InventoryMenuAPI extends PluginBase{
    private static $inventoryMenuVar = [];
    private static $inventory = [];
    private static $pluginbase;
    
    const INVENTORY_TYPE_CHEST = 1;
    const INVENTORY_TYPE_DOUBLE_CHEST = 2;
    const INVENTORY_TYPE_ENCHANTING_TABLE = 3;
    const INVENTORY_TYPE_HOPPER = 4;
    const INVENTORY_TYPE_BREWING_STAND = 5;
    const INVENTORY_TYPE_ANVIL = 6;
    const INVENTORY_TYPE_DISPENSER = 7;
    const INVENTORY_TYPE_DROPPER = 8;
    const INVENTORY_TYPE_BEACON = 9;
    const INVENTORY_TYPE_TRADING = 10; //Not implemented yet :(
    const INVENTORY_TYPE_COMMAND_BLOCK = 11; //Not implemented either
    
    public function onEnable(){
        $this->getServer()->getPluginManager()->registerEvents(new EventListener($this), $this);
        self::setPluginBase($this);
    }
    
    /**
     * Send an inventory menu to player
     *
     * @param Player  $player
     * @param Item[]  $items
     * @param string  $inventoryName
     * @param int     $inventoryType
     */
    public static function sendInventoryMenu(Player $player, array $items, $inventoryName = "Inventory Menu", $inventoryType = self::INVENTORY_TYPE_CHEST){
        if(self::isOpeningInventoryMenu($player)) return true;
        $x = (int) $player->x;
        $y = (int) $player->y + 4;
        $z = (int) $player->z;
        
        //if(count($items) === 0) $maxKey = 0; else $maxKey = max(array_keys($items));
        switch($inventoryType){
            default:
                throw new \InvalidArgumentException('Invalid Inventory Type');
            break;
            
            case self::INVENTORY_TYPE_DISPENSER:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::DISPENSER);
                $inv = new FakeInventory(WindowTypes::DISPENSER, new Vector3($x, $y, $z), [], 9);
            break;
            
            case self::INVENTORY_TYPE_DROPPER:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::DROPPER);
                $inv = new FakeInventory(WindowTypes::DROPPER, new Vector3($x, $y, $z), [], 9);
            break;
            
            case self::INVENTORY_TYPE_BEACON:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::BEACON);
                $inv = new FakeInventory(WindowTypes::BEACON, new Vector3($x, $y, $z), [], 1); //?
            break;
            
            case self::INVENTORY_TYPE_TRADING:
                throw new \RuntimeException('Trading Inventory is not supported on account of not impletented yet :(');
                //$inv = new FakeInventory(WindowTypes::TRADING, new Vector3($x, $y, $z), [], 27);
            break;
            
            case self::INVENTORY_TYPE_COMMAND_BLOCK:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::COMMAND_BLOCK);
                $inv = new FakeInventory(WindowTypes::COMMAND_BLOCK, new Vector3($x, $y, $z), [], 0);
            break;
            
            case self::INVENTORY_TYPE_CHEST:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::CHEST);
                $inv = new FakeInventory(WindowTypes::CONTAINER, new Vector3($x, $y, $z), [], 27);
            break;
            
            case self::INVENTORY_TYPE_ANVIL:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::ANVIL);
                $inv = new FakeInventory(WindowTypes::ANVIL, new Vector3($x, $y, $z), [], 27);
            break;
            
            case self::INVENTORY_TYPE_ENCHANTING_TABLE:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::ENCHANTING_TABLE);
                $inv = new FakeInventory(WindowTypes::ENCHANTMENT, new Vector3($x, $y, $z), [], 5);
            break;
            
            case self::INVENTORY_TYPE_BREWING_STAND:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::BREWING_STAND_BLOCK);
                $inv = new FakeInventory(WindowTypes::BREWING_STAND, new Vector3($x, $y, $z), [], 5); //5?
            break;
            
            case self::INVENTORY_TYPE_HOPPER:
                self::sendFakeBlock($player, $x, $y, $z, BlockIds::HOPPER_BLOCK);
                $inv = new FakeInventory(WindowTypes::HOPPER, new Vector3($x, $y, $z), [], 5);
            break;
                
            case self::INVENTORY_TYPE_DOUBLE_CHEST:
                self::sendFakeBlock($player, $x, $y, $z,BlockIds::CHEST);
                self::sendFakeBlock($player, $x, $y, $z + 1,BlockIds::CHEST);
                $tag = new CompoundTag();
                $tag->setInt('pairx', $x);
                $tag->setInt('pairz', $z);
                self::sendTagData($player, $tag, $x, $y, $z + 1);
                $inv = new FakeInventory(WindowTypes::CONTAINER, new Vector3($x, $y, $z), [], 54);
            break;
        }
        $tag = new CompoundTag();
        $tag->setString('CustomName', $inventoryName);
        self::sendTagData($player, $tag, $x, $y, $z);
        
        self::saveInventory($player);
        foreach($items as $itemkey => $item){
            $inv->setItem($itemkey,$item);
        }
        Server::getInstance()->getPluginManager()->callEvent(new InventoryMenuGenerateEvent($player,$items,$inventoryType,$inventoryName));
        switch($inventoryType){
            case self::INVENTORY_TYPE_ENCHANTING_TABLE:
            case self::INVENTORY_TYPE_HOPPER:
            case self::INVENTORY_TYPE_CHEST:
            case self::INVENTORY_TYPE_BREWING_STAND:
            case self::INVENTORY_TYPE_ANVIL:
            case self::INVENTORY_TYPE_DISPENSER:
            case self::INVENTORY_TYPE_DROPPER:
            case self::INVENTORY_TYPE_BEACON:
                self::$inventoryMenuVar[$player->getName()] = array($inventoryType,$x,$y,$z,$inventoryName);
            case self::INVENTORY_TYPE_COMMAND_BLOCK:
            case self::INVENTORY_TYPE_TRADING:
                $player->addWindow($inv);
            break;
            
            case self::INVENTORY_TYPE_DOUBLE_CHEST:
                self::$inventoryMenuVar[$player->getName()] = array(self::INVENTORY_TYPE_DOUBLE_CHEST,$x,$y,$z,$inventoryName);
                self::getPluginBase()->getScheduler()->scheduleDelayedTask(new DelayAddWindowTask($player,$inv), 10);
            break;
        }
    }
    
    /**
     * @param Player  $player
     * @param Item[]  $items
     * @param string  $inventoryName
     * @param int     $inventoryType
     */
    public static function fillInventoryMenu(Player $player, array $items, $inventoryName = "Fill Menu", $inventoryType = self::INVENTORY_TYPE_CHEST){
        self::closeInventoryMenu($player); //Need this?
        self::getPluginBase()->getScheduler()->scheduleDelayedTask(new DelaySendInventoryTask($player,$items, $inventoryName,$inventoryType), 10);
    }
    
    /**
     * Close an inventory menu if player is opening
     *
     * @param Player $player
     */
    public static function closeInventoryMenu(Player $player){
        if(!self::isOpeningInventoryMenu($player)) return true;
        $data = self::getData($player);
        Server::getInstance()->getPluginManager()->callEvent(new InventoryMenuCloseEvent($player, $data[4]));
        switch($data[0]){
            case self::INVENTORY_TYPE_DOUBLE_CHEST:
                self::sendFakeBlock($player,$data[1],$data[2],$data[3] + 1,BlockIds::AIR);
            case self::INVENTORY_TYPE_CHEST:
            case self::INVENTORY_TYPE_HOPPER:
            case self::INVENTORY_TYPE_BREWING_STAND:
            case self::INVENTORY_TYPE_ENCHANTING_TABLE:
            case self::INVENTORY_TYPE_ANVIL:
            case self::INVENTORY_TYPE_DISPENSER:
            case self::INVENTORY_TYPE_DROPPER:
            case self::INVENTORY_TYPE_BEACON:
            case self::INVENTORY_TYPE_TRADING:
            case self::INVENTORY_TYPE_COMMAND_BLOCK:
                self::sendFakeBlock($player,$data[1],$data[2],$data[3],BlockIds::AIR);
            break;
        }
        self::restoreInventory($player, true);
        unset(self::$inventoryMenuVar[$player->getName()]);
    }
    
    /**
     * Check whether player is opening inventory menu
     *
     * @param  Player $player
     * @return bool
     */
    public static function isOpeningInventoryMenu(Player $player) : bool{
        return array_key_exists($player->getName(),self::$inventoryMenuVar);
    }
    
    /**
     * @param Player  $player
     * @return array
     */
    public static function getData(Player $player) : array{
        return self::$inventoryMenuVar[$player->getName()] ?? [];
    }
    
    public static function saveInventory(Player $player){
        self::$inventory[$player->getName()] = $player->getInventory()->getContents();
    }
    
    public static function restoreInventory(Player $player, bool $reset = false){
        $inventory = self::$inventory[$player->getName()] ?? null;
        if($inventory === null) return false;
        $player->getInventory()->setContents($inventory);
        if($reset) unset($inventory[$player->getName()]);
    }
    
    private static function getPluginBase() : PluginBase{
        return self::$pluginbase;
    }
    
    private static function setPluginBase(PluginBase $plugin){
        self::$pluginbase = $plugin;
    }
    
    private static function sendTagData(Player $player, CompoundTag $tag, int $x, int $y, int $z){
        $writer = new NetworkLittleEndianNBTStream();
        $pk = new BlockEntityDataPacket;
        $pk->x = $x;
        $pk->y = $y;
        $pk->z = $z;
        $pk->namedtag = $writer->write($tag);
        $player->dataPacket($pk);
    }
    
    private static function sendFakeBlock(Player $player,int $x,int $y,int $z,int $blockid){
        $pk = new UpdateBlockPacket();
        $pk->x = $x;
        $pk->y = $y;
        $pk->z = $z;
        $pk->flags = UpdateBlockPacket::FLAG_ALL;
        $pk->blockRuntimeId = BlockFactory::toStaticRuntimeId($blockid);
        $player->dataPacket($pk);
    }
}<?php
namespace korado531m7\InventoryMenuAPI\task;

use pocketmine\scheduler\Task;
use pocketmine\Player;
use pocketmine\item\Item;

class DelayAddWindowTask extends Task{
    public function __construct(Player $player,$inventory){
        $this->who = $player;
        $this->inventory = $inventory;
    }
    
    public function onRun(int $tick) : void{
        $this->who->addWindow($this->inventory);
    }
}
<?php
namespace korado531m7\InventoryMenuAPI\task;

use korado531m7\InventoryMenuAPI\InventoryMenuAPI;
use pocketmine\scheduler\Task;
use pocketmine\Player;
use pocketmine\item\Item;

class DelaySendInventoryTask extends Task{
    public function __construct($player,$items, $inventoryName,$inventoryType){
        $this->player = $player;
        $this->items = $items;
        $this->inventoryName = $inventoryName;
        $this->inventoryType = $inventoryType;
    }
    
    public function onRun(int $tick) : void{
        InventoryMenuAPI::sendInventoryMenu($this->player,$this->items, $this->inventoryName,$this->inventoryType);
    }
}
<?php
namespace metowa1227;

use pocketmine\plugin\PluginBase;
use pocketmine\event\Listener;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\block\Block;
use pocketmine\utils\Config;
use pocketmine\command\ConsoleCommandSender;
use pocketmine\Player;
use pocketmine\math\Vector3;

use korado531m7\InventoryMenuAPI\InventoryMenuAPI;

class CommandBlock extends PluginBase implements Listener
{
	public function onEnable()
	{
		$this->getServer()->getPluginManager()->registerEvents($this, $this);
		$path = $this->getDataFolder();
		@mkdir($path);
		$this->saveData = new Config($path . "CommandBlocks.yml", Config::YAML);
	}

	public function onTouch(PlayerInteractEvent $event) : void
	{
		$player = $event->getPlayer();
		$block = $event->getBlock();
		if ($block->getId() !== Block::COMMAND_BLOCK)
			return;
		if ($event->getAction() === PlayerInteractEvent::LEFT_CLICK_BLOCK)
			return;
		switch ($player->getGamemode()) {
			case 1:
				InventoryMenuAPI::sendInventoryMenu($player, [], "", InventoryMenuAPI::INVENTORY_TYPE_COMMAND_BLOCK);
				$this->blockData[$player->getName()] = $block;
				return;
			case 0:
				$this->runCommand($player, $block);
				return;
		}
	}

	public function onBreak(BlockBreakEvent $event)
	{
		$block = $event->getBlock();
		$x = round($block->x);
		$y = round($block->y);
		$z = round($block->z);
		$level = $block->getLevel()->getName();
		$pos = $x . ':' . $y . ':' . $z . ':' . $level;
		if (!$this->saveData->exists($pos))
			return;
		$this->saveData->remove($pos);
		$this->saveData->save();
	}

	private function runCommand(Player $player, $block)
	{
		$x = round($block->x);
		$y = round($block->y);
		$z = round($block->z);
		$level = $block->getLevel()->getName();
		$name = $player->getName();
		$pos = $x . ':' . $y . ':' . $z . ':' . $level;
		if (!$this->saveData->exists($pos))
			return;
		$data = $this->saveData->get($pos);
		if ($data["sender"] === "CONSOLE")
			$sender = new ConsoleCommandSender();
		else
			$sender = $player;
		$command = $data["command"];
		$keys = ["@s", "@p", "@r"];
		$nearest = $block->getLevel()->getNearestEntity(new Vector3($player->x, $player->y, $player->z), 100.00);
		if (empty($nearest))
			$nearest = $name;
		$online = $this->getServer()->getOnlinePlayers();
		$count = count($online);
		$rand = mt_rand(0, $count);
		$i = 0;
		$random = $player;
		foreach ($online as $players) {
			if ($i === $rand)
				$random = $players;
			$i++;
		}
		$replace = [$name, $nearest->getName(), $random->getName()];
		$result = str_replace($keys, $replace, $command);
		if (strpos($result, "@a") !== false || strpos($result, "@e") !== false) {  //Player only supported.
			foreach ($online as $players) {
				$result = str_replace(["@a", "@e"], [$name, $name], $result);
				$this->getServer()->dispatchCommand($players, $result);
			}
			return;
		}
		$this->getServer()->dispatchCommand($sender, $result);
	}

	public function onReceive(DataPacketReceiveEvent $event)
	{
		$packet = $event->getPacket();
		if ($packet instanceof CommandBlockUpdatePacket) {
			$player = $event->getPlayer();
			$name = $player->getName();
			if (!isset($this->blockData[$name]))
				return;
			$block = $this->blockData[$name];
			/**
			 * Since an incorrect value is returned, it is not used
				$x = round($packet->x);
				$y = round($packet->y);
				$z = round($packet->z);
			**/
			$x = round($block->x);
			$y = round($block->y);
			$z = round($block->z);
			$level = $block->getLevel()->getName();
			$pos = $x . ':' . $y . ':' . $z . ':' . $level;
			$sender = ($packet->isConditional) ? 'CONSOLE' : 'PLAYER';
			$this->saveData->set($pos, [
				"command" => $packet->command,
				"sender" => $sender
			]);
			$this->saveData->save();
			unset($this->blockData[$name]);
		}
	}
}
h6*8HéåØçYwÓ•ŠáÈžêô   GBMB