-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit df24b9b
Showing
54 changed files
with
2,443 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
name: Backpack | ||
author: ShadowMikado | ||
api: [5.0.0] | ||
main: ShadowMikado\Backpack\Main | ||
version: 1.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
item: "diamond" | ||
|
||
permission: | ||
enabled: false | ||
name: "backpack.use" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
|
||
namespace ShadowMikado\Backpack; | ||
use muqsit\invmenu\InvMenuHandler; | ||
use pocketmine\event\Listener; | ||
use pocketmine\plugin\PluginBase; | ||
use pocketmine\utils\Config; | ||
use pocketmine\utils\SingletonTrait; | ||
use ShadowMikado\Backpack\listeners\backpack; | ||
|
||
class Main extends PluginBase implements Listener | ||
{ | ||
use SingletonTrait; | ||
|
||
public static Config $config; | ||
|
||
protected function onLoad(): void | ||
{ | ||
self::setInstance($this); | ||
$this->getLogger()->info("Loading..."); | ||
|
||
} | ||
|
||
protected function onEnable(): void | ||
{ | ||
$this->getLogger()->info("Enabling..."); | ||
|
||
if(!InvMenuHandler::isRegistered()){ | ||
InvMenuHandler::register($this); | ||
} | ||
|
||
$this->saveDefaultConfig(); | ||
self::$config = $this->getConfig(); | ||
|
||
$this->getServer()->getPluginManager()->registerEvents(new backpack(), $this); | ||
} | ||
|
||
protected function onDisable(): void | ||
{ | ||
$this->getLogger()->info("Disabling..."); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?php | ||
|
||
namespace ShadowMikado\Backpack\listeners; | ||
|
||
use muqsit\invmenu\InvMenu; | ||
use muqsit\invmenu\transaction\InvMenuTransaction; | ||
use muqsit\invmenu\transaction\InvMenuTransactionResult; | ||
use pocketmine\event\inventory\InventoryCloseEvent; | ||
use pocketmine\event\Listener; | ||
use pocketmine\event\player\PlayerItemUseEvent; | ||
use pocketmine\inventory\Inventory; | ||
use pocketmine\inventory\transaction\InventoryTransaction; | ||
use pocketmine\item\Item; | ||
use pocketmine\item\StringToItemParser; | ||
use pocketmine\item\VanillaItems; | ||
use pocketmine\nbt\tag\CompoundTag; | ||
use pocketmine\nbt\tag\ListTag; | ||
use pocketmine\player\Player; | ||
use ShadowMikado\Backpack\Main; | ||
|
||
class backpack implements Listener | ||
{ | ||
|
||
|
||
public function onUse(PlayerItemUseEvent $e) | ||
{ | ||
$player = $e->getPlayer(); | ||
|
||
if ($this->hasBackpackPermission($player) && $this->isBackpack($e->getItem())) { | ||
$bitem = $e->getItem(); | ||
|
||
$menu = InvMenu::create(InvMenu::TYPE_CHEST); | ||
$menu->setName("{$player->getName()}'s backpack"); | ||
|
||
$menu->setInventoryCloseListener( | ||
function (Player $player, Inventory $inventory) use ($bitem) { | ||
$bitem2 = clone $bitem; | ||
$bitem->pop(); | ||
echo "poped"; | ||
|
||
$inv = $inventory; | ||
if ($this->isBackpack($bitem)) { | ||
$contents = $inv->getContents(); | ||
|
||
$tags = []; | ||
|
||
foreach ($contents as $slot => $item) { | ||
$nbt = $item->nbtSerialize($slot); | ||
$tags[] = $nbt; | ||
} | ||
|
||
$taglist = CompoundTag::create()->setTag("items", new ListTag($tags)); | ||
$bitem2->setNamedTag($taglist); | ||
|
||
$player->getInventory()->setItemInHand($bitem2); | ||
} | ||
} | ||
); | ||
|
||
$backpack = $e->getItem(); | ||
$contents = []; | ||
|
||
|
||
$tlist = $backpack->getNamedTag()->getListTag("items"); | ||
if (!is_null($tlist)) { | ||
foreach ($tlist as $tags) { | ||
$item = Item::nbtDeserialize($tags); | ||
|
||
$contents[] = $item; | ||
} | ||
} else { | ||
$contents[] = VanillaItems::AIR(); | ||
} | ||
|
||
$menu->getInventory()->setContents($contents); | ||
|
||
$menu->send($player); | ||
|
||
|
||
} | ||
} | ||
|
||
private function hasBackpackPermission(Player $player): bool | ||
{ | ||
$permissionEnabled = Main::$config->getNested("permission.enabled"); | ||
$permissionName = Main::$config->getNested("permission.name"); | ||
|
||
return $permissionEnabled ? $player->hasPermission($permissionName) : true; | ||
} | ||
|
||
private function isBackpack(Item $item): bool | ||
{ | ||
$backpack = $this->nameToItem(Main::$config->get("item"))->getTypeId(); | ||
return $item->getTypeId() === $backpack; | ||
} | ||
|
||
private function nameToItem(string $name): Item | ||
{ | ||
return StringToItemParser::getInstance()->parse($name); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace muqsit\invmenu; | ||
|
||
use Closure; | ||
use LogicException; | ||
use muqsit\invmenu\inventory\SharedInvMenuSynchronizer; | ||
use muqsit\invmenu\session\InvMenuInfo; | ||
use muqsit\invmenu\session\network\PlayerNetwork; | ||
use muqsit\invmenu\transaction\DeterministicInvMenuTransaction; | ||
use muqsit\invmenu\transaction\InvMenuTransaction; | ||
use muqsit\invmenu\transaction\InvMenuTransactionResult; | ||
use muqsit\invmenu\transaction\SimpleInvMenuTransaction; | ||
use muqsit\invmenu\type\InvMenuType; | ||
use muqsit\invmenu\type\InvMenuTypeIds; | ||
use pocketmine\inventory\Inventory; | ||
use pocketmine\inventory\transaction\action\SlotChangeAction; | ||
use pocketmine\inventory\transaction\InventoryTransaction; | ||
use pocketmine\item\Item; | ||
use pocketmine\player\Player; | ||
|
||
class InvMenu implements InvMenuTypeIds{ | ||
|
||
/** | ||
* @param string $identifier | ||
* @param mixed ...$args | ||
* @return InvMenu | ||
*/ | ||
public static function create(string $identifier, ...$args) : InvMenu{ | ||
return new InvMenu(InvMenuHandler::getTypeRegistry()->get($identifier), ...$args); | ||
} | ||
|
||
/** | ||
* @param (Closure(DeterministicInvMenuTransaction) : void)|null $listener | ||
* @return Closure(InvMenuTransaction) : InvMenuTransactionResult | ||
*/ | ||
public static function readonly(?Closure $listener = null) : Closure{ | ||
return static function(InvMenuTransaction $transaction) use($listener) : InvMenuTransactionResult{ | ||
$result = $transaction->discard(); | ||
if($listener !== null){ | ||
$listener(new DeterministicInvMenuTransaction($transaction, $result)); | ||
} | ||
return $result; | ||
}; | ||
} | ||
|
||
readonly public InvMenuType $type; | ||
protected ?string $name = null; | ||
protected ?Closure $listener = null; | ||
protected ?Closure $inventory_close_listener = null; | ||
protected Inventory $inventory; | ||
protected ?SharedInvMenuSynchronizer $synchronizer = null; | ||
|
||
public function __construct(InvMenuType $type, ?Inventory $custom_inventory = null){ | ||
if(!InvMenuHandler::isRegistered()){ | ||
throw new LogicException("Tried creating menu before calling " . InvMenuHandler::class . "::register()"); | ||
} | ||
$this->type = $type; | ||
$this->inventory = $this->type->createInventory(); | ||
$this->setInventory($custom_inventory); | ||
} | ||
|
||
public function __destruct(){ | ||
$this->setInventory(null); | ||
} | ||
|
||
/** | ||
* @deprecated Access {@see InvMenu::$type} directly | ||
* @return InvMenuType | ||
*/ | ||
public function getType() : InvMenuType{ | ||
return $this->type; | ||
} | ||
|
||
public function getName() : ?string{ | ||
return $this->name; | ||
} | ||
|
||
public function setName(?string $name) : self{ | ||
$this->name = $name; | ||
return $this; | ||
} | ||
|
||
/** | ||
* @return (Closure(InvMenuTransaction) : InvMenuTransactionResult)|null | ||
*/ | ||
public function getListener() : ?Closure{ | ||
return $this->listener; | ||
} | ||
|
||
/** | ||
* @param (Closure(InvMenuTransaction) : InvMenuTransactionResult)|null $listener | ||
* @return self | ||
*/ | ||
public function setListener(?Closure $listener) : self{ | ||
$this->listener = $listener; | ||
return $this; | ||
} | ||
|
||
/** | ||
* @return (Closure(Player, Inventory) : void)|null | ||
*/ | ||
public function getInventoryCloseListener() : ?Closure{ | ||
return $this->inventory_close_listener; | ||
} | ||
|
||
/** | ||
* @param (Closure(Player, Inventory) : void)|null $listener | ||
* @return self | ||
*/ | ||
public function setInventoryCloseListener(?Closure $listener) : self{ | ||
$this->inventory_close_listener = $listener; | ||
return $this; | ||
} | ||
|
||
public function getInventory() : Inventory{ | ||
return $this->inventory; | ||
} | ||
|
||
public function setInventory(?Inventory $custom_inventory) : void{ | ||
if($this->synchronizer !== null){ | ||
$this->synchronizer->destroy(); | ||
$this->synchronizer = null; | ||
} | ||
|
||
if($custom_inventory !== null){ | ||
$this->synchronizer = new SharedInvMenuSynchronizer($this, $custom_inventory); | ||
} | ||
} | ||
|
||
/** | ||
* @param Player $player | ||
* @param string|null $name | ||
* @param (Closure(bool) : void)|null $callback | ||
*/ | ||
final public function send(Player $player, ?string $name = null, ?Closure $callback = null) : void{ | ||
$player->removeCurrentWindow(); | ||
|
||
$session = InvMenuHandler::getPlayerManager()->get($player); | ||
$network = $session->network; | ||
|
||
// Avoid players from spamming InvMenu::send() and other similar | ||
// requests and filling up queued tasks in memory. | ||
// It would be better if this check were implemented by plugins, | ||
// however I suppose it is more convenient if done within InvMenu... | ||
if($network->getPending() >= 8){ | ||
$network->dropPending(); | ||
}else{ | ||
$network->dropPendingOfType(PlayerNetwork::DELAY_TYPE_OPERATION); | ||
} | ||
|
||
$network->waitUntil(PlayerNetwork::DELAY_TYPE_OPERATION, 0, function(bool $success) use($player, $session, $name, $callback) : bool{ | ||
if(!$success){ | ||
if($callback !== null){ | ||
$callback(false); | ||
} | ||
return false; | ||
} | ||
|
||
$graphic = $this->type->createGraphic($this, $player); | ||
if($graphic !== null){ | ||
$session->setCurrentMenu(new InvMenuInfo($this, $graphic, $name), static function(bool $success) use($callback) : void{ | ||
if($callback !== null){ | ||
$callback($success); | ||
} | ||
}); | ||
}else{ | ||
if($callback !== null){ | ||
$callback(false); | ||
} | ||
} | ||
return false; | ||
}); | ||
} | ||
|
||
/** | ||
* @internal use InvMenu::send() instead. | ||
* | ||
* @param Player $player | ||
* @return bool | ||
*/ | ||
public function sendInventory(Player $player) : bool{ | ||
return $player->setCurrentWindow($this->getInventory()); | ||
} | ||
|
||
public function handleInventoryTransaction(Player $player, Item $out, Item $in, SlotChangeAction $action, InventoryTransaction $transaction) : InvMenuTransactionResult{ | ||
$inv_menu_txn = new SimpleInvMenuTransaction($player, $out, $in, $action, $transaction); | ||
return $this->listener !== null ? ($this->listener)($inv_menu_txn) : $inv_menu_txn->continue(); | ||
} | ||
|
||
public function onClose(Player $player) : void{ | ||
if($this->inventory_close_listener !== null){ | ||
($this->inventory_close_listener)($player, $this->getInventory()); | ||
} | ||
|
||
InvMenuHandler::getPlayerManager()->get($player)->removeCurrentMenu(); | ||
} | ||
} |
Oops, something went wrong.