redtv_muqsit / invmenu
A PocketMine-MP 病毒来创建和管理虚拟库存!
This package is not auto-updated.
Last update: 2024-09-20 18:39:34 UTC
README
InvMenu 是一个 PocketMine-MP 病毒,它简化了创建和管理虚拟库存的过程!
安装
您可以在 poggit 上通过点击 这里 获取编译好的 .phar 文件。
用法
InvMenu 支持从任何类型的 Inventory
创建 GUI。
注意: 您必须在启用插件之前注册 InvMenuHandler
,然后才能开始创建 InvMenu
实例。
if(!InvMenuHandler::isRegistered()){ InvMenuHandler::register($this); }
创建 InvMenu 实例
InvMenu::create($identifier)
创建一个 InvMenu 的新实例。 $identifier
必须是已注册的 InvMenuType
对象的标识符。InvMenu 随带 3 个预注册的 InvMenuType
标识符:InvMenu::TYPE_CHEST
、InvMenu::TYPE_DOUBLE_CHEST
和 InvMenu::TYPE_HOPPER
。
$menu = InvMenu::create(InvMenu::TYPE_CHEST);
要访问此菜单的库存,您可以
$inventory = $menu->getInventory();
$inventory
实现了 pocketmine 的 Inventory
接口,因此您可以访问所有花哨的 pocketmine 库存方法。
$menu->getInventory()->setContents([ VanillaItems::DIAMOND_SWORD(), VanillaItems::DIAMOND_PICKAXE() ]); $menu->getInventory()->addItem(VanillaItems::DIAMOND_AXE()); $menu->getInventory()->setItem(3, VanillaItems::GOLD_INGOT());
要向玩家发送菜单,请使用
/** @var Player $player */ $menu->send($player);
是的,就是这样。非常简单。
为菜单指定自定义名称
要为菜单设置自定义名称,请使用
$menu->setName("Custom Name");
您还可以在 InvMenu::send()
期间为每个玩家分别指定不同的菜单名称。
/** @var Player $player */ $menu->send($player, "Greetings, " . $player->getName());
验证菜单是否已发送给玩家
虽然不太常见,但插件可能会阻止玩家打开库存。这也可能是在尝试丢弃垃圾 InvMenu::send()
请求(如果您同时发送两个菜单而没有延迟,第一个菜单请求可能被视为垃圾)。
/** @var string|null $name */ $menu->send($player, $name, function(bool $sent) : void{ if($sent){ // do something } });
处理菜单项交易
要处理发生到和从菜单库存中的项目交易,您可以指定一个 Closure
处理程序,该处理程序在每次交易发生时由 InvMenu
触发。您可以在处理程序中允许、取消并执行其他操作。要将事务处理程序注册到菜单中,请使用
/** @var Closure $listener */ $menu->setListener($listener);
$listener
是什么?
/** * @param InvMenuTransaction $transaction * * Must return an InvMenuTransactionResult instance. * Return $transaction->continue() to continue the transaction. * Return $transaction->discard() to cancel the transaction. * @return InvMenuTransactionResult */ Closure(InvMenuTransaction $transaction) : InvMenuTransactionResult;
InvMenuTransaction
包含所有项目交易数据。
InvMenuTransaction::getPlayer()
返回触发交易的 Player
。
InvMenuTransaction::getItemClicked()
返回玩家在菜单中点击的 Item
。
InvMenuTransaction::getItemClickedWith()
返回玩家点击项目时手中的 Item
。
InvMenuTransaction::getAction()
返回一个 SlotChangeAction
实例,以获取从菜单库存中点击的项目的槽位索引。
InvMenuTransaction::getTransaction()
返回完整的 InventoryTransaction
实例。
$menu->setListener(function(InvMenuTransaction $transaction) : InvMenuTransactionResult{ $player = $transaction->getPlayer(); $itemClicked = $transaction->getItemClicked(); $itemClickedWith = $transaction->getItemClickedWith(); $action = $transaction->getAction(); $invTransaction = $transaction->getTransaction(); return $transaction->continue(); });
不允许玩家从菜单库存中取出苹果的处理程序
$menu->setListener(function(InvMenuTransaction $transaction) : InvMenuTransactionResult{ if($transaction->getItemClicked()->getId() === ItemIds::APPLE){ $player->sendMessage("You cannot take apples out of that inventory."); return $transaction->discard(); } return $transaction->continue(); });
防止玩家更改库存
您有两种方法可以防止玩家修改菜单的库存内容。
方法 #1:调用 InvMenuTransaction::discard()
$menu->setListener(function(InvMenuTransaction $transaction) : InvMenuTransactionResult{ // do something return $transaction->discard(); });
方法 #2:使用 InvMenu::readonly()
$menu->setListener(InvMenu::readonly());
$menu->setListener(InvMenu::readonly(function(DeterministicInvMenuTransaction $transaction) : void{ // do something }));
根据您的用例,您可能发现其中一种比另一种更好。虽然 方法 #1
给您对交易的完全控制权(您可以根据玩家是否有权限、玩家是否在特定区域等条件有条件地取消交易),但 方法 #2
减少了 InvMenuTransactionResult
导入和调用到 InvMenutransaction::discard()
的样板。
交易后执行任务
在玩家查看存货时,有一些操作是不可能的,例如发送表单——玩家在查看存货时无法查看表单。要执行此操作,您需要关闭存货菜单,并确保他们已经关闭了它,通过等待他们那边的响应。您可以通过向 InvMenuTransactionResult::then()
提供回调来实现。
$menu->setListener(function(InvMenuTransaction $transaction) : InvMenuTransactionResult{ $transaction->getPlayer()->removeCurrentWindow(); return $transaction->discard()->then(function(Player $player) : void{ // $player === $transaction->getPlayer() // assert($player->isOnline()); $player->sendForm(new Form()); }); });
$menu->setListener(InvMenu::readonly(function(DeterministicInvMenuTransaction $transaction) : void{ $transaction->getPlayer()->removeCurrentWindow(); $transaction->then(function(Player $player) : void{ $player->sendForm(new Form()); }); }));
监听玩家关闭或不再查看存货
要监听存货关闭触发器,请使用
/** @var Closure $listener */ $menu->setInventoryCloseListener($listener);
$listener
是什么?
/** * @param Player $player the player who closed the inventory. * * @param Inventory $inventory the inventory instance closed by the player. */ Closure(Player $player, Inventory $inventory) : void;
强制关闭或从玩家处移除菜单
/** @var Player $player */ $player->removeCurrentWindow();
注册自定义的 InvMenu 类型
假设您想向玩家发送分配器存货。虽然 InvMenu 没有附带 InvMenu::TYPE_DISPENSER
,您仍然可以通过注册一个带有分配器存货信息的 InvMenuType
对象来创建分配器 InvMenu。
public const TYPE_DISPENSER = "myplugin:dispenser"; protected function onEnable() : void{ InvMenuHandler::getTypeRegistry()->register(self::TYPE_DISPENSER, InvMenuTypeBuilders::BLOCK_ACTOR_FIXED() ->setBlock(BlockFactory::getInstance()->get(BlockLegacyIds::DISPENSER, 0)) ->setBlockActorId("Dispenser") ->setSize(9) ->setNetworkWindowType(WindowTypes::DISPENSER) ->build()); }
太棒了!现在您可以使用以下方法创建分配器菜单
$menu = InvMenu::create(self::TYPE_DISPENSER);
InvMenu 维基
使用 InvMenu 的应用程序、示例、教程和特色项目可以在 InvMenu 维基 上找到。