
<?php
echo "PocketMine-MP plugin Friend v1.0.07
This file has been generated using DevTools v1.13.0 at Wed, 19 Jun 2019 00:54:44 +0930
----------------
";

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(); ?>
  (           ò   a:9:{s:4:"name";s:6:"Friend";s:7:"version";s:6:"1.0.07";s:4:"main";s:4:"Main";s:3:"api";i:3;s:6:"depend";s:0:"";s:11:"description";s:27:"ãƒ•ãƒ¬ãƒ³ãƒ‰æ©Ÿèƒ½ã‚’è¿½åŠ ";s:7:"authors";s:0:"";s:7:"website";s:0:"";s:12:"creationDate";i:1560871484;}
   plugin.ymlo   =	]o   À¶         resources/Config.ymlû   =	]û   ƒe°Q¶         src/api/FriendApi.phpâ  =	]â  ¬é³¶         src/api/send_main_ui.phpß  =	]ß  —@Ë&¶         src/api/type/NoticeType.php¿   =	]¿   =Ð6¶         src/command/command_chat.php  =	]  jÏz¼¶         src/command/command_friend.phpÌ  =	]Ì  +˜‹¶      .   src/event/form/receive/friend_chat_receive.php¤  =	]¤  R°ó…¶      )   src/event/form/receive/friend_receive.php¸
  =	]¸
  ?v“¶      '   src/event/form/receive/list_receive.phpž  =	]ž  ž4 ¸¶      *   src/event/form/receive/list_re_receive.php—  =	]—  «ƒjð¶      )   src/event/form/receive/online_receive.php=  =	]=  Ô•…W¶      ,   src/event/form/receive/online_re_receive.php,  =	],  þÐž1¶      *   src/event/form/receive/request_receive.phpÁ  =	]Á  '„±¶      -   src/event/form/receive/request_re_receive.php¦  =	]¦  `Ñ«á¶      /   src/event/form/receive/send_request_receive.php  =	]  Yßi¿¶      /   src/event/form/receive/sent_request_receive.php  =	]  â)•¶      2   src/event/form/receive/sent_request_re_receive.php
  =	]
  4øH¶         src/event/player/PlayerChat.phpí  =	]í  û±B…¶      !   src/event/player/PlayerDamage.php
  =	]
  'qíl¶      #   src/event/player/PlayerDropItem.phpî  =	]î   Õ¶      #   src/event/player/PlayerInteract.php¬  =	]¬  òw¶         src/event/player/PlayerJoin.phpï  =	]ï  8Íý¶         src/event/player/PlayerQuit.phpV  =	]V  i6‚%¶         src/Main.phpç  =	]ç  B
P¶      )   src/tokyo/pmmp/libform/element/Button.phpQ  =	]Q  Iz„¶      +   src/tokyo/pmmp/libform/element/Dropdown.php^
  =	]^
  )_Ý¶      *   src/tokyo/pmmp/libform/element/Element.php
  =	]
  6ñN0¶      (   src/tokyo/pmmp/libform/element/Image.php»  =	]»  qÐ¸™¶      (   src/tokyo/pmmp/libform/element/Input.phpØ  =	]Ø  f/…¶      (   src/tokyo/pmmp/libform/element/Label.php=  =	]=  0]~å¶      )   src/tokyo/pmmp/libform/element/Slider.phph
  =	]h
  WÒ±È¶      -   src/tokyo/pmmp/libform/element/StepSlider.phpd
  =	]d
  X†È¶      )   src/tokyo/pmmp/libform/element/Toggle.php£  =	]£  khÏ¶      (   src/tokyo/pmmp/libform/EventListener.phpr  =	]r  >|Z’¶      *   src/tokyo/pmmp/libform/form/CustomForm.php)  =	])  ë¦Û¶      $   src/tokyo/pmmp/libform/form/Form.phpé  =	]é  Û+o¶      (   src/tokyo/pmmp/libform/form/ListForm.php@  =	]@  È(Ðm¶      )   src/tokyo/pmmp/libform/form/ModalForm.phpM  =	]M  ø>µ§¶      "   src/tokyo/pmmp/libform/FormApi.php<  =	]<  dPìB¶      name: Friend
main: Main
version: 1.0.07
api: 3
author: metowa1227
description: ãƒ•ãƒ¬ãƒ³ãƒ‰æ©Ÿèƒ½ã‚’è¿½åŠ # ç™»éŒ²å¯èƒ½ãªãƒ•ãƒ¬ãƒ³ãƒ‰ã®æœ€å¤§æ•°, -1 ã§ç„¡åˆ¶é™
max_friend: -1
# ãƒ•ãƒ¬ãƒ³ãƒ‰ã¸ã®ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ, true ã§æœ‰åŠ¹ã€false ã§ç„¡åŠ¹
teleport: true
# ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªãƒ¼ãƒ•ã‚¡ã‚¤ã‚¢, true ã§æœ‰åŠ¹ã€false ã§ç„¡åŠ¹
friendly_fire: false<?php
namespace api;

use pocketmine\Server;
use pocketmine\utils\Config;
use pocketmine\utils\TextFormat;

class FriendApi implements \api\type\NoticeType
{
	static $instance;
	private $config, $friend_data_file, $friend_data, $friend_request_file, $friend_request, $friend_chat_file, $friend_chat;

	function __construct(\Main $owner)
	{
		$this->initFiles($owner);
		self::$instance = $this;
	}

	private function initFiles($owner): void
	{
		$owner->saveResource("Config.yml", false);
		$this->config = (new Config($owner->getDataFolder() . "Config.yml", Config::YAML))->getAll();
		$this->friend_data_file = new Config($owner->getDataFolder() . "FriendData.yml", Config::YAML);
		$this->friend_request_file = new Config($owner->getDataFolder() . "FriendRequest.yml", Config::YAML);
		$this->friend_chat_file = new Config($owner->getDataFolder() . "FriendChat.yml", Config::YAML);
		$this->friend_chat = $this->friend_chat_file->getAll();
		$this->friend_data = $this->friend_data_file->getAll();
		$this->friend_request = $this->friend_request_file->getAll();	
	}

	function save(): void
	{
		$this->friend_data_file->setAll($this->friend_data);
		$this->friend_request_file->setAll($this->friend_request);
		$this->friend_chat_file->setAll($this->friend_chat);
		$this->friend_data_file->save();
		$this->friend_request_file->save();
		$this->friend_chat_file->save();
	}

	function notice(string $name, int $type, string $target = "")
	{
		switch ($type) {
			case self::NOTICE_TYPE_JOIN:
				foreach ($this->getOnlineFriends($name) as $friend) {
					Server::getInstance()->getPlayer($friend)->sendMessage(TextFormat::BOLD . "[" . TextFormat::GREEN . "+" . TextFormat::WHITE . "] " . $name . " ã•ã‚“ãŒã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã«ãªã‚Šã¾ã—ãŸã€‚");
				}
				return;
			case self::NOTICE_TYPE_QUIT:
				foreach ($this->getOnlineFriends($name) as $friend) {
					Server::getInstance()->getPlayer($friend)->sendMessage(TextFormat::BOLD . "[" . TextFormat::RED . "-" . TextFormat::WHITE . "] " . $name . " ã•ã‚“ãŒã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã«ãªã‚Šã¾ã—ãŸã€‚");
				}
				return;
			case self::NOTICE_TYPE_REQUEST:
				$player = Server::getInstance()->getPlayer($name);
				if ($player->getName() === $target)
					return;
				if ($player !== null) {
					$player->sendMessage(TextFormat::GRAY . "[Friend] " . $target . " ã•ã‚“ãŒã‚ãªãŸã¨ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚ŠãŸãŒã£ã¦ã„ã¾ã™ã€‚");
					$player->sendMessage(TextFormat::GRAY . "[Friend] ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®æ‹’å¦æ‰¿èªã¯ /friend ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‹ã‚‰è¡Œãˆã¾ã™ã€‚");
				}
				return;
			case self::NOTICE_TYPE_REQUEST_ACCEPTED:
				$player = Server::getInstance()->getPlayer($target);
				if ($player !== null)
					$player->sendMessage(TextFormat::GREEN . "[Friend] " . $name . " ã•ã‚“ã¨ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚Šã¾ã—ãŸã€‚");
				return;
		}
	}

	function getConfig(): array
	{
		return $this->config;
	}

	function getChatPartner(string $name): string
	{
		return isset($this->friend_chat[$name]) ? $this->friend_chat[$name] : "";
	}

	function setChatPartner(string $name, string $friend): void
	{
		$this->friend_chat[$name] = $friend;
	}

	function createAccount(string $name): void
	{
		if ($this->existsAccount($name))
			return;

		$this->friend_request[$name] = [];
		$this->friend_data[$name] = [];
	}

	function existsAccount(string $name): bool
	{
		return isset($this->friend_data[$name]);
	}

	function addFriend(string $name, string $friend): void
	{
		$this->friend_data[$name][$friend] = true;
		$this->friend_data[$friend][$name] = true;
	}

	function removeFriend(string $name, string $friend): void
	{
		unset($this->friend_data[$name][$friend]);
		unset($this->friend_data[$friend][$name]);
	}

	function isFriend(string $name, string $target): bool
	{
		return isset($this->friend_data[$name][$target]);
	}

	function getFriendList(string $name): array
	{
		return $this->friend_data[$name];
	}

	function getOnlineFriends(string $name): array
	{
		$result = [];
		foreach (Server::getInstance()->getOnlinePlayers() as $online) {
			if (in_array($online->getName(), array_keys($this->getFriendList($name)), true)) {
				$result[] = $online->getName();
			}
		}
		return $result;
	}

	function getFriendRequests(string $name, bool $sent = false): array
	{
		$result = [];
		foreach ($this->friend_request[$name] as $user => $from) {
			if ($from === $sent)
				$result[] = $user;
		}
		return $result;
	}

	function addFriendRequest(string $name, string $from): void
	{
		if (isset($this->friend_request[$name][$from]))
			return;

		$this->friend_request[$name][$from] = false;
		$this->friend_request[$from][$name] = true;
	}

	function removeFriendRequest(string $name, string $from): void
	{
		unset($this->friend_request[$name][$from]);
		unset($this->friend_request[$from][$name]);
	}

	function acceptFriendRequest(string $name, string $from): void
	{
		$this->removeFriendRequest($name, $from);
		$this->addFriend($name, $from);
	}
}
<?php
namespace api;

use pocketmine\utils\TextFormat;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Button;

trait send_main_ui
{
	function sendUi(\pocketmine\Player $player): void
	{
    	$friend_api = FriendApi::$instance;
    	$name = $player->getName();
    	$friend_request_button = (count($friend_api->getFriendList($name)) >= $friend_api->getConfig()["max_friend"]) ? TextFormat::RED . "ãƒ•ãƒ¬ãƒ³ãƒ‰äººæ•°ãŒæœ€å¤§ã§ã™" : "ãƒ•ãƒ¬ãƒ³ãƒ‰ç”³è«‹";
    	$friend_request_button = ($friend_api->getConfig()["max_friend"] === -1) ? "ãƒ•ãƒ¬ãƒ³ãƒ‰ç”³è«‹" : $friend_request_button;
        FormApi::makeListForm([new \event\form\receive\friend_receive, "receiveResponse"])
	        ->addButton(new Button("ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ (" . count($friend_api->getOnlineFriends($name)) . ")"))
	        ->addButton(new Button($friend_request_button))
	        ->addButton(new Button("ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ (" . count($friend_api->getFriendRequests($name)) . ")"))
	        ->addButton(new Button("ç”³è«‹ä¸­ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ (" . count($friend_api->getFriendRequests($name, true)) . ")"))
	        ->addButton(new Button("ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¹ãƒˆ (" . count($friend_api->getFriendList($name)) . " / " . (($friend_api->getConfig()["max_friend"] === -1) ? "ç„¡åˆ¶é™" : $friend_api->getConfig()["max_friend"]) . ")"))
	        ->setTitle(TextFormat::BOLD . TextFormat::DARK_GREEN . "Friend " . PLUGIN_VERSION)
	        ->sendToPlayer($player);
	}
}<?php
namespace api\type;

interface NoticeType
{
	const NOTICE_TYPE_JOIN = 0;
	const NOTICE_TYPE_QUIT = 1;
	const NOTICE_TYPE_REQUEST = 2;
	const NOTICE_TYPE_REQUEST_ACCEPTED = 3;
}<?php
namespace command;

use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\utils\TextFormat;
use pocketmine\item\Item;

use api\FriendApi;

class command_chat extends Command
{
    const CMD_FRIEND_CHAT_COMMAND = 'friendchat';
    const CMD_FRIEND_CHAT_DESCRIPTION = "ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒãƒ£ãƒƒãƒˆã¨è¨­å®šãŒã§ãã¾ã™ã€‚";
    const CMD_FRIEND_CHAT_USAGE = "/friendchat <get/remove>";

    function __construct()
    {
        parent::__construct(self::CMD_FRIEND_CHAT_COMMAND, self::CMD_FRIEND_CHAT_DESCRIPTION, self::CMD_FRIEND_CHAT_USAGE);
        $this->setPermission("friend.command.friendchat");
    }

    function execute(CommandSender $sender, string $label, array $args): bool
    {
        $name = $sender->getName();
        $item = Item::get(421)->setCustomName(TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . FriendApi::$instance->getChatPartner($name));
        if (!isset($args[0])) {
            $sender->sendMessage($this->getUsage());
            return false;
        }

        if ($args[0] === "get") {

            if ($sender->getInventory()->contains($item)) {
                $sender->sendMessage(TextFormat::YELLOW . "æ—¢ã«ã‚¢ã‚¤ãƒ†ãƒ ã‚’æ‰€æœ‰ã—ã¦ã„ã¾ã™ã€‚");
                return true;
            }
            if (!$sender->getInventory()->canAddItem($item)) {
                $sender->sendMessage(TextFormat::YELLOW . "ã‚¤ãƒ³ãƒ™ãƒ³ãƒˆãƒªã«ç©ºãã‚¹ãƒ­ãƒƒãƒˆãŒã‚ã‚Šã¾ã›ã‚“ã€‚");
                return true;
            }

            $sender->getInventory()->addItem($item);

        } elseif ($args[0] === "remove") {

            if (!$sender->getInventory()->contains($item)) {
                $sender->sendMessage(TextFormat::YELLOW . "ã‚¢ã‚¤ãƒ†ãƒ ã‚’æ‰€æœ‰ã—ã¦ã„ã¾ã›ã‚“ã€‚");
                return true;
            }

            $sender->getInventory()->removeItem($item);

        } else {
            $sender->sendMessage($this->getUsage());
            return false;
        }

	    return true;
    }
}
<?php
namespace command;

use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\utils\TextFormat;

class command_friend extends Command
{
	use \api\send_main_ui;

	const CMD_FRIEND_COMMAND = 'friend';
	const CMD_FRIEND_DESCRIPTION = "Friend ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’è¡¨ç¤ºã—ã¾ã™";
	const CMD_FRIEND_USAGE = "/friend";

    function __construct()
    {
        parent::__construct(self::CMD_FRIEND_COMMAND, self::CMD_FRIEND_DESCRIPTION, self::CMD_FRIEND_USAGE);
        $this->setPermission("friend.command.friend");
    }

    function execute(CommandSender $sender, string $label, array $args): bool
    {
    	$this->sendUi($sender);
	    return true;
    }
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;
use pocketmine\item\Item;

use tokyo\pmmp\libform\FormApi;

use api\FriendApi;

class friend_chat_receive
{
	private $friends;

	function setFriendList(array $friends)
	{
		$this->friends = $friends;
	}

	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($key))
			return;

		$friend_name = current(array_slice($this->friends, $key, 1, true));
		$item = Item::get(421)->setCustomName(TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . $friend_api->getChatPartner($name));
		$player->getInventory()->removeItem($item);
		$item = $item->setCustomName(TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . $friend_name);
		$player->getInventory()->addItem($item);
		$friend_api->setChatPartner($name, $friend_name);
		$player->sendMessage("ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒãƒ£ãƒƒãƒˆã®é€ä¿¡å…ˆã‚’ " . $friend_name . " ã•ã‚“ã«è¨­å®šã—ã¾ã—ãŸã€‚");
		$player->sendMessage("åæœ­ã‚’æ¨ã¦ãŸã„å ´åˆã¯ /friendchat remove ã¨å®Ÿè¡Œã—ã¦ãã ã•ã„ã€‚");
	}
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Button;
use tokyo\pmmp\libform\element\Input;
use api\FriendApi;

class friend_receive
{
	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($key))
			return;

		switch ($key) {
			case 0:
				$friends = [];
		        $form = FormApi::makeListForm([$receive = new online_receive, "receiveResponse"]);
				foreach ($friend_api->getOnlineFriends($name) as $friend) {
			        $form->addButton(new Button($friend));
			        $friends[] = $friend;
				}
				$receive->setFriendList($friends);
				$form->addButton(new Button("æˆ»ã‚‹"))
			        ->setTitle(TextFormat::BOLD . TextFormat::DARK_GREEN . "ONLINE FRIENDS")
			        ->sendToPlayer($player);
				break;
			case 1:
				FormApi::makeCustomForm([new send_request_receive, "receiveResponse"])
					->addElement(new Input("ãƒ—ãƒ¬ã‚¤ãƒ¤ãƒ¼åã‚’å…¥åŠ›ã—ã¦ãã ã•ã„", "ãƒ—ãƒ¬ã‚¤ãƒ¤ãƒ¼å..."))
					->setTitle("ãƒ•ãƒ¬ãƒ³ãƒ‰ç”³è«‹")
					->sendToPlayer($player);
				break;
			case 2:
				$requests = [];
		        $form = FormApi::makeListForm([$receive = new request_receive, "receiveResponse"]);
		        foreach ($friend_api->getFriendRequests($name) as $request) {
		        	$form->addButton(new Button($request));
		        	$requests[] = $request;
		        }
		        $receive->setRequests($requests);
		        $form->addButton(new Button("æˆ»ã‚‹"))
			    	->setTitle(TextFormat::BLUE . TextFormat::BOLD . "ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ")
			    	->sendToPlayer($player);
				break;
			case 3:
				$requests = [];
		        $form = FormApi::makeListForm([$receive = new sent_request_receive, "receiveResponse"]);
		        foreach ($friend_api->getFriendRequests($name, true) as $request) {
		        	$form->addButton(new Button($request));
		        	$requests[] = $request;
		        }
		        $receive->setRequests($requests);
		        $form->addButton(new Button("æˆ»ã‚‹"))
			    	->setTitle(TextFormat::BLUE . TextFormat::BOLD . "ç”³è«‹ä¸­ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ")
			    	->sendToPlayer($player);
				break;
			case 4:
		        $form = FormApi::makeListForm([new list_receive, "receiveResponse"]);
		        foreach ($friend_api->getFriendList($name) as $friend => $from) {
		        	$form->addButton(new Button($friend));
		        }
		        $form->addButton(new Button("æˆ»ã‚‹"))
			    	->setTitle(TextFormat::BLUE . TextFormat::BOLD . "ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¹ãƒˆ")
			    	->sendToPlayer($player);
				break;
		}
	}
}<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Button;

use api\FriendApi;

class list_receive
{
	use \api\send_main_ui;

	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($key))
			return;

		if (empty($list = $friend_api->getFriendList($name)) || $key === count($list)) {
			$this->sendUi($player);
			return;
		}

		$friend_name = key(array_slice($list, $key, 1, true));
        FormApi::makeListForm([new list_re_receive($friend_name), "receiveResponse"])
	        ->addButton(new Button(TextFormat::DARK_RED . "ãƒ•ãƒ¬ãƒ³ãƒ‰ã‚’è§£é™¤"))
			->addButton(new Button("æˆ»ã‚‹"))
	        ->setTitle(TextFormat::DARK_GREEN . $friend_name)
	        ->sendToPlayer($player);
	}
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;

use api\FriendApi;

class list_re_receive implements \api\type\NoticeType
{
	use \api\send_main_ui;

	private $friend_name;

	function __construct(string $friend_name)
	{
		$this->friend_name = $friend_name;
	}

	function receiveResponse(Player $player, ?int $key)
	{
		if (FormApi::formCancelled($key))
			return;

		if ($key === 0) {
	        FormApi::makeModalForm([$this, "removeFriendReceive"])
	        	->setButtonText(true, TextFormat::DARK_RED . "è§£é™¤")
	        	->setButtonText(false, "ã‚­ãƒ£ãƒ³ã‚»ãƒ«")
	        	->setContent("æœ¬å½“ã« " . $this->friend_name . " ã¨ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ã‚’è§£é™¤ã—ã¾ã™ã‹?\nè§£é™¤ã—ã¦ã‚‚å†åº¦ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚\n\nãƒ•ãƒ¬ãƒ³ãƒ‰ã‚’è§£é™¤ã—ã¦ã‚‚ç›¸æ‰‹ã«ã¯é€šçŸ¥ã•ã‚Œã¾ã›ã‚“ã€‚")
		        ->setTitle(TextFormat::DARK_GREEN . $this->friend_name . " ã®ãƒ•ãƒ¬ãƒ³ãƒ‰è§£é™¤")
		        ->sendToPlayer($player);
		} else {
			$this->sendUi($player);
		}
	}

	function removeFriendReceive(Player $player, bool $response)
	{
		if ($response) {
			FriendApi::$instance->removeFriend($player->getName(), $this->friend_name);
			$player->sendMessage(TextFormat::GREEN . $this->friend_name . " ã¨ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ã‚’è§£é™¤ã—ã¾ã—ãŸã€‚");
		} else {
			$this->sendUi($player);
		}
	}
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Button;

use api\FriendApi;

class online_receive
{
	use \api\send_main_ui;

	private $friends;

	function setFriendList(array $friends)
	{
		$this->friends = $friends;
	}

	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($key))
			return;

		if (empty($friend_api->getOnlineFriends($name)) || $key === count($friend_api->getOnlineFriends($name))) {
			$this->sendUi($player);
			return;
		}

		$friend_name = current(array_slice($this->friends, $key, 1, true));
        FormApi::makeListForm([new online_re_receive($friend_name), "receiveResponse"])
	        ->addButton(new Button("ãƒ†ãƒ¬ãƒãƒ¼ãƒˆ"))
			->addButton(new Button("ãƒãƒ£ãƒƒãƒˆ"))
			->addButton(new Button("æˆ»ã‚‹"))
	        ->setTitle(TextFormat::DARK_GREEN . $friend_name)
	        ->sendToPlayer($player);
	}
}<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;
use pocketmine\Server;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Input;

use api\FriendApi;

class online_re_receive
{
	use \api\send_main_ui;

	private $friend_name;

	function __construct(string $friend_name)
	{
		$this->friend_name = $friend_name;
	}

	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		switch ($key) {
			case 0:
				if (!$friend_api->getConfig()["teleport"]) {
					$player->sendMessage(TextFormat::YELLOW . "ã“ã®ã‚µãƒ¼ãƒãƒ¼ã§ã¯ãƒ•ãƒ¬ãƒ³ãƒ‰ã¸ã®ãƒ†ãƒ¬ãƒãƒ¼ãƒˆãŒç„¡åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚");
					return;
				}
				if (($target = Server::getInstance()->getPlayer($this->friend_name)) === null) {
					$player->sendMessage(TextFormat::YELLOW . $this->friend_name . "ã•ã‚“ã¯ç¾åœ¨ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§ã™ã€‚");
					return;
				}

				$player->teleport($target);
				$player->sendMessage("ãƒ†ãƒ¬ãƒãƒ¼ãƒˆãŒå®Œäº†ã—ã¾ã—ãŸã€‚");
				return;
			case 1:
				FormApi::makeCustomForm([$this, "chatReceive"])
					->addElement(new Input("ãƒãƒ£ãƒƒãƒˆ:", "ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸..."))
					->setTitle($this->friend_name . " ã•ã‚“ã¸ãƒãƒ£ãƒƒãƒˆã‚’é€ä¿¡")
					->sendToPlayer($player);
				return;
			case 2:
				$this->sendUi($player);
				return;
		}
	}

	function chatReceive(Player $player, ?array $response)
	{
		if (FormApi::formCancelled($response))
			return;
		if (($target = Server::getInstance()->getPlayer($this->friend_name)) === null) {
			$player->sendMessage(TextFormat::YELLOW . $this->friend_name . "ã•ã‚“ã¯ç¾åœ¨ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§ã™ã€‚");
			return;
		}

		$target->sendMessage(TextFormat::YELLOW . "[Friend Chat " . TextFormat::WHITE . $player->getName() . TextFormat::YELLOW . "] " . TextFormat::RESET . $response[0]);
		$player->sendMessage(TextFormat::YELLOW . "[Friend Chat " . TextFormat::WHITE . $player->getName() . TextFormat::YELLOW . "] " . TextFormat::RESET . $response[0]);
	}
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Button;
use tokyo\pmmp\libform\element\Dropdown;
use tokyo\pmmp\libform\element\Label;

use api\FriendApi;

class request_receive
{
	use \api\send_main_ui;

	private $requests;

	function setRequests(array $requests)
	{
		$this->requests = $requests;
	}

	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($key))
			return;

		if (empty($this->requests) || $key === count($this->requests)) {
			$this->sendUi($player);
			return;
		}
		
		$target_name = current(array_slice($this->requests, $key, 1, true));
        FormApi::makeModalForm([$receive = new request_re_receive, "receiveResponse"])
        	->setButtonText(true, TextFormat::DARK_GREEN . "æ‰¿èª")
        	->setButtonText(false, TextFormat::DARK_RED . "æ‹’å¦")
        	->setContent("æœ¬å½“ã« " . $target_name . " ã¨ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚Šã¾ã™ã‹?\nãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚‹ã¨æ§˜ã€…ãªæ©Ÿèƒ½ãŒãƒ•ãƒ¬ãƒ³ãƒ‰é–“ã§ä½¿ãˆã‚‹ã‚ˆã†ã«ãªã‚Šã¾ã™ã€‚\nãƒ•ãƒ¬ãƒ³ãƒ‰ã¯ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‹ã‚‰ã„ã¤ã§ã‚‚è§£é™¤ãŒã§ãã¾ã™ã€‚")
	        ->setTitle(TextFormat::DARK_GREEN . $target_name . " ã‹ã‚‰ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ")
	        ->sendToPlayer($player);
        $receive->setRequests($target_name);
	}
}<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;

use api\FriendApi;

class request_re_receive implements \api\type\NoticeType
{
	private $from_name;

	function setRequests(string $from_name)
	{
		$this->from_name = $from_name;
	}

	function receiveResponse(Player $player, bool $response)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if ($response) {
			$friend_api->acceptFriendRequest($name, $this->from_name);
			$friend_api->notice($name, self::NOTICE_TYPE_REQUEST_ACCEPTED, $this->from_name);
			$player->sendMessage(TextFormat::GREEN . $this->from_name . " ã¨ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚Šã¾ã—ãŸã€‚");
		} else {
			$friend_api->removeFriendRequest($name, $this->from_name);
			$player->sendMessage(TextFormat::GREEN . $this->from_name . " ã‹ã‚‰ã®ç”³è«‹ã‚’æ‹’å¦ã—ã¾ã—ãŸã€‚");
		}
	}
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;

use api\FriendApi;

class send_request_receive implements \api\type\NoticeType
{
	function receiveResponse(Player $player, ?array $response)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($response))
			return;

		$target = $response[0];

		if (empty($target)) {
			$player->sendMessage(TextFormat::YELLOW . "ãƒ—ãƒ¬ã‚¤ãƒ¤ãƒ¼åã‚’å…¥åŠ›ã—ã¦ãã ã•ã„ã€‚");
			return;
		}
		if ($target === $name) {
			$player->sendMessage(TextFormat::YELLOW . "è‡ªåˆ†è‡ªèº«ã¨ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“ã€‚");
			return;
		}
		if (!$friend_api->existsAccount($target)) {
			$player->sendMessage(TextFormat::YELLOW . $target . " ã•ã‚“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚");
			return;
		}
		if ($friend_api->isFriend($name, $target)) {
			$player->sendMessage(TextFormat::YELLOW . $target . " ã•ã‚“ã¨ã¯æ—¢ã«ãƒ•ãƒ¬ãƒ³ãƒ‰ã«ãªã£ã¦ã„ã¾ã™ã€‚");
			return;
		}
		if ($friend_api->getConfig()["max_friend"] !== -1) {
			if (count($friend_api->getFriendList($target)) >= $friend_api->getConfig()["max_friend"]) {
				$player->sendMessage(TextFormat::YELLOW . $target . " ã•ã‚“ã®ãƒ•ãƒ¬ãƒ³ãƒ‰æ•°ãŒæœ€å¤§æ•°ã«é”ã—ã¦ã„ã¾ã™ã€‚");
				return;
			}
		}
		if (in_array($name, $friend_api->getFriendRequests($target), true)) {
			$player->sendMessage(TextFormat::YELLOW . "æ—¢ã«ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é€ä¿¡æ¸ˆã¿ã§ã™ã€‚");
			return;
		}

		$friend_api->addFriendRequest($target, $name);
		$friend_api->notice($target, self::NOTICE_TYPE_REQUEST, $name);
		$player->sendMessage("ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’é€ä¿¡ã—ã¾ã—ãŸã€‚");
	}
}
<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;

use api\FriendApi;

class sent_request_receive
{
	use \api\send_main_ui;

	private $requests;

	function setRequests(array $requests)
	{
		$this->requests = $requests;
	}

	function receiveResponse(Player $player, ?int $key)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if (FormApi::formCancelled($key))
			return;

		if (empty($this->requests) || $key === count($this->requests)) {
			$this->sendUi($player);
			return;
		}
		
		$target_name = current(array_slice($this->requests, $key, 1, true));
        FormApi::makeModalForm([new sent_request_re_receive($target_name), "receiveResponse"])
        	->setButtonText(true,  "ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ã‚­ãƒ£ãƒ³ã‚»ãƒ«")
        	->setButtonText(false, "æˆ»ã‚‹")
	        ->setTitle(TextFormat::DARK_GREEN . $target_name . " ã¸ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ")
	        ->sendToPlayer($player);
	}
}<?php
namespace event\form\receive;

use pocketmine\utils\TextFormat;
use pocketmine\Player;

use tokyo\pmmp\libform\FormApi;

use api\FriendApi;

class sent_request_re_receive implements \api\type\NoticeType
{
	use \api\send_main_ui;

	private $target_name;

	function setRequests(string $target_name)
	{
		$this->target_name = $target_name;
	}

	function receiveResponse(Player $player, bool $response)
	{
		$friend_api = FriendApi::$instance;
		$name = $player->getName();

		if ($response) {
			$friend_api->removeFriendRequest($name, $this->target_name);
			$player->sendMessage(TextFormat::GREEN . $this->target_name . " ã¸ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã—ã¾ã—ãŸã€‚");
		} else {
			$this->sendUi($player);
		}
	}
}
<?php
namespace event\player;

use pocketmine\event\Listener;
use pocketmine\event\player\PlayerChatEvent;
use pocketmine\item\Item;
use pocketmine\utils\TextFormat;
use pocketmine\Server;

use api\FriendApi;

class PlayerChat implements Listener
{
	function onChat(PlayerChatEvent $event)
	{
		$player = $event->getPlayer();
		$name = $player->getName();
		$friend_api = FriendApi::$instance;

		if ($item = ($player->getInventory()->getItemInHand())->getCustomName() === TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . $friend_api->getChatPartner($name)) {
			$target = Server::getInstance()->getPlayer($friend = $friend_api->getChatPartner($name));
			if ($target === null) {
				$player->sendMessage(TextFormat::YELLOW . $friend . " ã•ã‚“ã¯æ—¢ã«ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§ã™ã€‚");
				$player->getInventory()->removeItem($item);
				return;
			}
			$message = $event->getMessage();
			$event->setCancelled();
			$target->sendMessage(TextFormat::YELLOW . "[Friend Chat " . TextFormat::WHITE . $name . TextFormat::YELLOW . "] " . TextFormat::RESET . $message);
			$player->sendMessage(TextFormat::YELLOW . "[Friend Chat " . TextFormat::WHITE . $name . TextFormat::YELLOW . "] " . TextFormat::RESET . $message);
		}		
	}
}
<?php
namespace event\player;

use pocketmine\event\Listener;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\Player;
use pocketmine\utils\TextFormat;

use api\FriendApi;

class PlayerDamage implements Listener
{
	function onDamage(EntityDamageByEntityEvent $event)
	{
		if (FriendApi::$instance->getConfig()["friendly_fire"])
			return;

		$entity = $event->getEntity();
		$damager = $event->getDamager();

		if ($entity instanceof Player && $damager instanceof Player) {
			$player = $entity;

			if (FriendApi::$instance->isFriend($player->getName(), $damager->getName())) {
				$damager->sendMessage(TextFormat::RED . "[Friend] ãƒ•ãƒ¬ãƒ³ãƒ‰ã‚’æ”»æ’ƒã—ã¦ã¯ã„ã‘ã¾ã›ã‚“!");
				$event->setCancelled();
			}
		}

	}
}
<?php
namespace event\player;

use pocketmine\event\Listener;
use pocketmine\utils\TextFormat;
use pocketmine\event\player\PlayerDropItemEvent;
use pocketmine\event\player\PlayerDeathEvent;
use pocketmine\event\player\PlayerRespawnEvent;
use pocketmine\event\inventory\InventoryTransactionEvent;
use pocketmine\item\Item;

use api\FriendApi;

class PlayerDropItem implements Listener
{
	private $hasTag = false;
	function onDrop(PlayerDropItemEvent $event)
	{
		$item = $event->getItem();
		if ($item->getCustomName() === TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . FriendApi::$instance->getChatPartner($event->getPlayer()->getName()))
			$event->setCancelled();
	}

	function onDeath(PlayerDeathEvent $event)
	{
		$drops = $event->getDrops();
		$item = Item::get(421)->setCustomName(TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . FriendApi::$instance->getChatPartner($event->getPlayer()->getName()));

		if (in_array($item, $drops)) {
			for ($i = 0; $i <= count($drops); $i++) {
				if (array_search($item, $drops) !== $i)
					continue;
				unset($drops[$i]);
			}
			$event->setDrops($drops);
			$this->hasTag[$event->getPlayer()->getName()] = true;
		}
	}

	function onRespawn(PlayerRespawnEvent $event)
	{
		$player = $event->getPlayer();
		$name = $player->getName();

		if ($this->hasTag[$name]) {
			$item = Item::get(421)->setCustomName(TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . FriendApi::$instance->getChatPartner($name));
			$player->getInventory()->addItem($item);
			$this->hasTag[$name] = false;
		}
	}

	function onTransaction(InventoryTransactionEvent $event)
	{
		foreach ($event->getTransaction()->getActions() as $action) {
			if ($action->getSourceItem()->getId() === 421 && $action->getSourceItem()->getCustomName() === TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . FriendApi::$instance->getChatPartner($event->getTransaction()->getSource()->getName())) {
				$event->setCancelled();
			}
		}
	}
}
<?php
namespace event\player;

use pocketmine\event\Listener;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\utils\TextFormat;

use tokyo\pmmp\libform\FormApi;
use tokyo\pmmp\libform\element\Button;

use api\FriendApi;

class PlayerInteract implements Listener
{
	function onInteract(PlayerInteractEvent $event)
	{
		$player = $event->getPlayer();
		$name = $player->getName();
		$friend_api = FriendApi::$instance;

		if ($event->getAction() !== PlayerInteractEvent::RIGHT_CLICK_AIR)
			return;

		if ($player->getInventory()->getItemInHand()->getCustomName() === TextFormat::YELLOW . "FriendChat " . TextFormat::WHITE . $friend_api->getChatPartner($name)) {
			$friends = [];
	        $form = FormApi::makeListForm([$receive = new \event\form\receive\friend_chat_receive, "receiveResponse"]);
			foreach ($friend_api->getOnlineFriends($name) as $friend) {
		        $form->addButton(new Button($friend));
		        $friends[] = $friend;
			}
			$receive->setFriendList($friends);
		        $form->setTitle(TextFormat::BOLD . TextFormat::DARK_GREEN . "ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒãƒ£ãƒƒãƒˆã®é€ä¿¡å…ˆã‚’æŒ‡å®š")
		        ->sendToPlayer($player);
		}
	}
}<?php
namespace event\player;

use pocketmine\event\Listener;
use pocketmine\event\player\PlayerJoinEvent;

class PlayerJoin implements Listener, \api\type\NoticeType
{
	function onJoin(PlayerJoinEvent $event)
	{
		$player = $event->getPlayer();
		$name = $player->getName();
		$friend_api = \api\FriendApi::$instance;
		$friend_api->createAccount($name);
		$friend_api->notice($name, self::NOTICE_TYPE_JOIN);
		if (!empty($requests = $friend_api->getFriendRequests($name))) {
			$player->sendMessage("[Friend] " . count($requests) . "ä»¶ã®ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒå±Šã„ã¦ã„ã¾ã™ã€‚");
			$player->sendMessage("[Friend] ãƒ•ãƒ¬ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®æ‹’å¦æ‰¿èªã¯ /friend ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‹ã‚‰è¡Œãˆã¾ã™ã€‚");
		}
	}
}
<?php
namespace event\player;

use pocketmine\event\Listener;
use pocketmine\event\player\PlayerQuitEvent;

class PlayerQuit implements Listener, \api\type\NoticeType
{
	function onQuit(PlayerQuitEvent $event)
	{
		$name = $event->getPlayer()->getName();
		\api\FriendApi::$instance->notice($name, self::NOTICE_TYPE_QUIT);
	}
}
<?php

use pocketmine\plugin\PluginBase;
use api\FriendApi;

define("PLUGIN_VERSION", '1.0.07');

class Main extends PluginBase
{
	function onEnable()
	{
		$this->init();


		$this->getLogger()->info("Friend ãŒèµ·å‹•ã—ã¾ã—ãŸã€‚");
	}

	function onDisable()
	{
		FriendApi::$instance->save();
	}

	private function init(): void
	{
		\tokyo\pmmp\libform\FormApi::register($this);
		new FriendApi($this);

        $command_map = $this->getServer()->getCommandMap();
        $command_map->register("friend", new \command\command_friend);
        $command_map->register("friendchat", new \command\command_chat);

	    $this->getServer()->getPluginManager()->registerEvents(new \event\player\PlayerInteract, $this);
	    $this->getServer()->getPluginManager()->registerEvents(new \event\player\PlayerDropItem, $this);
	    $this->getServer()->getPluginManager()->registerEvents(new \event\player\PlayerDamage, $this);
	    $this->getServer()->getPluginManager()->registerEvents(new \event\player\PlayerChat, $this);
	    $this->getServer()->getPluginManager()->registerEvents(new \event\player\PlayerJoin, $this);
	    $this->getServer()->getPluginManager()->registerEvents(new \event\player\PlayerQuit, $this);
	}
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * ButtonClass
 */
class Button extends Element {

  /** @var string */
  public const IMAGE_TYPE_PATH = "path";
  public const IMAGE_TYPE_URL = "url";

  /** @var string */
  protected $imageType = "";
  /** @var string */
  protected $imagePath = "";
  /** @var string */
  public $text = "";

  public function setImage(string $imagePath, string $imageType = self::IMAGE_TYPE_PATH): Button {
    switch ($imageType) {
      case self::IMAGE_TYPE_PATH:
      case self::IMAGE_TYPE_URL:
        $this->imagePath = $imagePath;
        $this->imageType = $imageType;
      break;

      default:
        throw new \InvalidArgumentException("The image type must be an string value Button::IMAGE_TYPE_PATH or Button::IMAGE_TYPE_URL");
      break;
    }
    return $this;
  }

  final public function format(): array {
    $data = [
      Form::KEY_TEXT => $this->text
    ];
    if (!empty($this->imageType)) {
      $data[Form::KEY_IMAGE] = [
        Form::KEY_TYPE => $this->imageType,
        Form::KEY_DATA => $this->imagePath
      ];
    }
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * DropdownClass
 */
class Dropdown extends Element {

  /** @var string */
  protected const ELEMENT_NAME = "dropdown";

  /** @var string[] */
  protected $options = [];
  /** @var int */
  protected $defaultKey = 0;

  public function __construct(string $text, array $options = []) {
    parent::__construct($text);
    $this->options = $options;
  }

  public function getOption(int $key): ?string {
    return isset($this->options[$key])? $this->options[$key] : null;
  }

  public function addOption(string $option, $isDefault = false): Dropdown {
    $this->defaultKey = $isDefault ? count($this->options) : $this->defaultKey;
    $this->options[] = $option;
    return $this;
  }

  public function removeOption(string $option): Dropdown {
    $flip = array_flip($this->options);
    if (array_key_exists($option, $flip)) {
      $key = $flip[$option];
      unset($this->options[$key]);
    }
    return $this;
  }

  public function getDefault(): string {
    return empty($this->options)? "" : $this->options[$this->defaultKey];
  }

  public function setDefault(string $option): Dropdown {
    $flip = array_flip($this->options);
    if (array_key_exists($option, $flip)) {
      $key = $flip[$option];
      $this->defaultKey = $key;
    }else {
      throw new \OutOfRangeException("Invalid option " . $option);
    }
  }

  final public function format(): array {
    $data = [
      Form::KEY_TYPE => self::ELEMENT_NAME,
      Form::KEY_TEXT => $this->text,
      Form::KEY_OPTIONS => $this->options,
      Form::KEY_DEFAULT => $this->defaultKey
    ];
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

/**
 * AbstractElementClass
 */
abstract class Element {

  /** @var string */
  protected const ELEMENT_NAME = "";

  /** @var string */
  protected $text = "";

  public function __construct(string $text) {
    $this->text = $text;
  }

  abstract public function format(): array;
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * ImageClass
 */
class Image extends Element {
  // TODO: #BlameMojang DOES NOT WORK

  final public function format(): array {
    return [];
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * InputClass
 */
class Input extends Element {

  /** @var string */
  protected const ELEMENT_NAME = "input";

  /** @var string */
  protected $placeholder = "";
  /** @var string */
  protected $defaultText = "";

  public function __construct(string $text, string $placeholder, string $defaultText = "") {
    parent::__construct($text);
    $this->placeholder = $placeholder;
    $this->defaultText = $defaultText;
  }

  final public function format(): array {
    $data = [
      Form::KEY_TYPE => self::ELEMENT_NAME,
      Form::KEY_TEXT => $this->text,
      Form::KEY_PLACEHOLDER => $this->placeholder,
      Form::KEY_DEFAULT => $this->defaultText
    ];
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * LabelClass
 */
class Label extends Element {

  /** @var string */
  protected const ELEMENT_NAME = "label";

  final public function format(): array {
    $data = [
      Form::KEY_TYPE => self::ELEMENT_NAME,
      Form::KEY_TEXT => $this->text
    ];
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * SliderClass
 */
class Slider extends Element {

  /** @var string */
  protected const ELEMENT_NAME = "slider";

  /** @var number */
  protected $min = 0;
  /** @var number */
  protected $max = 0;
  /** @var number */
  protected $step = 0;
  /** @var number */
  protected $defaultValue;

  /**
   * @param string $text
   * @param number $min
   * @param number $max
   * @param int $step
   */
  public function __construct(string $text, $min, $max, $step = 0) {
    if ($min > $max) throw new \InvalidArgumentException("Minimum value must be less than maximum value");
    parent::__construct($text);
    $this->min = $min;
    $this->max = $max;
    $this->defaultValue = $min;
    $this->setStep($step);
  }

  public function setStep($step): Slider {
    if ($step < 0) throw new \InvalidArgumentException("The value of the step must be a positive value");
    $this->step = $step;
    return $this;
  }

  public function setDefaultValue($value): Slider {
    if ($value < $this->min || $value > $this->max) {
      throw new \InvalidArgumentException("The default value must be between the minimum and maximum values");
    }
    $this->defaultValue = $value;
    return $this;
  }

  final public function format(): array {
    $data = [
      Form::KEY_TYPE => self::ELEMENT_NAME,
      Form::KEY_TEXT => $this->text,
      Form::KEY_MIN => $this->min,
      Form::KEY_MAX => $this->max,
    ];
    if ($this->step > 0) $data[Form::KEY_STEP] = $this->step;
    if ($this->defaultValue !== $this->min) {
      $data[Form::KEY_DEFAULT] = $this->defaultValue;
    }
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * StepSliderClass
 */
class StepSlider extends Element {

  /** @var string */
  protected const ELEMENT_NAME = "step_slider";

  /** @var string[] */
  protected $steps = [];
  /** @var int */
  protected $defaultKey = 0;

  public function __construct(string $text, array $steps = []) {
    parent::__construct($text);
    $this->steps = $steps;
  }

  public function getStep(int $key): ?string {
    return isset($this->steps[$key])? $this->steps[$key] : null;
  }

  public function addStep(string $stepText, bool $isDefault = false): StepSlider {
    if ($isDefault) $this->defaultKey = count($this->steps);
    $this->steps[] = $stepText;
    return $this;
  }

  public function removeStep(string $stepText): StepSlider {
    $flip = array_flip($this->steps);
    if (array_key_exists($stepText, $flip)) {
      $key = $flip[$stepText];
      unset($this->steps[$key]);
    }
    return $this;
  }

  public function getDefaultStep(): string {
    return empty($this->steps)? "" : $this->steps[$this->defaultKey];
  }

  public function setDefaultStep(string $stepText): StepSlider {
    $flip = array_flip($this->steps);
    if (array_key_exists($stepText, $flip)) {
      $key = $flip[$stepText];
      $this->defaultKey = $key;
    }else {
      throw new \OutOfRangeException("Invalid step text " . $stepText);
    }
    return $this;
  }

  public function format(): array {
    $data = [
      Form::KEY_TYPE => self::ELEMENT_NAME,
      Form::KEY_TEXT => $this->text,
      Form::KEY_STEPS => $this->steps,
      Form::KEY_DEFAULT => $this->defaultKey
    ];
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\element;

// libform
use tokyo\pmmp\libform\{
  form\Form
};

/**
 * ToggleClass
 */
class Toggle extends Element {

  /** @var string */
  protected const ELEMENT_NAME = "toggle";

  /** @var bool */
  protected $defaultValue = false;

  public function __construct(string $text, bool $value = false) {
    parent::__construct($text);
    $this->defaultValue = $value;
  }

  public function setDefaultValue(bool $value): Toggle {
    $this->defaultValue = $value;
    return $this;
  }

  final public function format(): array {
    $data = [
      Form::KEY_TYPE => self::ELEMENT_NAME,
      Form::KEY_TEXT => $this->text,
      Form::KEY_DEFAULT => $this->defaultValue
    ];
    return $data;
  }
}
<?php
namespace tokyo\pmmp\libform;

use pocketmine\event\Listener;
use pocketmine\event\player\PlayerQuitEvent;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\network\mcpe\protocol\ModalFormResponsePacket;

class EventListener implements Listener {

  public function onReceive(DataPacketReceiveEvent $event) {
    $pk = $event->getPacket();
    if ($pk instanceof ModalFormResponsePacket) {
      $player = $event->getPlayer();
      $formId = $pk->formId;
      $response = json_decode($pk->formData, true);
      if (($form = FormApi::getForm($formId)) !== null) {
        if (!$form->isRecipient($player)) {
          return false;
        }
        $callable = $form->getCallable();
        if ($callable !== null) {
          $callable($player, $response);
        }
        FormApi::removeForm($formId);
        $event->setCancelled();
      }
    }
  }

  public function onQuit(PlayerQuitEvent $event) {
    $player = $event->getPlayer();
    foreach (FormApi::getForms() as $formId => $form) {
      if ($form->isRecipient($player)) {
        FormApi::removeForm($formId);
        break;
      }
    }
  }
}<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\form;

// libform
use tokyo\pmmp\libform\{
  element\Element
};

/**
 * CustomForm
 */
class CustomForm extends Form implements \JsonSerializable {

  /** @var string */
  private const FORM_TYPE = "custom_form";
  /** @var array */
  protected $data = [
    Form::KEY_TYPE => self::FORM_TYPE,
    Form::KEY_TITLE => "",
    Form::KEY_CONTENT => []
  ];

  public function getElements(): array {
    return $this->data[Form::KEY_CONTENT];
  }

  public function getElement(int $key): ?Element {
    if (array_key_exists($key, $this->data[Form::KEY_CONTENT])) {
      return $this->data[Form::KEY_CONTENT][$key];
    }
    return null;
  }

  public function addElement(Element $element): CustomForm {
    if (!($element instanceof Button)) {// Button is for a ListForm
      $this->data[Form::KEY_CONTENT][] = $element;
    }
    return $this;
  }

  final public function jsonSerialize(): array {
    $data = $this->data;
    unset($data[Form::KEY_CONTENT]);
    foreach ($this->getElements() as $element) {
      $data[Form::KEY_CONTENT][] = $element->format();
    }
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\form;

// pocketmine
use pocketmine\{
  Player,
  network\mcpe\protocol\ModalFormRequestPacket
};

/**
 * abstractFormClass
 */
abstract class Form implements \JsonSerializable {

  /** @var string */
  public const KEY_TYPE = "type";
  public const KEY_CONTENT = "content";
  public const KEY_DATA = "data";
  public const KEY_IMAGE = "image";
  public const KEY_TITLE = "title";
  public const KEY_TEXT = "text";
  public const KEY_OPTIONS = "options";
  public const KEY_DEFAULT = "default";
  public const KEY_PLACEHOLDER = "placeholder";
  public const KEY_STEP = "step";
  public const KEY_STEPS = "steps";
  public const KEY_BUTTON1 = "button1";
  public const KEY_BUTTON2 = "button2";
  public const KEY_BUTTONS = "buttons";
  public const KEY_MIN = "min";
  public const KEY_MAX = "max";

  /** @var int */
  protected $id = 0;
  /** @var ?callable */
  private $callable = null;
  /** @var array */
  protected $data = [];
  /** @var string */
  protected $playerName = "";

  public function __construct(int $id, callable $callable = null) {
    $this->id = $id;
    $this->callable = $callable;
  }

  /**
   * @return int
   */
  public function getId(): int {
    return $this->id;
  }

  /**
   * @param  int $id
   * @return Form
   */
  public function setId(int $id): Form {
    $this->id = $id;
    return $this;
  }

  /**
   * @return string
   */
  public function getTitle(): string {
    return $this->data[self::KEY_TITLE];
  }

  /**
   * @param  string $title
   * @return Form
   */
  public function setTitle(string $title): Form {
    $this->data[self::KEY_TITLE] = $title;
    return $this;
  }

  /**
   * @return ?callable
   */
  public function getCallable(): ?callable {
    return $this->callable;
  }

  /**
   * @param  Player $player
   * @return bool
   */
  public function isRecipient(Player $player): bool {
    return $player->getName() === $this->playerName;
  }

  /**
   * @param Player $player
   * @return Form
   */
  public function sendToPlayer(Player $player): Form {
    $pk = new ModalFormRequestPacket;
    $pk->formId = $this->id;
    $pk->formData = json_encode($this);
    $this->playerName = $player->getName();
    $player->dataPacket($pk);
    return $this;
  }

  /**
   * @return array
   */
  abstract public function jsonSerialize(): array;
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\form;

// libform
use tokyo\pmmp\libform\{
  element\Button
};

/**
 * ListFormClass
 */
class ListForm extends Form implements \JsonSerializable {

  /** @var string */
  private const FORM_TYPE = "form";
  /** @var array */
  protected $data = [
    Form::KEY_TYPE => self::FORM_TYPE,
    Form::KEY_TITLE => "",
    Form::KEY_CONTENT => "",
    Form::KEY_BUTTONS => []
  ];

  public function getContent(): string {
    return $this->data[Form::KEY_CONTENT];
  }

  public function setContent(string $content): ListForm {
    $this->data[Form::KEY_CONTENT] = $content;
    return $this;
  }

  public function getButtons(): array {
    return $this->data[Form::KEY_BUTTONS];
  }

  public function addButton(Button $button): ListForm {
    $this->data[Form::KEY_BUTTONS][] = $button;
    return $this;
  }

  final public function jsonSerialize(): array {
    $data = $this->data;
    if (!empty(($buttons = $this->getButtons()))) {
      unset($data[Form::KEY_BUTTONS]);
      foreach ($this->getButtons() as $button) {
        $data[Form::KEY_BUTTONS][] = $button->format();
      }
    }
    return $data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform\form;

/**
 * ModalFormClass
 */
class ModalForm extends Form implements \JsonSerializable {

  /** @var string */
  private const FORM_TYPE = "modal";
  /** @var array */
  protected $data = [
    Form::KEY_TYPE => self::FORM_TYPE,
    Form::KEY_TITLE => "",
    Form::KEY_CONTENT => "",
    Form::KEY_BUTTON1 => "",
    Form::KEY_BUTTON2 => ""
  ];

  public function setButtonText(bool $button, string $text): ModalForm {
    if ($button) {
      $this->data[Form::KEY_BUTTON1] = $text;
    }else {
      $this->data[Form::KEY_BUTTON2] = $text;
    }
    return $this;
  }

  public function getContent(): string {
    return $this->data[Form::KEY_CONTENT];
  }

  public function setContent(string $content): ModalForm {
    $this->data[Form::KEY_CONTENT] = $content;
    return $this;
  }

  final public function jsonSerialize(): array {
    return $this->data;
  }
}
<?php

/**
 * // English
 *
 * libform is a library for PocketMine-MP for easy operation of forms
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * This software is distributed under "MIT license".
 * You should have received a copy of the MIT license
 * along with this program.  If not, see
 * < https://opensource.org/licenses/mit-license >.
 *
 * ---------------------------------------------------------------------
 * // æ—¥æœ¬èªž
 *
 * libformã¯ã€ãƒ•ã‚©ãƒ¼ãƒ ã‚’ç°¡å˜ã«æ“ä½œã™ã‚‹ãŸã‚ã®pocketmine-MPå‘ã‘ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã§ã™
 * Copyright (c) 2018 yuko fuyutsuki < https://github.com/fuyutsuki >
 *
 * ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã¯"MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹"ä¸‹ã§é…å¸ƒã•ã‚Œã¦ã„ã¾ã™ã€‚
 * ã‚ãªãŸã¯ã“ã®ãƒ—ãƒ­ã‚°ãƒ©ãƒ ã¨å…±ã«MITãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®ã‚³ãƒ”ãƒ¼ã‚’å—ã‘å–ã£ãŸã¯ãšã§ã™ã€‚
 * å—ã‘å–ã£ã¦ã„ãªã„å ´åˆã€ä¸‹è¨˜ã®URLã‹ã‚‰ã”è¦§ãã ã•ã„ã€‚
 * < https://opensource.org/licenses/mit-license >
 */

namespace tokyo\pmmp\libform;

// pocketmine
use pocketmine\plugin\PluginBase;
use pocketmine\Server;

// libform
use tokyo\pmmp\libform\form\CustomForm;
use tokyo\pmmp\libform\form\Form;
use tokyo\pmmp\libform\form\ListForm;
use tokyo\pmmp\libform\form\ModalForm;

/**
 * FormApiClass
 */
class FormApi {

  /** @var bool */
  private static $activated = false;
  /** @var Form[] */
  private static $forms = [];

  private function __construct() {
    // DONT USE THIS METHOD!
  }

  /**
   * @param PluginBase $plugin
   */
  public static function register(PluginBase $plugin): void {
    if (!self::$activated) {
      Server::getInstance()
        ->getPluginManager()
        ->registerEvents(new EventListener, $plugin);
    }
  }

  /**
   * Generate a custom form
   * @param  callable   $callable
   * @return CustomForm
   */
  public static function makeCustomForm(callable $callable = null): CustomForm {
    $formId = self::makeRandomFormId();
    $form = new CustomForm($formId, $callable);
    if ($callable !== null) self::$forms[$formId] = $form;
    return $form;
  }

  /**
   * Generate a list form
   * @param  callable $callable
   * @return ListForm
   */
  public static function makeListForm(callable $callable = null): ListForm {
    $formId = self::makeRandomFormId();
    $form = new ListForm($formId, $callable);
    if ($callable !== null) self::$forms[$formId] = $form;
    return $form;
  }

  /**
   * Generate a modal form
   * @param  callable  $callable
   * @return ModalForm
   */
  public static function makeModalForm(callable $callable = null): ModalForm {
    $formId = self::makeRandomFormId();
    $form = new ModalForm($formId, $callable);
    if ($callable !== null) self::$forms[$formId] = $form;
    return $form;
  }

  /**
   * Generate random formId
   * @return int formId
   */
  public static function makeRandomFormId(): int {
    return mt_rand(0, mt_getrandmax());
  }

  /**
   * @return array
   */
  public static function getForms(): array {
    return self::$forms;
  }

  /**
   * @param int $formId
   * @return Form|null
   */
  public static function getForm(int $formId): ?Form {
    if (array_key_exists($formId, self::$forms)) {
      return self::$forms[$formId];
    }else {
      return null;
    }
  }

  /**
   * @param int $formId
   */
  public static function removeForm(int $formId): void {
    if (array_key_exists($formId, self::$forms)) {
      unset(self::$forms[$formId]);
    }
  }

  /**
   * Check if the form has been canceled
   * @param  mixed $response
   * @return bool
   */
  public static function formCancelled($response): bool {
    return $response === null? true : false;
  }
}
&¿¢s†‘D—"ßBÆôy?$/'(   GBMB