001 package org.bukkit.inventory; 002 003 import org.bukkit.GameMode; 004 import org.bukkit.entity.HumanEntity; 005 import org.bukkit.event.inventory.InventoryType; 006 007 /** 008 * Represents a view linking two inventories and a single player (whose 009 * inventory may or may not be one of the two). 010 * <p> 011 * Note: If you implement this interface but fail to satisfy the expected 012 * contracts of certain methods, there's no guarantee that the game will work 013 * as it should. 014 */ 015 public abstract class InventoryView { 016 public final static int OUTSIDE = -999; 017 /** 018 * Represents various extra properties of certain inventory windows. 019 */ 020 public enum Property { 021 /** 022 * The progress of the down-pointing arrow in a brewing inventory. 023 */ 024 BREW_TIME(0, InventoryType.BREWING), 025 /** 026 * The progress of the right-pointing arrow in a furnace inventory. 027 */ 028 COOK_TIME(0, InventoryType.FURNACE), 029 /** 030 * The progress of the flame in a furnace inventory. 031 */ 032 BURN_TIME(1, InventoryType.FURNACE), 033 /** 034 * How many total ticks the current fuel should last. 035 */ 036 TICKS_FOR_CURRENT_FUEL(2, InventoryType.FURNACE), 037 /** 038 * In an enchanting inventory, the top button's experience level 039 * value. 040 */ 041 ENCHANT_BUTTON1(0, InventoryType.ENCHANTING), 042 /** 043 * In an enchanting inventory, the middle button's experience level 044 * value. 045 */ 046 ENCHANT_BUTTON2(1, InventoryType.ENCHANTING), 047 /** 048 * In an enchanting inventory, the bottom button's experience level 049 * value. 050 */ 051 ENCHANT_BUTTON3(2, InventoryType.ENCHANTING); 052 int id; 053 InventoryType style; 054 private Property(int id, InventoryType appliesTo) { 055 this.id = id; 056 style = appliesTo; 057 } 058 059 public InventoryType getType() { 060 return style; 061 } 062 063 /** 064 * 065 * @deprecated Magic value 066 */ 067 @Deprecated 068 public int getId() { 069 return id; 070 } 071 } 072 /** 073 * Get the upper inventory involved in this transaction. 074 * 075 * @return the inventory 076 */ 077 public abstract Inventory getTopInventory(); 078 079 /** 080 * Get the lower inventory involved in this transaction. 081 * 082 * @return the inventory 083 */ 084 public abstract Inventory getBottomInventory(); 085 086 /** 087 * Get the player viewing. 088 * 089 * @return the player 090 */ 091 public abstract HumanEntity getPlayer(); 092 093 /** 094 * Determine the type of inventory involved in the transaction. This 095 * indicates the window style being shown. It will never return PLAYER, 096 * since that is common to all windows. 097 * 098 * @return the inventory type 099 */ 100 public abstract InventoryType getType(); 101 102 /** 103 * Sets one item in this inventory view by its raw slot ID. 104 * <p> 105 * Note: If slot ID -999 is chosen, it may be expected that the item is 106 * dropped on the ground. This is not required behaviour, however. 107 * 108 * @param slot The ID as returned by InventoryClickEvent.getRawSlot() 109 * @param item The new item to put in the slot, or null to clear it. 110 */ 111 public void setItem(int slot, ItemStack item) { 112 if (slot != OUTSIDE) { 113 if (slot < getTopInventory().getSize()) { 114 getTopInventory().setItem(convertSlot(slot),item); 115 } else { 116 getBottomInventory().setItem(convertSlot(slot),item); 117 } 118 } else { 119 getPlayer().getWorld().dropItemNaturally(getPlayer().getLocation(), item); 120 } 121 } 122 123 /** 124 * Gets one item in this inventory view by its raw slot ID. 125 * 126 * @param slot The ID as returned by InventoryClickEvent.getRawSlot() 127 * @return The item currently in the slot. 128 */ 129 public ItemStack getItem(int slot) { 130 if (slot == OUTSIDE) { 131 return null; 132 } 133 if (slot < getTopInventory().getSize()) { 134 return getTopInventory().getItem(convertSlot(slot)); 135 } else { 136 return getBottomInventory().getItem(convertSlot(slot)); 137 } 138 } 139 140 /** 141 * Sets the item on the cursor of one of the viewing players. 142 * 143 * @param item The item to put on the cursor, or null to remove the item 144 * on their cursor. 145 */ 146 public final void setCursor(ItemStack item) { 147 getPlayer().setItemOnCursor(item); 148 } 149 150 /** 151 * Get the item on the cursor of one of the viewing players. 152 * 153 * @return The item on the player's cursor, or null if they aren't holding 154 * one. 155 */ 156 public final ItemStack getCursor() { 157 return getPlayer().getItemOnCursor(); 158 } 159 160 /** 161 * Converts a raw slot ID into its local slot ID into whichever of the two 162 * inventories the slot points to. 163 * <p> 164 * If the raw slot refers to the upper inventory, it will be returned 165 * unchanged and thus be suitable for getTopInventory().getItem(); if it 166 * refers to the lower inventory, the output will differ from the input 167 * and be suitable for getBottomInventory().getItem(). 168 * 169 * @param rawSlot The raw slot ID. 170 * @return The converted slot ID. 171 */ 172 public final int convertSlot(int rawSlot) { 173 int numInTop = getTopInventory().getSize(); 174 if (rawSlot < numInTop) { 175 return rawSlot; 176 } 177 int slot = rawSlot - numInTop; 178 if (getPlayer().getGameMode() == GameMode.CREATIVE && getType() == InventoryType.PLAYER) { 179 return slot; 180 } 181 if (getType() == InventoryType.CRAFTING) { 182 if(slot < 4) return 39 - slot; 183 else slot -= 4; 184 } 185 if (slot >= 27) slot -= 27; 186 else slot += 9; 187 return slot; 188 } 189 190 /** 191 * Closes the inventory view. 192 */ 193 public final void close() { 194 getPlayer().closeInventory(); 195 } 196 197 /** 198 * Check the total number of slots in this view, combining the upper and 199 * lower inventories. 200 * <p> 201 * Note though that it's possible for this to be greater than the sum of 202 * the two inventories if for example some slots are not being used. 203 * 204 * @return The total size 205 */ 206 public final int countSlots() { 207 return getTopInventory().getSize() + getBottomInventory().getSize(); 208 } 209 210 /** 211 * Sets an extra property of this inventory if supported by that 212 * inventory, for example the state of a progress bar. 213 * 214 * @param prop the window property to update 215 * @param value the new value for the window property 216 * @return true if the property was updated successfully, false if the 217 * property is not supported by that inventory 218 */ 219 public final boolean setProperty(Property prop, int value) { 220 return getPlayer().setWindowProperty(prop, value); 221 } 222 223 /** 224 * Get the title of this inventory window. 225 * 226 * @return The title. 227 */ 228 public final String getTitle() { 229 return getTopInventory().getTitle(); 230 } 231 }