[Elvarg] 100% Items Kept On Death
When looking through to find possible ways to fix Elvarg's IKOD I realized that information was sparse. But, I was able to create the algorithm to have the correct items show up in the interface with correct amounts. This will mainly fix the issue of having a whole stack items being kept instead of just one of the stacked item.
ItemsKeptOnDeath.java
Code:
/**
* Handles items kept on death.
* @author Swiffy
* @author Note
*/
public class ItemsKeptOnDeath {
private static final String KEPT = "kept";
private static final String LOST = "lost";
/**
* Sends the items kept on death interface for a player.
* @param player Player to send the items kept on death interface for.
*/
public static void open(Player player) {
clearInterfaceData(player); //To prevent sending multiple layers of items.
sendInterfaceData(player); //Send info on the interface.
player.getPacketSender().sendInterface(17100); //Open the interface.
}
/**
* Sorts inventory and equipment items into kept array list or lost array list
* @param player Player
* @return map containing kept and lost array list
*/
private static HashMap<String, ArrayList<Item>> sortItems(Player player) {
ArrayList<Item> items =
Arrays.stream(Misc.concat(player.getInventory().getItems(), player.getEquipment().getItems()))
.map(Item::new)
.filter(Item::isValid)
.sorted(Comparator.comparingInt(Item::getValue).reversed())
.collect(Collectors.toCollection(ArrayList::new));
int amountKept = getAmountToKeep(player);
ArrayList<Item> kept = new ArrayList<>();
for (Item item : items) {
while (kept.size() < amountKept && item.getAmount() > 0) {
kept.add(new Item(item.getId(), 1));
item.decrementAmountBy(1);
}
}
ArrayList<Item> lost = items.stream()
.filter(Item::isValid)
.collect(Collectors.groupingBy(Item::getId))
.values().stream()
.flatMap(values -> {
Item item = values.get(0);
if (item.getDefinition().isStackable()) {
int sum = values.stream().mapToInt(Item::getAmount).sum();
int id = item.getId();
return Stream.of(new Item(id, sum));
} return values.stream();
}).collect(Collectors.toCollection(ArrayList::new));
HashMap<String, ArrayList<Item>> map = new HashMap<>();
map.put(KEPT, kept);
map.put(LOST, lost);
return map;
}
/**
* Sends the items kept on death data for a player.
* @param player Player to send the items kept on death data for.
*/
public static void sendInterfaceData(Player player) {
player.getPacketSender().sendString(17107, ""+getAmountToKeep(player));
HashMap<String, ArrayList<Item>> items = sortItems(player);
player.getPacketSender().sendInterfaceItems(17108, items.get(KEPT));
player.getPacketSender().sendInterfaceItems(17109, items.get(LOST));
}
/**
* Clears the items kept on death interface for a player.
* @param player Player to clear the items kept on death interface for.
*/
public static void clearInterfaceData(Player player) {
player.getPacketSender().clearItemOnInterface(17108);
player.getPacketSender().clearItemOnInterface(17109);
}
/**
* Sets the items to keep on death for a player.
* @param player Player to set items for.
*/
public static ArrayList<Item> getItemsToKeep(Player player) {
ArrayList<Item> items = new ArrayList<>();
for(Item item : Misc.concat(player.getInventory().getItems(), player.getEquipment().getItems())) {
if(item == null || item.getId() <= 0 || item.getAmount() <= 0 || !item.getDefinition().isTradeable()) {
continue;
}
items.add(item);
}
items.sort(Comparator.comparing((Item item) -> item.getDefinition().getValue()).reversed());
System.out.println(items);
ArrayList<Item> toKeep = new ArrayList<>();
int amountToKeep = getAmountToKeep(player);
for(int i = 0; i < amountToKeep && i < items.size(); i++) {
toKeep.add(items.get(i));
}
return toKeep;
}
public static int getAmountToKeep(Player player) {
if(player.getSkullTimer() > 0) {
if(player.getSkullType() == SkullType.RED_SKULL) {
return 0;
}
}
return (player.getSkullTimer() > 0 ? 0 : 3) + (PrayerHandler.isActivated(player, PrayerHandler.PROTECT_ITEM) ? 1 : 0);
}
}
The main part about the class edit is the function sortItems it will output a Map containing the items that are kept and lost. You will have to add it the death task so it will also give the correct amount of items when a player dies. That requires a few changes but it's pretty easy. (Instead of calling itemsToKeep, call sortItems(player).get(KEPT). As is, the interface should work perfectly now.
Some warnings:
- Make sure Item overrides the clone method and it returns a new Item.
Some methods used in Item.java
Code:
/**
* Copy Constructor
* @param item
*/
public Item(Item item) {
this(item.getId(), item.getAmount());
}
public ItemDefinition getDefinition() {
return ItemDefinition.forId(id);
}
public Integer getValue() {
return this.getDefinition().getValue();
}
@Override
public Item clone() {
return new Item(id, amount);
}
This also contains the client code discussed in [Only registered and activated users can see links. Click Here To Register...]
Quote:
You only really need 2 inventory widgets instead.
Server: [Only registered and activated users can see links. Click Here To Register...] *Note
Client:
[Only registered and activated users can see links. Click Here To Register...]
Server side needs a bit of work for the stackable stuff though.
Coin stack
[Only registered and activated users can see links. Click Here To Register...]
Dragon Arrows equipped and in inventory, combine noted and un-noted items
[Only registered and activated users can see links. Click Here To Register...].