Guest User

Untitled

a guest
Oct 23rd, 2017
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.44 KB | None | 0 0
  1. package org.hyperion.rs2.model.container;
  2.  
  3. import static java.lang.System.arraycopy;
  4. import static java.util.Collections.unmodifiableCollection;
  5. import static org.hyperion.rs2.model.ItemDefinition.getItemDefinition;
  6.  
  7. import java.util.Collection;
  8. import java.util.LinkedList;
  9. import java.util.List;
  10.  
  11. import org.hyperion.rs2.model.Item;
  12.  
  13. /**
  14.  * A container holds a group of items.
  15.  *
  16.  * @author Graham
  17.  * @author optimizations by Mike
  18.  *
  19.  */
  20. public final class Container {
  21.  
  22.     // Placed the max stack constant here, since it is located at other classes through out many different sources.
  23.     private static final int ITEM_STACK_CAPACITY = Integer.MAX_VALUE;
  24.  
  25.     /**
  26.      * The type of container.
  27.      *
  28.      * @author Graham
  29.      *
  30.      */
  31.     public enum Type {
  32.         /**
  33.          * A standard container such as inventory.
  34.          */
  35.         STANDARD,
  36.         /**
  37.          * A container which always stacks, e.g. the bank, regardless of the
  38.          * item.
  39.          */
  40.         ALWAYS_STACK,
  41.     }
  42.  
  43.     /**
  44.      * The capacity of this container.
  45.      */
  46.     private final int capacity;
  47.  
  48.     /**
  49.      * The items in this container.
  50.      */
  51.     private Item[] items;
  52.  
  53.     /**
  54.      * A list of listeners.
  55.      */
  56.     private final List<ContainerListener> listeners = new LinkedList<ContainerListener>();
  57.  
  58.     /**
  59.      * The container type.
  60.      */
  61.     private final Type type;
  62.  
  63.     /**
  64.      * Firing events flag.
  65.      */
  66.     private boolean firingEvents = true;
  67.  
  68.     /**
  69.      * Creates the container with the specified capacity.
  70.      *
  71.      * @param type The type of this container.
  72.      * @param capacity The capacity of this container.
  73.      */
  74.     public Container(Type type, int capacity) {
  75.         this.type = type;
  76.         this.capacity = capacity;
  77.         this.items = new Item[capacity];
  78.     }
  79.  
  80.     /**
  81.      * Sets the firing events flag.
  82.      *
  83.      * @param firingEvents The flag.
  84.      */
  85.     public void setFiringEvents(boolean firingEvents) {
  86.         this.firingEvents = firingEvents;
  87.     }
  88.  
  89.     /**
  90.      * Checks the firing events flag.
  91.      *
  92.      * @return <code>true</code> if events are fired, <code>false</code> if not.
  93.      */
  94.     public boolean isFiringEvents() {
  95.         return firingEvents;
  96.     }
  97.  
  98.     /**
  99.      * Gets the listeners of this container.
  100.      *
  101.      * @return The listeners of this container.
  102.      */
  103.     public Collection<ContainerListener> getListeners() {
  104.         return unmodifiableCollection(listeners);
  105.     }
  106.  
  107.     /**
  108.      * Adds a listener.
  109.      *
  110.      * @param listener The listener to add.
  111.      */
  112.     public void addListener(ContainerListener listener) {
  113.         listeners.add(listener);
  114.         listener.itemsChanged(this);
  115.     }
  116.  
  117.     /**
  118.      * Removes a listener.
  119.      *
  120.      * @param listener The listener to remove.
  121.      */
  122.     public void removeListener(ContainerListener listener) {
  123.         listeners.remove(listener);
  124.     }
  125.  
  126.     /**
  127.      * Removes all listeners.
  128.      */
  129.     public void removeAllListeners() {
  130.         listeners.clear();
  131.     }
  132.  
  133.     /**
  134.      * Shifts all items to the top left of the container leaving no gaps.
  135.      */
  136.     public void shift() {
  137.         final Item[] old = items;
  138.         items = new Item[capacity];
  139.         int newIndex = 0;
  140.         for (int i = 0; i < capacity; i++) {
  141.             if (old[i] != null) {
  142.                 items[newIndex] = old[i];
  143.                 newIndex++;
  144.             }
  145.         }
  146.         if (firingEvents) {
  147.             fireItemsChanged();
  148.         }
  149.     }
  150.  
  151.     /**
  152.      * Gets the next free slot.
  153.      *
  154.      * @return The slot, or {@code -1} if there are no available slots.
  155.      */
  156.     public int freeSlot() {
  157.         for (int i = 0; i < capacity; i++) {
  158.             if (items[i] == null) {
  159.                 return i;
  160.             }
  161.         }
  162.         return -1;
  163.     }
  164.  
  165.     /**
  166.      * Attempts to add an item into the next free slot.
  167.      *
  168.      * @param item The item.
  169.      * @return <code>true</code> if the item was added, <code>false</code> if
  170.      *         not.
  171.      */
  172.     public boolean add(Item item) {
  173.         final int id = item.getId();
  174.         if (item.getDefinition().isStackable() || type.equals(ContainerType.ALWAYS_STACK)) {
  175.             for (int i = 0; i < capacity; i++) {
  176.                 if (items[i] != null && items[i].getId() == id) {
  177.                     final int totalCount = item.getCount() + items[i].getCount();
  178.                     if (totalCount > ITEM_STACK_CAPACITY || totalCount < 1) {
  179.                         return false;
  180.                     }
  181.                     set(i, new Item(id, totalCount));
  182.                     return true;
  183.                 }
  184.             }
  185.             final int slot = freeSlot();
  186.             if (slot == -1) {
  187.                 return false;
  188.             } else {
  189.                 set(slot, item);
  190.                 return true;
  191.             }
  192.         } else {
  193.             final int count = item.getCount();
  194.             final int[] slots = getFreeSlots();
  195.             if (slots.length >= count) {
  196.                 final boolean b = firingEvents;
  197.                 firingEvents = false;
  198.                 try {
  199.                     for (int i = 0; i < count; i++) {
  200.                         set(slots[i], new Item(id));
  201.                     }
  202.                     if (b) {
  203.                         fireItemsChanged();
  204.                     }
  205.                     return true;
  206.                 } finally {
  207.                     firingEvents = b;
  208.                 }
  209.             } else {
  210.                 return false;
  211.             }
  212.         }
  213.     }
  214.  
  215.     /**
  216.      * Gets the number of free slots.
  217.      *
  218.      * @return The number of free slots.
  219.      */
  220.     public int freeSlots() {
  221.         return capacity - size();
  222.     }
  223.  
  224.     /**
  225.      * Gets an item.
  226.      *
  227.      * @param index The position in the container.
  228.      * @return The item.
  229.      */
  230.     public Item get(int index) {
  231.         return items[index];
  232.     }
  233.  
  234.     /**
  235.      * Gets an item by ID.
  236.      *
  237.      * @param id The ID.
  238.      * @return The item, or <code>null</code> if it could not be found.
  239.      */
  240.     public Item getById(int id) {
  241.         for (Item item : items) {
  242.             if (item != null && item.getId() == id) {
  243.                 return item;
  244.             }
  245.         }
  246.         return null;
  247.     }
  248.  
  249.     /**
  250.      * Gets a slot by ID.
  251.      *
  252.      * @param id The ID.
  253.      * @return The slot, or {@code -1} if it could not be found.
  254.      */
  255.     public int getSlotById(int id) {
  256.         for (int i = 0; i < capacity; i++) {
  257.             if (items[i] != null && items[i].getId() == id) {
  258.                 return i;
  259.             }
  260.         }
  261.         return -1;
  262.     }
  263.  
  264.     /**
  265.      * Sets an item.
  266.      *
  267.      * @param index The position in the container.
  268.      * @param item The item.
  269.      */
  270.     public void set(int index, Item item) {
  271.         items[index] = item;
  272.         if (firingEvents) {
  273.             fireItemChanged(index);
  274.         }
  275.     }
  276.  
  277.     /**
  278.      * Gets the capacity of this container.
  279.      *
  280.      * @return The capacity of this container.
  281.      */
  282.     public int capacity() {
  283.         return capacity;
  284.     }
  285.  
  286.     /**
  287.      * Gets the size of this container.
  288.      *
  289.      * @return The size of this container.
  290.      */
  291.     public int size() {
  292.         int size = 0;
  293.         for (Item item : items) {
  294.             if (item != null) {
  295.                 size++;
  296.             }
  297.         }
  298.         return size;
  299.     }
  300.  
  301.     /**
  302.      * Checks if this container is empty.
  303.      *
  304.      * @return {@code true} if so, {@code false} otherwise.
  305.      */
  306.     public boolean isEmpty() {
  307.         for (Item item : items) {
  308.             if (item != null) {
  309.                 return false;
  310.             }
  311.         }
  312.         return true;
  313.     }
  314.  
  315.     /**
  316.      * Clears this container.
  317.      */
  318.     public void clear() {
  319.         items = new Item[items.length];
  320.         if (firingEvents) {
  321.             fireItemsChanged();
  322.         }
  323.     }
  324.  
  325.     /**
  326.      * Returns an array representing this container.
  327.      *
  328.      * @return The array.
  329.      */
  330.     public Item[] toArray() {
  331.         return items;
  332.     }
  333.  
  334.     /**
  335.      * Checks if a slot is used.
  336.      *
  337.      * @param slot The slot.
  338.      * @return <code>true</code> if an item is present, <code>false</code>
  339.      *         otherwise.
  340.      */
  341.     public boolean isSlotUsed(int slot) {
  342.         return items[slot] != null;
  343.     }
  344.  
  345.     /**
  346.      * Checks if a slot is free.
  347.      *
  348.      * @param slot The slot.
  349.      * @return <code>true</code> if an item is not present, <code>false</code>
  350.      *         otherwise.
  351.      */
  352.     public boolean isSlotFree(int slot) {
  353.         return items[slot] == null;
  354.     }
  355.  
  356.     /**
  357.      * Removes an item.
  358.      *
  359.      * @param item The item to remove.
  360.      * @return The number of items removed.
  361.      */
  362.     public int remove(Item item) {
  363.         return remove(-1, item);
  364.     }
  365.  
  366.     /**
  367.      * Removes an item.
  368.      *
  369.      * @param preferredSlot The preferred slot to remove from.
  370.      * @param item The item to remove.
  371.      * @return The number of items removed.
  372.      */
  373.     public int remove(int preferredSlot, Item item) {
  374.         int removed = 0;
  375.         if (item.getDefinition().isStackable() || type.equals(ContainerType.ALWAYS_STACK)) {
  376.             final int slot = getSlotById(item.getId());
  377.             final Item stack = get(slot);
  378.             if (stack.getCount() > item.getCount()) {
  379.                 removed = item.getCount();
  380.                 set(slot, new Item(stack.getId(), stack.getCount() - item.getCount()));
  381.             } else {
  382.                 removed = stack.getCount();
  383.                 set(slot, null);
  384.             }
  385.         } else {
  386.             for (int i = 0; i < item.getCount(); i++) {
  387.                 int slot = getSlotById(item.getId());
  388.                 if (i == 0 && preferredSlot != -1) {
  389.                     final Item inSlot = get(preferredSlot);
  390.                     if (inSlot.getId() == item.getId()) {
  391.                         slot = preferredSlot;
  392.                     }
  393.                 }
  394.                 if (slot != -1) {
  395.                     removed++;
  396.                     set(slot, null);
  397.                 } else {
  398.                     break;
  399.                 }
  400.             }
  401.         }
  402.         return removed;
  403.     }
  404.  
  405.     /**
  406.      * Transfers an {@link Item} from one {@link Container} to another.
  407.      *
  408.      * @param from The container to transfer from.
  409.      * @param to The container to transfer to.
  410.      * @param fromSlot The slot in the original container.
  411.      * @param id The item id.
  412.      * @return A flag indicating if the transfer was successful.
  413.      */
  414.     public static boolean transfer(Container from, Container to, int fromSlot, int id) {
  415.         final Item fromItem = from.get(fromSlot);
  416.         if (fromItem == null || fromItem.getId() != id) {
  417.             return false;
  418.         }
  419.         if (to.add(fromItem)) {
  420.             from.set(fromSlot, null);
  421.             return true;
  422.         } else {
  423.             return false;
  424.         }
  425.     }
  426.  
  427.     /**
  428.      * Returns a copy of the specified {@link Container}.
  429.      *
  430.      * @param c The container to copy.
  431.      * @return The newly created container.
  432.      */
  433.     public static Container copy(Container c) {
  434.         final int capacity = c.capacity;
  435.         final Container newC = new Container(c.type, capacity);
  436.         arraycopy(c.items, 0, newC.items, 0, capacity);
  437.         return newC;
  438.     }
  439.  
  440.     /**
  441.      * Swaps two items.
  442.      *
  443.      * @param fromSlot From slot.
  444.      * @param toSlot To slot.
  445.      */
  446.     public void swap(int fromSlot, int toSlot) {
  447.         final Item temp = get(fromSlot);
  448.         final boolean b = firingEvents;
  449.         firingEvents = false;
  450.         try {
  451.             set(fromSlot, get(toSlot));
  452.             set(toSlot, temp);
  453.             if (b) {
  454.                 fireItemsChanged(fromSlot, toSlot);
  455.             }
  456.         } finally {
  457.             firingEvents = b;
  458.         }
  459.     }
  460.  
  461.     /**
  462.      * Gets the total amount of an item, including the items in stacks.
  463.      *
  464.      * @param id The id.
  465.      * @return The amount.
  466.      */
  467.     public int getCount(int id) {
  468.         int total = 0;
  469.         for (Item item : items) {
  470.             if (item != null && item.getId() == id) {
  471.                 total += item.getCount();
  472.             }
  473.         }
  474.         return total;
  475.     }
  476.  
  477.     /**
  478.      * Inserts an item.
  479.      *
  480.      * @param fromSlot The old slot.
  481.      * @param toSlot The new slot.
  482.      */
  483.     public void insert(int fromSlot, int toSlot) {
  484.         // we reset the item in the from slot
  485.         final Item from = items[fromSlot];
  486.         if (from == null) {
  487.             return;
  488.         }
  489.         items[fromSlot] = null;
  490.         // find which direction to shift in
  491.         if (fromSlot > toSlot) {
  492.             int shiftFrom = toSlot;
  493.             int shiftTo = fromSlot;
  494.             for (int i = (toSlot + 1); i < fromSlot; i++) {
  495.                 if (items[i] == null) {
  496.                     shiftTo = i;
  497.                     break;
  498.                 }
  499.             }
  500.             final Item[] slice = new Item[shiftTo - shiftFrom];
  501.             arraycopy(items, shiftFrom, slice, 0, slice.length);
  502.             arraycopy(slice, 0, items, shiftFrom + 1, slice.length);
  503.         } else {
  504.             int sliceStart = fromSlot + 1;
  505.             final int sliceEnd = toSlot;
  506.             for (int i = (sliceEnd - 1); i >= sliceStart; i--) {
  507.                 if (items[i] == null) {
  508.                     sliceStart = i;
  509.                     break;
  510.                 }
  511.             }
  512.             final Item[] slice = new Item[sliceEnd - sliceStart + 1];
  513.             arraycopy(items, sliceStart, slice, 0, slice.length);
  514.             arraycopy(slice, 0, items, sliceStart - 1, slice.length);
  515.         }
  516.         // now fill in the target slot
  517.         items[toSlot] = from;
  518.         if (firingEvents) {
  519.             fireItemsChanged();
  520.         }
  521.     }
  522.  
  523.     /**
  524.      * Fires an item changed event.
  525.      *
  526.      * @param slot The slot that changed.
  527.      */
  528.     public void fireItemChanged(int slot) {
  529.         for (ContainerListener listener : listeners) {
  530.             listener.itemChanged(this, slot);
  531.         }
  532.     }
  533.  
  534.     /**
  535.      * Fires an items changed event.
  536.      */
  537.     public void fireItemsChanged() {
  538.         for (ContainerListener listener : listeners) {
  539.             listener.itemsChanged(this);
  540.         }
  541.     }
  542.  
  543.     /**
  544.      * Fires an items changed event.
  545.      *
  546.      * @param slots The slots that changed.
  547.      */
  548.     public void fireItemsChanged(int... slots) {
  549.         for (ContainerListener listener : listeners) {
  550.             listener.itemsChanged(this, slots);
  551.         }
  552.     }
  553.  
  554.     /**
  555.      * Checks if the container contains the specified item.
  556.      *
  557.      * @param id The item id.
  558.      * @return <code>true</code> if so, <code>false</code> if not.
  559.      */
  560.     public boolean contains(int id) {
  561.         return getSlotById(id) != -1;
  562.     }
  563.  
  564.     /**
  565.      * Checks if this {@link Container} has enough room for the specified
  566.      * {@link Item}.
  567.      *
  568.      * @param item The item.
  569.      * @return {@code true} if so, {@code false} otherwise.
  570.      */
  571.     public boolean hasRoomFor(Item item) {
  572.         return freeSpace(item.getId()) >= item.getCount();
  573.     }
  574.  
  575. }
Add Comment
Please, Sign In to add comment