Skip to content

Commit

Permalink
Added files
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadowMikado authored Dec 16, 2023
0 parents commit df24b9b
Show file tree
Hide file tree
Showing 54 changed files with 2,443 additions and 0 deletions.
5 changes: 5 additions & 0 deletions plugin.yml
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
5 changes: 5 additions & 0 deletions resources/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
item: "diamond"

permission:
enabled: false
name: "backpack.use"
43 changes: 43 additions & 0 deletions src/ShadowMikado/Backpack/Main.php
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...");
}

}
101 changes: 101 additions & 0 deletions src/ShadowMikado/Backpack/listeners/backpack.php
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);
}
}
200 changes: 200 additions & 0 deletions src/muqsit/invmenu/InvMenu.php
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();
}
}
Loading

0 comments on commit df24b9b

Please sign in to comment.