mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-05 16:49:04 +00:00
Inventory improvements: (expand commit for details).
- Fixed a bug with Inventory#add(Item) not handling integer overflow properly. - Fixed a bug with Inventory#add(Item) returning an Item object with an amount of 0 instead of null. - Inventory#add(Item) now returns an Optional<Item> object and cleaned up portions of the method. - code clean-up to Inventory#remove(int, int). - Inventory#remove(int, int) now supports stopping and refiring of listeners while the inventory is being updated (prevents flickering and unnecessary updating of the inventory for batch updates).
This commit is contained in:
@@ -3,6 +3,7 @@ package org.apollo.game.model.inv;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apollo.game.model.Item;
|
import org.apollo.game.model.Item;
|
||||||
import org.apollo.game.model.def.ItemDefinition;
|
import org.apollo.game.model.def.ItemDefinition;
|
||||||
@@ -116,84 +117,92 @@ public final class Inventory {
|
|||||||
* @return The amount that remains.
|
* @return The amount that remains.
|
||||||
*/
|
*/
|
||||||
public int add(int id, int amount) {
|
public int add(int id, int amount) {
|
||||||
Item item = add(new Item(id, amount));
|
Optional<Item> optionalItem = add(new Item(id, amount));
|
||||||
return (item != null) ? item.getAmount() : 0;
|
return optionalItem.map(item -> optionalItem.isPresent() ? item.getAmount() : 0).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an item to this inventory. This will attempt to add as much of the item that is possible. If the item
|
* Attempts to add as much of the specified {@code item} to this inventory
|
||||||
* remains, it will be returned (in the case of stackable items, any quantity that remains in the stack is
|
* as possible. If any of the item remains, an {@link Item item with the
|
||||||
* returned). If nothing remains, the method will return {@code null}. If something remains, the listener will also
|
* remainder} will be returned (in the case of stack-able items, any
|
||||||
* be notified which could be used, for example, to send a message to the player.
|
* quantity that remains in the stack is returned). If nothing remains, the
|
||||||
*
|
* method will return {@link Optional#empty an empty Optional}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* If anything remains at all, the listener will be notified which could be
|
||||||
|
* used for notifying a player that their inventory is full, for example.
|
||||||
|
*
|
||||||
* @param item The item to add to this inventory.
|
* @param item The item to add to this inventory.
|
||||||
* @return The item that remains if there is not enough room in the inventory. If nothing remains, {@code null}.
|
* @return The item that may remain, if nothing remains,
|
||||||
|
* {@link Optional#empty an empty Optional} is returned.
|
||||||
*/
|
*/
|
||||||
public Item add(Item item) {
|
public Optional<Item> add(Item item) {
|
||||||
int id = item.getId();
|
int id = item.getId();
|
||||||
boolean stackable = isStackable(item.getDefinition());
|
boolean stackable = isStackable(item.getDefinition());
|
||||||
|
|
||||||
if (stackable) {
|
if (stackable) {
|
||||||
for (int slot = 0; slot < capacity; slot++) {
|
int slot = slotOf(id);
|
||||||
|
|
||||||
|
if (slot != -1) {
|
||||||
Item other = items[slot];
|
Item other = items[slot];
|
||||||
|
|
||||||
if (other != null && other.getId() == id) {
|
long total = (long) item.getAmount() + other.getAmount();
|
||||||
long total = item.getAmount() + other.getAmount();
|
int amount, remaining;
|
||||||
int amount, remaining;
|
|
||||||
|
|
||||||
if (total > Integer.MAX_VALUE) {
|
if (total > Integer.MAX_VALUE) {
|
||||||
amount = (int) (total - Integer.MAX_VALUE);
|
amount = (int) (total - Integer.MAX_VALUE);
|
||||||
remaining = (int) (total - amount);
|
remaining = (int) (total - amount);
|
||||||
notifyCapacityExceeded();
|
notifyCapacityExceeded();
|
||||||
} else {
|
} else {
|
||||||
amount = (int) total;
|
amount = (int) total;
|
||||||
remaining = 0;
|
remaining = 0;
|
||||||
}
|
|
||||||
|
|
||||||
set(slot, new Item(id, amount));
|
|
||||||
return remaining > 0 ? new Item(id, remaining) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set(slot, new Item(id, amount));
|
||||||
|
return remaining > 0 ? Optional.of(new Item(id, remaining)) : Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int slot = 0; slot < capacity; slot++) {
|
for (slot = 0; slot < capacity; slot++) {
|
||||||
Item other = items[slot];
|
if (items[slot] == null) {
|
||||||
if (other == null) {
|
|
||||||
set(slot, item);
|
set(slot, item);
|
||||||
return null;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyCapacityExceeded();
|
notifyCapacityExceeded();
|
||||||
return item;
|
return Optional.of(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
int remaining = item.getAmount();
|
int remaining = item.getAmount();
|
||||||
|
|
||||||
|
if (remaining == 0) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
stopFiringEvents();
|
stopFiringEvents();
|
||||||
try {
|
try {
|
||||||
Item single = new Item(item.getId(), 1);
|
Item single = new Item(item.getId(), 1);
|
||||||
|
|
||||||
for (int slot = 0; slot < capacity; slot++) {
|
for (int slot = 0; slot < capacity; slot++) {
|
||||||
if (items[slot] == null) {
|
if (items[slot] == null) {
|
||||||
remaining--;
|
|
||||||
set(slot, single); // share the instances
|
set(slot, single); // share the instances
|
||||||
|
|
||||||
if (remaining <= 0) {
|
if (--remaining <= 0) {
|
||||||
break;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
startFiringEvents();
|
startFiringEvents();
|
||||||
|
|
||||||
|
if (remaining != item.getAmount()) {
|
||||||
|
notifyItemsUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remaining != item.getAmount()) {
|
notifyCapacityExceeded();
|
||||||
notifyItemsUpdated();
|
|
||||||
}
|
|
||||||
if (remaining > 0) {
|
|
||||||
notifyCapacityExceeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Item(item.getId(), remaining);
|
return Optional.of(new Item(item.getId(), remaining));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -442,19 +451,19 @@ public final class Inventory {
|
|||||||
* @return The amount that was removed.
|
* @return The amount that was removed.
|
||||||
*/
|
*/
|
||||||
public int remove(int id, int amount) {
|
public int remove(int id, int amount) {
|
||||||
ItemDefinition definition = ItemDefinition.lookup(id);
|
ItemDefinition def = ItemDefinition.lookup(id);
|
||||||
boolean stackable = isStackable(definition);
|
boolean stackable = isStackable(def);
|
||||||
|
|
||||||
if (stackable) {
|
if (stackable) {
|
||||||
for (int slot = 0; slot < capacity; slot++) {
|
int slot = slotOf(id);
|
||||||
|
|
||||||
|
if (slot != -1) {
|
||||||
Item item = items[slot];
|
Item item = items[slot];
|
||||||
|
|
||||||
if (item != null && item.getId() == id) {
|
if (amount >= item.getAmount()) {
|
||||||
if (amount >= item.getAmount()) {
|
set(slot, null);
|
||||||
set(slot, null);
|
return item.getAmount();
|
||||||
return item.getAmount();
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
set(slot, new Item(item.getId(), item.getAmount() - amount));
|
set(slot, new Item(item.getId(), item.getAmount() - amount));
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
@@ -464,16 +473,26 @@ public final class Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
for (int slot = 0; slot < capacity; slot++) {
|
|
||||||
Item item = items[slot];
|
|
||||||
|
|
||||||
if (item != null && item.getId() == id) {
|
stopFiringEvents();
|
||||||
set(slot, null);
|
|
||||||
removed++;
|
try {
|
||||||
|
for (int slot = 0; slot < capacity; slot++) {
|
||||||
|
Item item = items[slot];
|
||||||
|
if (item != null && item.getId() == id) {
|
||||||
|
set(slot, null);
|
||||||
|
|
||||||
|
if (++removed >= amount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removed >= amount) {
|
} finally {
|
||||||
break;
|
startFiringEvents();
|
||||||
|
|
||||||
|
if (removed > 0) {
|
||||||
|
notifyItemsUpdated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user