[Bleeding] Implementation of inventory framework. Addresses BUKKIT-856
See the corresponding Bukkit commit for details. Implementation details: - Any packets that include an itemstack will send air stacks as null; maybe this will even eliminate the client crash that occurs if the client receives an air stack - Better handling of null itemstacks in general (ie less converting them to air stacks) - Inventory.setContents() can now take an array smaller than the inventory without error - Player.updateInventory() should now correctly update the result slot in a crafting inventory Some small credit goes to Afforess (initial implementation of openInventory() methods) and Drakia (initial implementation of InventoryOpenEvent and InventoryCloseEvent). By: Celtic Minstrel <celtic.minstrel.ca@some.place>
This commit is contained in:
@@ -1,12 +1,33 @@
|
||||
package org.bukkit.craftbukkit.entity;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.server.Container;
|
||||
import net.minecraft.server.EntityHuman;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.ICrafting;
|
||||
import net.minecraft.server.Packet100OpenWindow;
|
||||
import net.minecraft.server.Packet101CloseWindow;
|
||||
import net.minecraft.server.TileEntityBrewingStand;
|
||||
import net.minecraft.server.TileEntityDispenser;
|
||||
import net.minecraft.server.TileEntityFurnace;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.inventory.CraftContainer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryPlayer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.Permission;
|
||||
@@ -42,6 +63,18 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
getInventory().setItemInHand(item);
|
||||
}
|
||||
|
||||
public ItemStack getItemOnCursor() {
|
||||
return new CraftItemStack(getHandle().inventory.l());
|
||||
}
|
||||
|
||||
public void setItemOnCursor(ItemStack item) {
|
||||
CraftItemStack stack = new CraftItemStack(item.getType(), item.getAmount(), item.getDurability());
|
||||
getHandle().inventory.b(stack.getHandle());
|
||||
if (this instanceof CraftPlayer) {
|
||||
((EntityPlayer)getHandle()).D(); // Send set slot for cursor
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSleeping() {
|
||||
return getHandle().sleeping;
|
||||
}
|
||||
@@ -129,4 +162,111 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
||||
public String toString() {
|
||||
return "CraftHumanEntity{" + "id=" + getEntityId() + "name=" + getName() + '}';
|
||||
}
|
||||
|
||||
public InventoryView getOpenInventory() {
|
||||
return getHandle().activeContainer.getBukkitView();
|
||||
}
|
||||
|
||||
public InventoryView openInventory(Inventory inventory) {
|
||||
InventoryType type = inventory.getType();
|
||||
// TODO: Should we check that it really IS a CraftInventory first?
|
||||
CraftInventory craftinv = (CraftInventory) inventory;
|
||||
switch(type) {
|
||||
case PLAYER:
|
||||
case CHEST:
|
||||
getHandle().a(craftinv.getInventory());
|
||||
break;
|
||||
case DISPENSER:
|
||||
getHandle().a((TileEntityDispenser)craftinv.getInventory());
|
||||
break;
|
||||
case FURNACE:
|
||||
getHandle().a((TileEntityFurnace)craftinv.getInventory());
|
||||
break;
|
||||
case WORKBENCH:
|
||||
getHandle().b(getLocation().getBlockX(), getLocation().getBlockY(), getLocation().getBlockZ());
|
||||
break;
|
||||
case BREWING:
|
||||
getHandle().a((TileEntityBrewingStand)craftinv.getInventory());
|
||||
break;
|
||||
case ENCHANTING:
|
||||
getHandle().c(getLocation().getBlockX(), getLocation().getBlockY(), getLocation().getBlockZ());
|
||||
break;
|
||||
case CREATIVE:
|
||||
case CRAFTING:
|
||||
throw new IllegalArgumentException("Can't open a " + type + " inventory!");
|
||||
}
|
||||
getHandle().activeContainer.checkReachable = false;
|
||||
return getHandle().activeContainer.getBukkitView();
|
||||
}
|
||||
|
||||
public InventoryView openWorkbench(Location location, boolean force) {
|
||||
if (!force) {
|
||||
Block block = location.getBlock();
|
||||
if (block.getType() != Material.WORKBENCH) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (location == null) {
|
||||
location = getLocation();
|
||||
}
|
||||
getHandle().b(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
if (force) {
|
||||
getHandle().activeContainer.checkReachable = false;
|
||||
}
|
||||
return getHandle().activeContainer.getBukkitView();
|
||||
}
|
||||
|
||||
public InventoryView openEnchanting(Location location, boolean force) {
|
||||
if (!force) {
|
||||
Block block = location.getBlock();
|
||||
if (block.getType() != Material.ENCHANTMENT_TABLE) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (location == null) {
|
||||
location = getLocation();
|
||||
}
|
||||
getHandle().c(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
if (force) {
|
||||
getHandle().activeContainer.checkReachable = false;
|
||||
}
|
||||
return getHandle().activeContainer.getBukkitView();
|
||||
}
|
||||
|
||||
public void openInventory(InventoryView inventory) {
|
||||
if (!(getHandle() instanceof EntityPlayer)) return; // TODO: NPC support?
|
||||
if (getHandle().activeContainer != getHandle().defaultContainer) {
|
||||
// fire INVENTORY_CLOSE if one already open
|
||||
((EntityPlayer)getHandle()).netServerHandler.a(new Packet101CloseWindow(getHandle().activeContainer.windowId));
|
||||
}
|
||||
EntityPlayer player = (EntityPlayer) getHandle();
|
||||
Container container;
|
||||
if (inventory instanceof CraftInventoryView) {
|
||||
container = ((CraftInventoryView) inventory).getHandle();
|
||||
} else {
|
||||
container = new CraftContainer(inventory, player.aS());
|
||||
}
|
||||
|
||||
// Trigger an INVENTORY_OPEN event
|
||||
InventoryOpenEvent event = new InventoryOpenEvent(inventory);
|
||||
player.activeContainer.transferTo(container, this);
|
||||
server.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
container.transferTo(player.activeContainer, this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Now open the window
|
||||
player.netServerHandler.sendPacket(new Packet100OpenWindow(container.windowId, 1, "Crafting", 9));
|
||||
player.activeContainer = container;
|
||||
player.activeContainer.a((ICrafting) player);
|
||||
}
|
||||
|
||||
public void closeInventory() {
|
||||
getHandle().closeInventory();
|
||||
}
|
||||
|
||||
public boolean setWindowProperty(InventoryView.Property prop, int value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,20 @@ import net.minecraft.server.*;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.*;
|
||||
|
||||
import net.minecraft.server.Container;
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.Packet131ItemData;
|
||||
import net.minecraft.server.Packet200Statistic;
|
||||
import net.minecraft.server.Packet201PlayerInfo;
|
||||
import net.minecraft.server.Packet3Chat;
|
||||
import net.minecraft.server.Packet51MapChunk;
|
||||
import net.minecraft.server.Packet53BlockChange;
|
||||
import net.minecraft.server.Packet54PlayNoteBlock;
|
||||
import net.minecraft.server.Packet61WorldEvent;
|
||||
import net.minecraft.server.Packet6SpawnPosition;
|
||||
import net.minecraft.server.Packet70Bed;
|
||||
import net.minecraft.server.WorldServer;
|
||||
import org.bukkit.Achievement;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
@@ -33,6 +47,7 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.inventory.InventoryView.Property;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@@ -742,4 +757,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
public void removeMetadata(String metadataKey, Plugin owningPlugin) {
|
||||
server.getPlayerMetadata().removeMetadata(this, metadataKey, owningPlugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setWindowProperty(Property prop, int value) {
|
||||
Container container = getHandle().activeContainer;
|
||||
if (container.getBukkitView().getType() != prop.getType()) {
|
||||
return false;
|
||||
}
|
||||
getHandle().a(container, prop.getId(), value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user