How verify if chest is double chest


Hi guys, need help to verify if a chest is double chest using InteractBlockEvent, i started using SpongeAPI a short time ago and I’m having difficulties compared to BukkitAPI


Sponge is a learning curve compared to Bukkit as Bukkit has the ability to assume some features of the minecraft server as it was designed to work on its own and only its own. Sponge can work with Forge (and anything if someone makes it) so Sponge can not assume.

Anyway I can think of 2 ways. One that will work on all Sponge versions until 1.12.2 (AKA it wont work on 1.13 … but its simpler to make).

Way 1 X.X-1.13+
The one that works on all versions would be to get the Tile Entity and cast it to a Chest. From there get the Inventory of the chest and then check the max size of the inventory and check if it is 54 (I think thats a double) or 27 (I think thats a single).

Way 2 X.X-1.12.2
Get all 4 main Directions (AKA NORTH, EAST, SOUTH and WEST) and then compare that with the current chest block and check for another chest block. (In Minecraft Alpha-1.12.2 Release you can not place a chest next to another chest without making it a double and then you cannot place another chest next to that double, but you can in 1.13 - I still would not recommend this way as plugins and mods can actually place single chests next to one another (I think) and it not forward compatible … not that it would be anyway


I made it:

public void onUseTicket(InteractBlockEvent event){
    Player player = event.getCause().first(Player.class).get();
    if(event.getTargetBlock().getExtendedState().getType() == BlockTypes.CHEST){
        Chest chest = (Chest)event.getTargetBlock().getExtendedState().getType();
        if(chest.getInventory().capacity() != 54) return;
        Sponge.getServer().getBroadcastChannel().send(Text.of("It's a DoubleChest"));

but cause this error:

[Sponge]: Could not pass InteractBlockEvent$Secondary$Impl to Plugin{id=modernage, name=ModernAge Brasil, version=1.0-SNAPSHOT, source=mods\ModernAge.jar}
java.lang.AbstractMethodError: Method net/minecraft/tileentity/TileEntityChest.getInventory()Lorg/spongepowered/api/item/inventory/type/TileEntityInventory; is abstract
	at net.minecraft.tileentity.TileEntityChest.getInventory(SourceFile) ~[aky.class:?]
	at org.spongepowered.api.block.tileentity.carrier.TileEntityCarrier.getInventory( ~[TileEntityCarrier.class:1.8.9-4.2.0-BETA-352]
	at me.muloo.modernage.Main.onUseTicket( ~[Main.class:?]
	at org.spongepowered.common.event.listener.InteractBlockEventListener_Main_onUseTicket5.handle(Unknown Source) ~[?:?]
	at org.spongepowered.common.event.RegisteredListener.handle( ~[RegisteredListener.class:1.8.9-4.2.0-BETA-352]
	at [SpongeEventManager.class:1.8.9-4.2.0-BETA-352]
	at [SpongeEventManager.class:1.8.9-4.2.0-BETA-352]
	at org.spongepowered.common.SpongeImpl.postEvent( [SpongeImpl.class:1.8.9-4.2.0-BETA-352]
	at org.spongepowered.common.event.SpongeCommonEventFactory.callInteractBlockEventSecondary( [SpongeCommonEventFactory.class:1.8.9-4.2.0-BETA-352]
	at org.spongepowered.common.event.SpongeCommonEventFactory.callInteractBlockEventSecondary( [SpongeCommonEventFactory.class:1.8.9-4.2.0-BETA-352]
	at [lg.class:?]
	at [lm.class:?]
	at [ja.class:?]
	at [ja.class:?]
	at [PacketUtil.class:1.8.9-4.2.0-BETA-352]
	at$1.redirect$onProcessPacket$0(SourceFile:39) [fh$1.class:?]
	at$ [fh$1.class:?]
	at java.util.concurrent.Executors$ Source) [?:1.8.0_161]
	at Source) [?:1.8.0_161]
	at net.minecraft.util.Util.func_181617_a(SourceFile:44) [g.class:?]
	at net.minecraft.server.MinecraftServer.func_71190_q(SourceFile:143) [MinecraftServer.class:?]
	at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(SourceFile:299) [ko.class:?]
	at net.minecraft.server.MinecraftServer.func_71217_p(SourceFile:535) [MinecraftServer.class:?]
	at [MinecraftServer.class:?]
	at Source) [?:1.8.0_161]


Nice attempt. However BlockType can not be cast into a Chest. Check out “Tile Entity” link I put in the above post. Or you can take a look below. Also in java the == only applies to primitive types (aka int, double, float, char, etc.)


I have written in comments into the code with numbers, those numbers relate to text just below here.

  1. @First is a simpler way to find the first type within the cause tracker. Because I specified a player, it will find the first Player. You can read more here

  2. Personally I don’t like working with BlockSnapshots (much prefer BlockState) but because we can only get the tile entity from a location (I believe), we must get the location

  3. TileEntity is like BlockState from Bukkit (I.E if(block.getState() instanceof Chest). You can read more in the link provided in my last post.

  4. This part of the code just throws out the event if the block does not have a TileEntity attached. As all Chests have a TileEntity attached the block (if returned true for not having one) will not be a chest.

  5. This part checks that the TileEntity is a chests TileEntity as only Chests and DoubleChests can have this TileEntity. It throws out if not a chest

     public void onUseTicket(InteractBlockEvent event, @First Player player) { //1
         BlockSnapshot snapshot = event.getTargetBlock();
         Location<World> loc = snapshot.getLocation().get(); //2
         Optional<TileEntity> opTile = loc.getTileEntity(); //3
         if(!opTile.isPresent()){ //4
         TileEntity tile = opTile.get();
         if(!(tile instanceof Chest)) { //5
         Chest chest = (Chest)tile;
         if(chest.getInventory().capacity() != 54){


Your code works, but it only takes inventory from a single chest, even if they are connected it only takes the 27


Oh yeah. Sorry. Forgot they changed it. At the


There is a new method called

Optional<Inventory> opInv = chest.getDoubleChestInventory();

If that is present its a double chest, if not its a single