#Custom inventory has duplicate viewers

1 messages · Page 1 of 1 (latest)

paper bloom
#

I have an InventoryOpenEvent listener:

public class OpenEnderChestListener implements Listener {
    private final MagicBagPlugin plugin;

    public OpenEnderChestListener(MagicBagPlugin plugin) { this.plugin = plugin; }

    // deserialize inventory, put in activeenderchests hashmap then open inventory
    @EventHandler
    public void openEnderChest(InventoryOpenEvent event) {
        Bukkit.broadcastMessage("openEnderChest");
        if (!event.getInventory().getType().equals(InventoryType.ENDER_CHEST))
            return;
        TileState tileState = (TileState) event.getInventory().getLocation().getBlock().getState();
        if (!tileState.getPersistentDataContainer().has(plugin.getKey(), PersistentDataType.STRING))
            return;

        Block enderChestBlock = event.getInventory().getLocation().getBlock();
        Inventory enderChestInventory = plugin.getEnderChestInventory(enderChestBlock);
        Bukkit.broadcastMessage("before opening inventory: " + enderChestInventory.getViewers().toString());
        if (enderChestInventory == null)
            return;
        plugin.makeEnderChestActive(enderChestBlock, enderChestInventory);
        // this fires openInventoryEvent before this one has finished
        event.getPlayer().openInventory(enderChestInventory);
        Bukkit.broadcastMessage("after opening inventory: " + enderChestInventory.getViewers().toString());
        event.setCancelled(true);
        Bukkit.broadcastMessage("after cancelling event: " + enderChestInventory.getViewers().toString());
    }
}
#

and i have this InventoryCloseEvent listener:

public class CloseEnderChestListener implements Listener {
    private final MagicBagPlugin plugin;

    public CloseEnderChestListener(MagicBagPlugin plugin) { this.plugin = plugin; }

    @EventHandler
    public void closeEnderChest(InventoryCloseEvent event) {
        Bukkit.broadcastMessage("closeEnderChest: " + event.getViewers());

        if (!event.getInventory().getType().equals(InventoryType.CHEST))
            return;
        Bukkit.broadcastMessage("inventory type CHEST: " + event.getViewers());
        if (event.getInventory().getHolder() != null)
            return;
        if (event.getViewers().size() > 1)
            return;

        // if the player is a viewer of an active enderchest inventory, then this inventory must be that
        BidiMap<Block, Inventory> map = plugin.getActiveEnderChests();
        Player player = (Player) event.getPlayer();
        boolean active = false;
        for (Map.Entry<Block, Inventory> entry : map.entrySet()) {
            if (entry.getValue().getViewers().contains(player))
                active = true;
        }
        if (!active) return;

        Inventory enderChestInventory = event.getInventory();
        Block enderChestBlock = plugin.getActiveEnderChests().getKey(enderChestInventory);
        plugin.storeEnderChestInventory(enderChestBlock, enderChestInventory);
        plugin.makeEnderChestInactive(enderChestBlock, enderChestInventory);
    }
}
#

All the broadcastMessages in the open event show what I would expect, there are no viewers before the inventory has been opened and there is only one viewer after it has been

#

But for some reason from the start of the closeinventory listener, the inventory viewers list has two copies of the player in it

#

Why are there duplicates in the second event, and how do i fix this? I want to serialize and store the inventory once i know nobody is looking at it anymore

paper bloom
#

i am hoping this is me not understanding something about the way minecraft works

viral mortar
#

What are you trying to acomplish exactly?

#

I can only assume from the code you're trying to create your own ender-chest system?

#

this line alone would probably crash the server? an infinite loop of calling the same InventoryOpenEvent?

#
        // this fires openInventoryEvent before this one has finished
        event.getPlayer().openInventory(enderChestInventory);
paper bloom
#
    @EventHandler
    public void openEnderChest(InventoryOpenEvent event) {
        Bukkit.broadcastMessage("openEnderChest");
        if (!event.getInventory().getType().equals(InventoryType.ENDER_CHEST))
            return;
#

the opened inventory is a chest

#

I'm trying to make an enderchest behave like a normal chest

#

When a player opens the ender chest it's supposed to add that inventory to a hashmap in the plugin so when other players open the enderchest they all get the same inventory

#

I don't know if this is a good way to do that

viral mortar
#

Ohhh

#

In that case you don't want to be listening to an InventoryOpenEvent

#

You'll want to listen to an interact event

#

You can then check if they right-clicked an ender chest

paper bloom
#

I have an interact event but i put this on the openevent so the ender chest opening animation and sounds play

viral mortar
#

and open a regular chest GUI with no player handler

paper bloom
#

I will try and see if it fixes the issue though

viral mortar
#

is the player ever going to access their ec in this plugin? or are all ec's regular chests?

#

this might make it a bit easier if you care about the opening and sounds of the chest

paper bloom
#

all ender chests behave like normal until u use this item on one, then it becomes like a normal chest

#

i don't know why but it seems to have worked :0

paper bloom
#

moving it to the bottom of it ye

#

now i need to figure out how to play the enderchest animation

#

i think someone told me it the other day

viral mortar
#

ye was looking into that

#
public void playChestAction(Chest chest, boolean open)
{
  Location location = chest.getLocation();
  World world = ((CraftWorld) location.getWorld()).getHandle();
  BlockPosition position = new BlockPosition(location.getX(), location.getY(), location.getZ());
  TileEntityChest tileChest = (TileEntityChest) world.getTileEntity(position);
  world.playBlockAction(position, ((CraftBlock) location.getBlock()).getNMS().getBlock(), 1, open ? 1 : 0);
}
#

might have to try and adapt this for an enderchest

paper bloom
#

why do u do that casting and gethandle thing

#

thank u for finding that

viral mortar
#

A lot of implementations for things have 'Craft' infront of them

#

the 'getHandle()' is getting the NMS (net.minecraft.server) variant of this class

#

Instead of an import for org.bukkit.World, you should have an import for net.minecraft.world.level.World for that world variable

edgy sable
#

Mm packets

viral mortar
#

preferably not

edgy sable
#

I'd prob just spoof regular chests as ender chests tbh

viral mortar
#

op doesn't want that though

paper bloom
#

are packets easy and don't require updating

#

also i don't have the CraftWorld class, i looked it up and someone said they needed to put craftbukkit.jar somewhere specific but i can't find more info

viral mortar
#

on one hand there is ProtocolLib which means you now have a dependancy. Whenever you update, you have to wait for protocol lib to update.
on the other hand, you can just initialise and send packets yourself using NMS

edgy sable
#

player.sendBlockChange

#

It sucks but if you spam it enough

viral mortar
#

in this situation I don't think you need to directly send packets

paper bloom
#

i would like to do that playblockaction thing

edgy sable
#

Wasn't there a chest.setOpen

#

Or Liddable or something

#

I'm not home so just guessing

viral mortar
edgy sable
#

Ye that

viral mortar
#

can cast an ender chest block to lidded

#

and call open or close on it

edgy sable
#

No need to cast

viral mortar
#

well get from block then

paper bloom
#

:D:D

#

thank you guys

#

i will never learn nms or packets :pppp :D

viral mortar
#

You will at some point if you ever want to do something crazy or advanced lol

#

or the evil art of reverse engineering :p

paper bloom
edgy sable
#

eh pain

paper bloom
#

i thought protocollib made things easier