I'm trying to open a custom InventoryView to a player by using the openInventory(InventoryView view) method call. Except when I try and test it to see if it at least pops up on command, I get this exception. Code: org.bukkit.command.CommandException: Unhandled exception executing command 'jinv' in plugin KarmicJail v0.4 at org.bukkit.command.PluginCommand.execute(PluginCommand.java:42) at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:166) at org.bukkit.craftbukkit.CraftServer.dispatchCommand(CraftServer.java:473) at net.minecraft.server.NetServerHandler.handleCommand(NetServerHandler.java:821) at net.minecraft.server.NetServerHandler.chat(NetServerHandler.java:781) at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:764) at net.minecraft.server.Packet3Chat.handle(Packet3Chat.java:34) at net.minecraft.server.NetworkManager.b(NetworkManager.java:229) at net.minecraft.server.NetServerHandler.a(NetServerHandler.java:113) at net.minecraft.server.NetworkListenThread.a(NetworkListenThread.java:78) at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:551) at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:449) at net.minecraft.server.ThreadServerApplication.run(SourceFile:492) Caused by: java.lang.ClassCastException: com.mitsugaru.karmicjail.JailInventory$1 cannot be cast to org.bukkit.craftbukkit.inventory.CraftInventory at org.bukkit.craftbukkit.inventory.CraftContainer.<init>(CraftContainer.java:25) at org.bukkit.craftbukkit.entity.CraftHumanEntity.openInventory(CraftHumanEntity.java:282) at com.mitsugaru.karmicjail.FakeCommander.onCommand(FakeCommander.java:427) at com.mitsugaru.karmicjail.KarmicJail.onCommand(KarmicJail.java:87) at org.bukkit.command.PluginCommand.execute(PluginCommand.java:40) JailInventory class: Code: package com.mitsugaru.karmicjail; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import org.bukkit.Material; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; /** * Displays a jailed user's inventory. * * @author Tokume * */ public class JailInventory extends InventoryView { Player viewer; Inventory bottom; Inventory top; public JailInventory(Player viewer) { this.viewer = viewer; bottom = viewer.getInventory(); top = new Inventory() {//Anon inner class }; } @Override public Inventory getBottomInventory() { // TODO Auto-generated method stub return bottom; } @Override public HumanEntity getPlayer() { // TODO Auto-generated method stub return viewer; } @Override public Inventory getTopInventory() { // TODO Auto-generated method stub return top; } @Override public InventoryType getType() { // TODO Auto-generated method stub return InventoryType.CHEST; } } Is there something that I'm doing wrong?
I was curious, because I was thinking of implementing something like this as well, and wanted to know if anyone had tried it and got somewhere. Tracing through the code, it looks like that even if passing a custom InventoryView, the CraftContainer requires that both inventories be a CraftInventory (see here). Which means that as currently implemented, both inventories have to be something which comes from craftbukkit (like if you got the inventory of a block, or a minecart, or a player). You can make your own view, but it seems you'll need to attach it to some other existing, valid inventory. Some testing is required, but it may be possible to hide a chest block somewhere a ways away to use as your opposing inventory, and then you get the bonus of having the server handle the persistence for you. Edit I have from looking through the code decided that faking an Inventory at this point in time is not worth it, because it requires creating a CraftInventory, which in turn needs a net.minecraft.server.IInventory, and that just starts getting to be a headache because it requires depending on an API which can change drastically version to version. Edit2 You can do Code: getServer().createInventory(owner, InventoryType.CHEST) owner should be null since you don't want to associate this with an inventory.
Code:java Inventory inv = plugin.getServer().createInventory(this, 54, "Test"); // in this case "this" is a class that extends EntityEnderDragon implements InventoryHolder. ^^player.openInventory(inv); The ItemStack[] (inv.getContent()) is even serializeable, so you can save it to disk, send it over a network, ... Oh, and here's the old way for plugin.getServer().createInventory(this, 54, "Test"); Inventory inv = (Inventory)new InventoryLargeChest("test", new TileEntityChest(), new TileEntityChest()); the new one is better cause 54 can be any number (its the number of slots in the inv).
skimming over this, does that mean you can open an inventory thats as big as you want it? (similar to the creative mode inventory?) ...or set the size of a chest inventory..?
Yes, I didn't try it for myself but somebody noted somewhere that it's glitchy if you open a large inventory. Hum, maybe, but i don't think so.