PHPackages                             redtv\_muqsit/invmenu - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. redtv\_muqsit/invmenu

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

redtv\_muqsit/invmenu
=====================

A PocketMine-MP virion to create and manage virtual inventories!

013PHP

Since Nov 5Pushed 1y ago1 watchersCompare

[ Source](https://github.com/RedTv-Developpement/InvMenuByMuqsit)[ Packagist](https://packagist.org/packages/redtv_muqsit/invmenu)[ RSS](/packages/redtv-muqsit-invmenu/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

InvMenu
=======

[](#invmenu)

**InvMenu is a PocketMine-MP virion that eases creating and managing fake inventories!**[![](https://camo.githubusercontent.com/c5d333f9aced0c46c6761890e9603f78e9327db51b7c2023303f1febbab9aa24/68747470733a2f2f706f676769742e706d6d702e696f2f736869656c642e73746174652f496e764d656e75)](https://poggit.pmmp.io/p/InvMenu)

Installation
------------

[](#installation)

You can get the compiled .phar file on poggit by clicking [here](https://poggit.pmmp.io/ci/Muqsit/InvMenu/~).

Usage
-----

[](#usage)

InvMenu supports creating a GUI out of any kind of `Inventory`.

**NOTE:** You MUST register `InvMenuHandler` during plugin enable before you can begin creating `InvMenu` instances.

```
if(!InvMenuHandler::isRegistered()){
	InvMenuHandler::register($this);
}
```

Creating an InvMenu instance
----------------------------

[](#creating-an-invmenu-instance)

`InvMenu::create($identifier)` creates a new instance of InvMenu. `$identifier` must be an identifier of a registered `InvMenuType` object. InvMenu comes with 3 pre-registered `InvMenuType` identifiers: `InvMenu::TYPE_CHEST`, `InvMenu::TYPE_DOUBLE_CHEST` and `InvMenu::TYPE_HOPPER`.

```
$menu = InvMenu::create(InvMenu::TYPE_CHEST);
```

To access this menu's inventory, you can use:

```
$inventory = $menu->getInventory();
```

The `$inventory` implements pocketmine's `Inventory` interface, so you can access all the fancy pocketmine inventory methods.

```
$menu->getInventory()->setContents([
	VanillaItems::DIAMOND_SWORD(),
	VanillaItems::DIAMOND_PICKAXE()
]);
$menu->getInventory()->addItem(VanillaItems::DIAMOND_AXE());
$menu->getInventory()->setItem(3, VanillaItems::GOLD_INGOT());
```

To send the menu to a player, use:

```
/** @var Player $player */
$menu->send($player);
```

Yup, that's it. It's that simple.

Specifying a custom name to the menu
------------------------------------

[](#specifying-a-custom-name-to-the-menu)

To set a custom name to a menu, use

```
$menu->setName("Custom Name");
```

You can also specify a different menu name for each player separately during `InvMenu::send()`.

```
/** @var Player $player */
$menu->send($player, "Greetings, " . $player->getName());
```

Verifying whether the menu was sent to the player
-------------------------------------------------

[](#verifying-whether-the-menu-was-sent-to-the-player)

Not a common occurrence but it's possible for plugins to disallow players from opening inventories. This can also occur as an attempt to drop garbage `InvMenu::send()` requests (if you send two menus simultaneously without any delay in betweeen, the first menu request may be regarded as garbage).

```
/** @var string|null $name */
$menu->send($player, $name, function(bool $sent) : void{
	if($sent){
		// do something
	}
});
```

Handling menu item transactions
-------------------------------

[](#handling-menu-item-transactions)

To handle item transactions happening to and from the menu's inventory, you may specify a `Closure` handler that gets triggered by `InvMenu` every time a transaction occurs. You may allow, cancel and do other things within this handler. To register a transaction handler to a menu, use:

```
/** @var Closure $listener */
$menu->setListener($listener);
```

What's **`$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` holds all the item transction data.
`InvMenuTransaction::getPlayer()` returns the `Player` that triggered the transaction.
`InvMenuTransaction::getItemClicked()` returns the `Item` the player clicked in the menu.
`InvMenuTransaction::getItemClickedWith()` returns the `Item` the player had in their hand when clicking an item.
`InvMenuTransaction::getAction()` returns a `SlotChangeAction` instance, to get the slot index of the item clicked from the menu's inventory.
`InvMenuTransaction::getTransaction()` returns the complete `InventoryTransaction` instance.

```
$menu->setListener(function(InvMenuTransaction $transaction) : InvMenuTransactionResult{
	$player = $transaction->getPlayer();
	$itemClicked = $transaction->getItemClicked();
	$itemClickedWith = $transaction->getItemClickedWith();
	$action = $transaction->getAction();
	$invTransaction = $transaction->getTransaction();
	return $transaction->continue();
});
```

A handler that doesn't allow players to take out apples from the menu's inventory:

```
$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();
});
```

### Preventing inventory from being changed by players

[](#preventing-inventory-from-being-changed-by-players)

There are two ways you can go with to prevent players from modifying the inventory contents of a menu.

#### Method #1: Calling `InvMenuTransaction::discard()`

[](#method-1-calling-invmenutransactiondiscard)

```
$menu->setListener(function(InvMenuTransaction $transaction) : InvMenuTransactionResult{
	// do something
	return $transaction->discard();
});
```

#### Method #2: Using `InvMenu::readonly()`

[](#method-2-using-invmenureadonly)

```
$menu->setListener(InvMenu::readonly());
```

```
$menu->setListener(InvMenu::readonly(function(DeterministicInvMenuTransaction $transaction) : void{
	// do something
}));
```

Based on your use-case, you may find one better than the other. While `Method #1` gives you full control over a transaction (you can conditionally cancel a transaction, f.e based on whether player has permission, or player is in a specific area etc), `Method #2` reduces boilerplate `InvMenuTransactionResult` imports and calls to `InvMenutransaction::discard()`.

Executing a task post-transaction
---------------------------------

[](#executing-a-task-post-transaction)

A few actions are impossible to be done at the time a player is viewing an inventory, such as sending a form — a player won't be able to view a form while viewing an inventory. To do this, you will need to close the menu inventory and make sure they've closed it by waiting for a response from their side. You can do this by supplying a callback to `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());
	});
}));
```

Listening players closing or no longer viewing the inventory
------------------------------------------------------------

[](#listening-players-closing-or-no-longer-viewing-the-inventory)

To listen inventory close triggers, specify the inventory close Closure using:

```
/** @var Closure $listener */
$menu->setInventoryCloseListener($listener);
```

What's **`$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;
```

To forcefully close or remove the menu from a player:

```
/** @var Player $player */
$player->removeCurrentWindow();
```

Registering a custom InvMenu type
---------------------------------

[](#registering-a-custom-invmenu-type)

So let's say you'd like to send players a dispenser inventory. While InvMenu doesn't ship with a `InvMenu::TYPE_DISPENSER`, you can still create a dispenser InvMenu by registering an `InvMenuType` object with the information about what a dispenser inventory looks like.

```
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());
}
```

Sweet! Now you can create a dispenser menu using

```
$menu = InvMenu::create(self::TYPE_DISPENSER);
```

InvMenu Wiki
------------

[](#invmenu-wiki)

Applications, examples, tutorials and featured projects using InvMenu can be found on the [InvMenu Wiki](https://github.com/Muqsit/InvMenu/wiki/InvMenu-v4.0).

###  Health Score

15

—

LowBetter than 3% of packages

Maintenance31

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity16

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/11e604ce0482ce1f054258b2026fddba1f1dd31e25da069be6ac919e2d4082f6?d=identicon)[RedTv](/maintainers/RedTv)

---

Top Contributors

[![RedTv-Developpement](https://avatars.githubusercontent.com/u/71102168?v=4)](https://github.com/RedTv-Developpement "RedTv-Developpement (7 commits)")

### Embed Badge

![Health badge](/badges/redtv-muqsit-invmenu/health.svg)

```
[![Health](https://phpackages.com/badges/redtv-muqsit-invmenu/health.svg)](https://phpackages.com/packages/redtv-muqsit-invmenu)
```

###  Alternatives

[amstaffix/pagination

Simple pagination

46290.4k6](/packages/amstaffix-pagination)[faonni/module-smart-category

SmartCategory module is a base of Smart Categories functionality.

8289.3k3](/packages/faonni-module-smart-category)[sitegeist/silhouettes

Preconfigure property-silhuettes that can be applied to various properties of multiple NodeTypes.

16157.5k](/packages/sitegeist-silhouettes)[michaeljennings/refinery

A php class to refine data into a set format.

129.5k2](/packages/michaeljennings-refinery)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
