Skip to content

Instantly share code, notes, and snippets.

@Tyluur
Created January 4, 2021 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tyluur/074ab047299d6e138f1b6824777304ad to your computer and use it in GitHub Desktop.
Save Tyluur/074ab047299d6e138f1b6824777304ad to your computer and use it in GitHub Desktop.
package org.scapesoft.game.item;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.scapesoft.Constants;
import org.scapesoft.cache.loaders.ItemDefinitions;
import org.scapesoft.game.player.Player;
import org.scapesoft.utilities.game.item.ItemNames;
/**
* This class handles the decantation of potions in the most efficient way
* possible.
*
* @author Tyluur <itstyluur@gmail.com>
* @Since August 3rd, 2013
*/
public final class Decanting {
/**
* Handles the decantation of all potions in the player's inventory, to the
* specified dosage
*
* @Param player
* The player decanting
* @Param maxDosage
* The dosage to decant potions to
*/
public static void decantInventory(Player player, int maxDosage) {
Map<String, List<Item>> map = getDecantablePotions(player);
Iterator<Entry<String, List<Item>>> it$ = map.entrySet().iterator();
List<Item> newItems = new ArrayList<>();
List<Item> items = null;
while (it$.hasNext()) {
Entry<String, List<Item>> entry = it$.next();
String baseName = entry.getKey();
items = entry.getValue();
int totalDoses = 0;
for (Item item : items) {
totalDoses += getPotionDoses(item.getName().split(" "));
}
List<Integer> doses = new ArrayList<Integer>();
int tempDose = totalDoses;
for (int i = tempDose; i > 0; i--) {
if (i % maxDosage == 0) {
tempDose -= 4;
doses.add(maxDosage);
} else if (i == 1 && tempDose > 0) {
doses.add(tempDose);
}
}
for (Integer dose : doses) {
String newName = baseName + " (" + dose + ")";
int newId = ItemNames.getId(newName);
ItemDefinitions defs = ItemDefinitions.getItemDefinitions(newId);
if (defs.isNoted() && defs.getCertId() != -1) {
newId = defs.getCertId();
}
newItems.add(new Item(newId, 1));
}
}
if (items == null) {
return;
}
for (Item item : items) {
if (!player.getInventory().containsItem(item.getId(), item.getAmount())) {
return;
}
}
int nSize = newItems.size();
int size = items.size();
if (nSize < size) {
int difference = size - nSize;
for (int i = 0; i < difference; i++) {
newItems.add(new Item(229));
}
}
for (Item item : items) {
player.getInventory().deleteItem(item);
}
for (Item item : newItems) {
player.getInventory().addItem(item);
}
}
/**
* Creates a map of all decantable potions and stores the base name of the
* potions as the key (e.g super strength). The list of all potions that can
* be decanted is the value of the map.
*
* @Param player
* The player
* @Return
*/
public static Map<String, List<Item>> getDecantablePotions(Player player) {
Map<String, List<Item>> map = new HashMap<String, List<Item>>();
for (Item item : player.getInventory().getItems().toArray()) {
if (item == null || item.getDefinitions().isNoted()) {
continue;
}
String name = item.getName();
if (isPotion(name)) {
String baseName = getBaseName(name);
if (!map.containsKey(baseName)) {
List<Item> items = new ArrayList<Item>();
items.add(item);
map.put(baseName, items);
} else {
List<Item> items = map.get(baseName);
items.add(item);
}
}
}
return map;
}
/**
* Gets the cost of decanting all the potions in a player's inventory
*
* @Param player
* The player
* @Return
*/
public static int getPotionCost(Player player) {
Map<String, List<Item>> map = Decanting.getDecantablePotions(player);
Iterator<Entry<String, List<Item>>> it$ = map.entrySet().iterator();
int count = 0;
while (it$.hasNext()) {
Entry<String, List<Item>> entry = it$.next();
List<Item> items = entry.getValue();
int totalDoses = 0;
for (Item item : items) {
totalDoses += getPotionDoses(item.getName().split(" "));
}
count += (totalDoses / 4);
}
count *= COST_PER_POTION;
return count;
}
/**
* Figures out if you can use the two potions on each other
*
* @Param first
* The name of the first potion used
* @Param second
* The name of the second potion used
* @Return
*/
private static boolean isPotionSimilar(String first, String second) {
String firstBase = getBaseName(first);
String secondBase = getBaseName(second);
if (!firstBase.equalsIgnoreCase(secondBase)) {
return false;
}
return true;
}
/**
* Gets the doses of the potion
*
* @Param name
* The name of the potion split by spaces
* @Return
*/
private static int getPotionDoses(String[] name) {
int doses = 0;
for (String split : name) {
for (Character c : split.toCharArray()) {
if (Character.isDigit(c)) {
doses = Character.getNumericValue(c);
break;
}
}
}
return doses;
}
/**
* Gets the base name of the potion
*
* @Param name
* The name of the potion
* @Return
*/
private static String getBaseName(String name) {
String newName = "";
for (Character c : name.toCharArray()) {
if (Character.isLetter(c) || Character.isWhitespace(c)) {
newName += c;
}
}
return newName.trim();
}
/**
* Figures out if the item you are using is a potion or not.
*
* @Param name
* The name of the item
* @Return
*/
private static boolean isPotion(String name) {
if (name.toLowerCase().contains("amulet") || name.toLowerCase().contains("games") || name.toLowerCase().contains("flask")) {
return false;
}
String altString = "";
for (Character c : name.toCharArray()) {
if (Character.isLetter(c) || Character.isWhitespace(c)) {
continue;
}
altString += c;
}
Pattern pattern = Pattern.compile("\\([0-9]\\)");
Matcher m = pattern.matcher(altString);
if (m.find()) {
return true;
}
return false;
}
/**
* Handles the decantation process of two like potions
*
* @Param player
* The player who is decanting
* @Param fromSlot
* The slot the first item is from
* @Param toSlot
* The slot the second item is from
* @Return
*/
public static boolean handleDecanting(Player player, int fromSlot, int toSlot) {
try {
Item used = player.getInventory().getItem(toSlot);
Item with = player.getInventory().getItem(fromSlot);
String usedBase = used.getName();
String withBase = with.getName();
if (!isPotion(usedBase) || !isPotion(withBase) || !isPotionSimilar(usedBase, withBase)) {
return false;
}
String baseName = getBaseName(usedBase);
String[] usedSplit = usedBase.split(" ");
String[] withSplit = withBase.split(" ");
int usedDoses = getPotionDoses(usedSplit);
int withDoses = getPotionDoses(withSplit);
int totalDoses = usedDoses + withDoses;
int[] newDoses = new int[2];
if (totalDoses > 4) {
newDoses[0] = 4;
newDoses[1] = totalDoses - 4;
} else {
newDoses[0] = totalDoses;
}
if (totalDoses == 8) {
return true;
}
player.getInventory().deleteItem(with);
player.getInventory().deleteItem(used);
for (int dose : newDoses) {
if (dose == 0) {
player.getInventory().addItem(new Item(229));
continue;
}
String newName = baseName + " (" + dose + ")";
int newId = ItemNames.getId(newName);
ItemDefinitions defs = ItemDefinitions.getItemDefinitions(newId);
if (defs.isNoted() && defs.getCertId() != -1) {
newId = defs.getCertId();
}
Item item = new Item(newId, 1);
player.getInventory().addItem(item);
}
if (Constants.DEBUG) {
StringBuilder bldr = new StringBuilder();
for (int dose : newDoses) {
bldr.append(dose + ", ");
}
System.out.println("Dosage info[baseName=" + baseName + ", total=" + totalDoses + ", usedDoses=" + usedDoses + ", withDoses=" + withDoses + ", newDoses=" + bldr.toString().trim() + "]");
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* All inventory items will be transformed into flasks if they're (3).
*
* @Param player
* The player
*/
public static void decantToFlask(Player player) {
Map<String, Integer> map = new HashMap<String, Integer>();
Object lock = new Object();
for (Item item : player.getInventory().getItems().toArray()) {
if (item == null || item.getDefinitions().isNoted() || !isPotion(item.getName())) {
continue;
}
synchronized (lock) {
String name = item.getName();
String base = Decanting.getBaseName(name);
int doses = getPotionDoses(name.split(" "));
if (map.containsKey(base)) {
int amt = map.get(base);
map.remove(base);
map.put(base, amt + doses);
} else {
map.put(base, doses);
}
}
}
Iterator<Entry<String, Integer>> it = map.entrySet().iterator();
synchronized (lock) {
while (it.hasNext()) {
Entry<String, Integer> entry = it.next();
/** The name of the potion */
String name = entry.getKey();
/** The amount of total doses of the potion */
int amount = entry.getValue();
if (amount == 0 || amount % 6 != 0) {
player.sendMessage("You only had " + amount + " total doses of " + name + ", so you could not create a flask of this.");
continue;
}
/** The amount of flasks to create */
int amountToCreate = amount / 6;
/** The name of the flask */
String flaskName = name.replaceAll("potion", "").trim() + " flask (6)";
/** The id of the flask */
int id = ItemNames.getId(flaskName);
ItemDefinitions definitions = ItemDefinitions.getItemDefinitions(id);
if (definitions.isNoted() && definitions.getCertId() != -1) {
id = definitions.getCertId();
}
for (Item item : player.getInventory().getItems().toArray()) {
if (item == null) {
continue;
}
if (item.getName().contains(name)) {
player.getInventory().deleteItem(item);
}
}
player.getInventory().addItem(id, amountToCreate);
}
}
}
/**
* Empties a potion if the item is a potion.
*
* @Param player
* The player
* @Param item
* The item
* @Return
*/
public static boolean emptyPotion(Player player, Item item) {
String name = item.getName();
Pattern pattern = Pattern.compile("\\([0-9]\\)");
Matcher m = pattern.matcher(name);
if (item.getName().toLowerCase().contains("amulet") || item.getName().toLowerCase().contains("games") || name.toLowerCase().contains("ring")) {
return false;
}
if (m.find() || item.getId() == 227) {
player.getInventory().deleteItem(item);
player.getInventory().addItem(229, 1);
player.sendMessage("You empty the " + item.getName().toLowerCase() + ".");
}
return false;
}
/**
* The cost to decant one potion
*/
public static final int COST_PER_POTION = 1000;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment