Skip to content

Commit

Permalink
New Features: Custom Inventory Size & others
Browse files Browse the repository at this point in the history
  • Loading branch information
ShadowMikado authored Dec 18, 2023
1 parent 6a04145 commit c4f6aae
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 12 deletions.
Binary file added resources/InventoryUIResourcePack.mcpack
Binary file not shown.
2 changes: 2 additions & 0 deletions resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ item_configuration:
lore_empty: "§r§9Empty§r"
lore_content: "§r§9 {item} §6x{count}§r"
display_name_after_use: "§r§f{player}'s Backpack"
can_put_backpack_in_backpack: false

ui_configuration:
display_name: "{player}'s Backpack"
inv_size: 9

pack_configuration:
pack_name: "BackpackRP.mcpack"
19 changes: 18 additions & 1 deletion src/ShadowMikado/Backpack/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

namespace ShadowMikado\Backpack;

use muqsit\customsizedinvmenu\CustomSizedInvMenu;
use muqsit\invmenu\InvMenuHandler;
use pocketmine\inventory\CreativeInventory;
use pocketmine\item\ItemIdentifier;
use pocketmine\item\StringToItemParser;
use pocketmine\item\VanillaItems;
use pocketmine\plugin\PluginBase;
use pocketmine\plugin\PluginDescription;
use pocketmine\plugin\PluginLoader;
use pocketmine\plugin\ResourceProvider;
use pocketmine\resourcepacks\ZippedResourcePack;
use pocketmine\Server;
use pocketmine\utils\Config;
use pocketmine\utils\SingletonTrait;
use ShadowMikado\Backpack\listeners\backpack;
Expand All @@ -20,6 +24,14 @@ class Main extends PluginBase

public static Config $config;

private ResourceProvider $resourceProvider;

public function __construct(PluginLoader $loader, Server $server, PluginDescription $description, string $dataFolder, string $file, ResourceProvider $resourceProvider)
{
$this->resourceProvider = $resourceProvider;
parent::__construct($loader, $server, $description, $dataFolder, $file, $this->resourceProvider);
}

protected function onLoad(): void
{
self::setInstance($this);
Expand All @@ -38,9 +50,11 @@ protected function onEnable(): void
$this->saveDefaultConfig();
self::$config = $this->getConfig();
$this->saveResource(self::$config->getNested("pack_configuration.pack_name"));
$this->saveResource("InventoryUIResourcePack.mcpack");

$rpManager = $this->getServer()->getResourcePackManager();
$rpManager->setResourceStack(array_merge($rpManager->getResourceStack(), [new ZippedResourcePack(Path::join($this->getDataFolder(), self::$config->getNested("pack_configuration.pack_name")))]));
$rpManager->setResourceStack(array_merge($rpManager->getResourceStack(), [new ZippedResourcePack(Path::join($this->getDataFolder(), "InventoryUIResourcePack.mcpack"))]));
(new \ReflectionProperty($rpManager, "serverForceResources"))->setValue($rpManager, true);

$parsed = StringToItemParser::getInstance()->parse(self::$config->get("item"));
Expand All @@ -50,6 +64,9 @@ protected function onEnable(): void
CreativeInventory::getInstance()->add($item);
$this->getServer()->getPluginManager()->registerEvents(new backpack(), $this);


$customsizedinvmenu = new CustomSizedInvMenu($this->getPluginLoader(), $this->getServer(), $this->getDescription(), $this->getDataFolder(), $this->getFile(), $this->resourceProvider);
$customsizedinvmenu->onEnable();
}

protected function onDisable(): void
Expand Down
25 changes: 14 additions & 11 deletions src/ShadowMikado/Backpack/listeners/backpack.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ShadowMikado\Backpack\listeners;

use muqsit\customsizedinvmenu\CustomSizedInvMenu;
use pocketmine\event\Listener;
use pocketmine\event\player\PlayerItemUseEvent;
use pocketmine\item\Item;
Expand All @@ -27,18 +28,20 @@ public function onUse(PlayerItemUseEvent $e)
if ($this->hasBackpackPermission($player) && $this->isBackpack($e->getItem())) {
$backpack = $e->getItem();
$bitem = $e->getItem();
$menu = InvMenu::create(InvMenu::TYPE_CHEST);

$menu = CustomSizedInvMenu::create(Main::$config->getNested("ui_configuration.inv_size"));
$menu->setName(str_replace("{player}", $player->getName(), Main::$config->getNested("ui_configuration.display_name")));
$menu->setListener(function (InvMenuTransaction $transaction) use ($bitem): InvMenuTransactionResult {
if ($this->isBackpack($transaction->getItemClickedWith())) {
$transaction->getPlayer()->getWorld()->addSound($transaction->getPlayer()->getPosition(), new NoteSound(NoteInstrument::GUITAR(), 0));
$transaction->getPlayer()->sendPopup(Main::$config->getNested("messages.item_disabled"));
return $transaction->discard();
} else {
return $transaction->continue();
}
});

if (!Main::$config->getNested("item_configuration.can_put_backpack_in_backpack")) {
$menu->setListener(function (InvMenuTransaction $transaction) use ($bitem): InvMenuTransactionResult {
if ($this->isBackpack($transaction->getItemClickedWith())) {
$transaction->getPlayer()->getWorld()->addSound($transaction->getPlayer()->getPosition(), new NoteSound(NoteInstrument::GUITAR(), 0));
$transaction->getPlayer()->sendPopup(Main::$config->getNested("messages.item_disabled"));
return $transaction->discard();
} else {
return $transaction->continue();
}
});
}

$menu->setInventoryCloseListener(function (Player $player, InvMenuInventory $inventory) use ($bitem) {
echo $bitem->getCustomName();
Expand Down
52 changes: 52 additions & 0 deletions src/muqsit/customsizedinvmenu/CustomSizedActorInvMenuGraphic.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace muqsit\customsizedinvmenu;

use muqsit\invmenu\type\graphic\InvMenuGraphic;
use muqsit\invmenu\type\graphic\network\InvMenuGraphicNetworkTranslator;
use pocketmine\inventory\Inventory;
use pocketmine\player\Player;

final class CustomSizedActorInvMenuGraphic implements InvMenuGraphic
{

readonly private string $size_data;

public function __construct(
readonly private InvMenuGraphic $inner,
readonly private ?string $name,
readonly private int $length,
readonly private bool $scrollbar
)
{
$scroll = (int)$this->scrollbar;
$this->size_data = "§{$this->length}§{$scroll}§r§r§r§r§r§r§r§r§r§r";
}

public function send(Player $player, ?string $name): void
{
$this->inner->send($player, $this->size_data . ($name ?? $this->name ?? "Inventory"));
}

public function sendInventory(Player $player, Inventory $inventory): bool
{
return $this->inner->sendInventory($player, $inventory);
}

public function remove(Player $player): void
{
$this->inner->remove($player);
}

public function getNetworkTranslator(): ?InvMenuGraphicNetworkTranslator
{
return $this->inner->getNetworkTranslator();
}

public function getAnimationDuration(): int
{
return $this->inner->getAnimationDuration();
}
}
87 changes: 87 additions & 0 deletions src/muqsit/customsizedinvmenu/CustomSizedInvMenu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace muqsit\customsizedinvmenu;

use muqsit\invmenu\InvMenu;
use muqsit\invmenu\InvMenuHandler;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\item\VanillaItems;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\cache\StaticPacketCache;
use pocketmine\player\Player;
use pocketmine\plugin\PluginBase;
use pocketmine\utils\TextFormat;
use RuntimeException;
use function array_rand;
use function assert;
use function is_numeric;

final class CustomSizedInvMenu extends PluginBase
{

private const RESOURCE_PACK_ID = "21f0427f-572a-416d-a90e-c5d9becb0fa3";
private const TYPE_DYNAMIC_PREFIX = "muqsit:customsizedinvmenu_";

public function onEnable(): void
{
if ($this->getServer()->getResourcePackManager()->getPackById(self::RESOURCE_PACK_ID) === null) {
$this->getLogger()->warning("Resource pack 'Inventory UI Resource Pack' could not be found.");
$this->getLogger()->warning("This plugin cannot be loaded. Please download the resource pack from: https://github.com/tedo0627/InventoryUIResourcePack");
throw new RuntimeException("Resource pack 'Inventory UI Resource Pack' has not been loaded");
}

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

$packet = StaticPacketCache::getInstance()->getAvailableActorIdentifiers();
$tag = $packet->identifiers->getRoot();
assert($tag instanceof CompoundTag);
$id_list = $tag->getListTag("idlist");
assert($id_list !== null);
$id_list->push(CompoundTag::create()
->setString("bid", "")
->setByte("hasspawnegg", 0)
->setString("id", CustomSizedInvMenuType::ACTOR_NETWORK_ID)
->setByte("summonable", 0)
);
}

public static function create(int $size): InvMenu
{
static $ids_by_size = [];
if (!isset($ids_by_size[$size])) {
$id = self::TYPE_DYNAMIC_PREFIX . $size;
InvMenuHandler::getTypeRegistry()->register($id, CustomSizedInvMenuType::ofSize($size));
$ids_by_size[$size] = $id;
}
return InvMenu::create($ids_by_size[$size]);
}

public function onCommand(CommandSender $sender, Command $command, string $label, array $args): bool
{
if (!($sender instanceof Player)) {
$sender->sendMessage(TextFormat::RED . "Please use this command in-game.");
return true;
}

if (!isset($args[0]) || !is_numeric($args[0]) || (int)$args[0] <= 0) {
$sender->sendMessage(TextFormat::RED . "/" . $command . " <numSlots : int> [title : string]");
return true;
}

$menu = CustomSizedInvMenu::create((int)$args[0]);
$menu->setName($args[1] ?? null);

$items = VanillaItems::getAll();
for ($i = 0, $max = $menu->getInventory()->getSize(); $i < $max; $i++) {
$menu->getInventory()->setItem($i, $items[array_rand($items)]);
}

$menu->send($sender);
return true;
}
}
64 changes: 64 additions & 0 deletions src/muqsit/customsizedinvmenu/CustomSizedInvMenuType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace muqsit\customsizedinvmenu;

use muqsit\invmenu\inventory\InvMenuInventory;
use muqsit\invmenu\InvMenu;
use muqsit\invmenu\type\graphic\ActorInvMenuGraphic;
use muqsit\invmenu\type\graphic\InvMenuGraphic;
use muqsit\invmenu\type\graphic\network\ActorInvMenuGraphicNetworkTranslator;
use muqsit\invmenu\type\InvMenuType;
use pocketmine\entity\Entity;
use pocketmine\inventory\Inventory;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties;
use pocketmine\network\mcpe\protocol\types\inventory\WindowTypes;
use pocketmine\player\Player;
use function intdiv;
use function min;

final class CustomSizedInvMenuType implements InvMenuType
{

public const ACTOR_NETWORK_ID = "inventoryui:inventoryui";
readonly private ActorInvMenuGraphic $inner_graphic;

public function __construct(
readonly private int $size,
readonly private int $length,
readonly private bool $scrollbar
)
{
$actor_runtime_identifier = Entity::nextRuntimeId();

$properties = new EntityMetadataCollection();
$properties->setByte(EntityMetadataProperties::CONTAINER_TYPE, WindowTypes::INVENTORY);
$properties->setInt(EntityMetadataProperties::CONTAINER_BASE_SIZE, $this->size);

$this->inner_graphic = new ActorInvMenuGraphic(
self::ACTOR_NETWORK_ID,
$actor_runtime_identifier,
$properties->getAll(),
new ActorInvMenuGraphicNetworkTranslator($actor_runtime_identifier)
);
}

public static function ofSize(int $size): self
{
$length = intdiv($size, 9) + ($size % 9 === 0 ? 0 : 1);
$length = min($length, 6);
return new self($size, $length, $length * 9 < $size);
}

public function createGraphic(InvMenu $menu, Player $player): ?InvMenuGraphic
{
return new CustomSizedActorInvMenuGraphic($this->inner_graphic, $menu->getName(), $this->length, $this->scrollbar);
}

public function createInventory(): Inventory
{
return new InvMenuInventory($this->size);
}
}

0 comments on commit c4f6aae

Please sign in to comment.