├── .poggit.yml
├── README.md
├── src
└── muqsit
│ └── invmenuutils
│ └── InvMenuListenerUtils.php
└── virion.yml
/.poggit.yml:
--------------------------------------------------------------------------------
1 | --- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/Muqsit/InvMenuUtils
2 | build-by-default: true
3 | branches:
4 | - master
5 | projects:
6 | InvMenuUtils:
7 | path: ""
8 | model: virion
9 | type: library
10 | ...
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # InvMenuUtils
2 | A utility virion for the [InvMenu](https://github.com/Muqsit/InvMenu) virion implementing some commonly used procedures.
3 |
4 | ## Assigning multiple listeners to one `InvMenu`
5 | Multiple listeners have different behaviour for readonly and non-readonly InvMenu instances.
6 | For non-readonly InvMenu instances, listeners are prioritised in the order they were passed to the `InvMenuListenerUtils::multiple()` method.
7 | A listener will not be executed if the previous listener cancelled the transaction (i.e returned false).
8 | ```php
9 | $menu = InvMenu::create(InvMenu::TYPE_CHEST);
10 | $menu->setListener(InvMenuListenerUtils::multiple(
11 | $menu,
12 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
13 | echo "This listener is called first" . PHP_EOL;
14 | return true;
15 | },
16 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
17 | echo "This listener is called second." . PHP_EOL;
18 | return false;
19 | },
20 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
21 | // This listener is not called as the previous listener cancelled the transaction
22 | // by returning false.
23 | return true;
24 | }
25 | ));
26 | ```
27 | For readonly InvMenu instances, all listeners will be executed as the transaction is anyway forcefully cancelled.
28 | ```php
29 |
30 | $menu = InvMenu::create(InvMenu::TYPE_CHEST);
31 | $menu->readonly();
32 | $menu->setListener(InvMenuListenerUtils::multiple(
33 | $menu,
34 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : void{
35 | echo "This listener is called first" . PHP_EOL;
36 | },
37 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : void{
38 | echo "This listener is called second." . PHP_EOL;
39 | },
40 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : void{
41 | echo "This listener is called third." . PHP_EOL;
42 | }
43 | ));
44 | ```
45 |
46 | ## Assigning slot-specific listeners to an `InvMenu`
47 | Listen or handle specific slots, or handle each slot separately.
48 | Index your listeners to the slot you'd like the listener to handle/listen.
49 | TIP: Use index `-1` to "catch-all" (fallback).
50 | ```php
51 | $menu->setListener(InvMenuListenerUtils::slotSpecific($menu, [
52 | 8 => function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
53 | $player->sendMessage("You clicked slot #8");
54 | return true;
55 | },
56 | 16 => function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
57 | $player->sendMessage("You clicked slot #16");
58 | return true;
59 | },
60 | -1 => function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
61 | $player->sendMessage("Fallback: You clicked slot #" . $action->getSlot());
62 | return true;
63 | }
64 | ]));
65 | ```
66 |
67 | ## Blacklisting specific slots
68 | **NOTE:** This method is applicable ONLY to non-readonly InvMenu instances.
69 | Blacklisting an array of slots disallows players from modify those slots.
70 | ```php
71 | $menu = InvMenu::create(InvMenu::TYPE_CHEST);
72 | $menu->setListener(InvMenuListenerUtils::blacklistSlots([0, 4, 8]));
73 | ```
74 | You can even use this in combination with `InvMenuListenerUtils::multiple()`.
75 | ```php
76 | $menu = InvMenu::create(InvMenu::TYPE_CHEST);
77 | $menu->setListener(InvMenuListenerUtils::multiple(
78 | $menu,
79 | InvMenuListenerUtils::blacklistSlots([0, 1, 2]),
80 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
81 | $player->sendMessage("You didn't click any of these slots: 0, 1, 2");
82 | return true;
83 | }
84 | ));
85 | ```
86 |
87 | ## Whitelisting specific slots
88 | **NOTE:** This method is applicable ONLY to non-readonly InvMenu instances.
89 | Whitelisting an array of slots allows players to modify ONLY those slots.
90 | ```php
91 | $menu = InvMenu::create(InvMenu::TYPE_CHEST);
92 | $menu->setListener(InvMenuListenerUtils::whitelistSlots([0, 4, 8]));
93 | ```
94 | Similar to `InvMenuListenerUtils::blacklistSlots()`, you can use this in combination with `InvMenuListenerUtils::multiple()`.
95 | ```php
96 | $menu = InvMenu::create(InvMenu::TYPE_CHEST);
97 | $menu->setListener(InvMenuListenerUtils::multiple(
98 | $menu,
99 | InvMenuListenerUtils::whitelistSlots([0, 1, 2]),
100 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
101 | $player->sendMessage("You click one of these slots: 0, 1, 2");
102 | return true;
103 | }
104 | ));
105 | ```
106 |
107 | ## Filtering items with specific NBT tags
108 | **NOTE:** This method is applicable ONLY to non-readonly InvMenu instances.
109 | Filter items only with a specific NBT tag on them to allow players to take those items out of the inventory.
110 | ```php
111 | $menu->setListener(InvMenuListenerUtils::onlyItemsWithTag("CustomItem", StringTag::class));
112 | ```
113 | Filter items only without a specific NBT tag on them to allow players to take those items out of the inventory.
114 | ```php
115 | $menu->setListener(InvMenuListenerUtils::onlyItemsWithoutTag("Button", ByteTag::class));
116 | ```
117 | Similar to `InvMenuListenerUtils::whitelistSlots()` and `InvMenuListenerUtils::blacklistSlots()`, this can be used in combination with `InvMenuListenerUtils::multiple()`.
118 | ```php
119 | $menu->setListener(InvMenuListenerUtils::multiple(
120 | $menu,
121 | InvMenuListenerUtils::onlyItemsWithTag("Button", ByteTag::class),
122 | function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) : bool{
123 | $player->sendMessage("You clicked a button!");
124 | return false;
125 | }
126 | ));
127 | ```
128 |
--------------------------------------------------------------------------------
/src/muqsit/invmenuutils/InvMenuListenerUtils.php:
--------------------------------------------------------------------------------
1 | isReadonly() ? self::multipleReadonly(...$listeners) : self::multipleReadWrite(...$listeners);
39 | }
40 |
41 | public static function multipleReadonly(Closure ...$listeners) : Closure{
42 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($listeners) : void{
43 | foreach($listeners as $listener){
44 | $listener($player, $itemClicked, $itemClickedWith, $action);
45 | }
46 | };
47 | }
48 |
49 | public static function multipleReadWrite(Closure ...$listeners) : Closure{
50 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($listeners) : bool{
51 | foreach($listeners as $listener){
52 | if(!$listener($player, $itemClicked, $itemClickedWith, $action)){
53 | return false;
54 | }
55 | }
56 | return true;
57 | };
58 | }
59 |
60 | /**
61 | * An array of listeners indexed by the slot they should listen to.
62 | * Use index -1 for a "catch-all".
63 | *
64 | * @param InvMenu $menu
65 | * @param array $listeners
66 | * @return Closure
67 | */
68 | public static function slotSpecific(InvMenu $menu, array $listeners) : Closure{
69 | return $menu->isReadonly() ? self::slotSpecificReadonly($listeners) : self::slotSpecificReadWrite($listeners);
70 | }
71 |
72 | public static function slotSpecificReadonly(array $listeners) : Closure{
73 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($listeners) : void{
74 | $listener = $listeners[$action->getSlot()] ?? $listeners[-1] ?? null;
75 | if($listener !== null){
76 | $listener($player, $itemClicked, $itemClickedWith, $action);
77 | }
78 | };
79 | }
80 |
81 | public static function slotSpecificReadWrite(array $listeners) : Closure{
82 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($listeners) : bool{
83 | $listener = $listeners[$action->getSlot()] ?? $listeners[-1] ?? null;
84 | return $listener === null || $listener($player, $itemClicked, $itemClickedWith, $action);
85 | };
86 | }
87 |
88 | /**
89 | * @param int[] $slots
90 | * @return Closure
91 | */
92 | public static function blacklistSlots(array $slots) : Closure{
93 | $blacklist = new Set($slots);
94 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($blacklist) : bool{
95 | return !$blacklist->contains($action->getSlot());
96 | };
97 | }
98 |
99 | /**
100 | * @param int[] $slots
101 | * @return Closure
102 | */
103 | public static function whitelistSlots(array $slots) : Closure{
104 | $whitelist = new Set($slots);
105 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($whitelist) : bool{
106 | return $whitelist->contains($action->getSlot());
107 | };
108 | }
109 |
110 | /**
111 | * @param string $name
112 | * @param string $expectedClass
113 | * @return Closure
114 | */
115 | public static function onlyItemsWithTag(string $name, string $expectedClass = NamedTag::class) : Closure{
116 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($name, $expectedClass) : bool{
117 | return $itemClicked->getNamedTag()->hasTag($name, $expectedClass);
118 | };
119 | }
120 |
121 | /**
122 | * @param string $name
123 | * @param string $expectedClass
124 | * @return Closure
125 | */
126 | public static function onlyItemsWithoutTag(string $name, string $expectedClass = NamedTag::class) : Closure{
127 | return static function(Player $player, Item $itemClicked, Item $itemClickedWith, SlotChangeAction $action) use($name, $expectedClass) : bool{
128 | return !$itemClicked->getNamedTag()->hasTag($name, $expectedClass);
129 | };
130 | }
131 | }
--------------------------------------------------------------------------------
/virion.yml:
--------------------------------------------------------------------------------
1 | name: InvMenuUtils
2 | antigen: muqsit\invmenuutils
3 | api: 3.11.2
4 | version: 0.0.1
5 | author: Muqsit
6 |
--------------------------------------------------------------------------------