Writes a lot of code necessary for the scrapper

Adds the classes necessary for the new scrapper
Partly implements some scrapper functionality
Restructures some classes to reduce code duplication
Moves some classes to make some classes easier to find
Adds a bunch of TODOs where things have an unfinished implementation
This commit is contained in:
2023-11-14 16:04:48 +01:00
parent 1938a690c6
commit f3f3f66c38
40 changed files with 1788 additions and 594 deletions

View File

@ -1,5 +1,8 @@
package net.knarcraft.blacksmith.util;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@ -18,7 +21,7 @@ public final class ConfigHelper {
* @param value <p>The raw string list value</p>
* @return <p>The value as a string list, or null if not compatible</p>
*/
public static List<String> asStringList(Object value) {
public static @Nullable List<String> asStringList(@Nullable Object value) {
if (value == null) {
return new ArrayList<>();
}
@ -42,8 +45,10 @@ public final class ConfigHelper {
*
* @param value <p>The object value to get</p>
* @return <p>The value of the given object as a double</p>
* @throws ClassCastException <p>If a non-double is given as input</p>
* @throws NumberFormatException <p>If a non-double is given as input</p>
*/
public static double asDouble(Object value) {
public static double asDouble(@NotNull Object value) throws ClassCastException, NumberFormatException {
if (value instanceof String) {
return Double.parseDouble((String) value);
} else if (value instanceof Integer) {
@ -60,12 +65,15 @@ public final class ConfigHelper {
*
* @param value <p>The object value to get</p>
* @return <p>The value of the given object as a boolean</p>
* @throws ClassCastException <p>If the given value is not a boolean</p>
*/
public static boolean asBoolean(Object value) {
if (value instanceof String) {
public static boolean asBoolean(@NotNull Object value) throws ClassCastException {
if (value instanceof Boolean booleanValue) {
return booleanValue;
} else if (value instanceof String) {
return Boolean.parseBoolean((String) value);
} else {
return (Boolean) value;
throw new ClassCastException();
}
}
@ -76,8 +84,9 @@ public final class ConfigHelper {
*
* @param value <p>The object value to get</p>
* @return <p>The value of the given object as an integer</p>
* @throws ClassCastException <p>If the given value is not an integer</p>
*/
public static int asInt(Object value) {
public static int asInt(@NotNull Object value) throws ClassCastException {
if (value instanceof String) {
return Integer.parseInt((String) value);
} else {

View File

@ -3,6 +3,8 @@ package net.knarcraft.blacksmith.util;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A helper class for parsing input into proper object types
@ -19,7 +21,7 @@ public final class InputParsingHelper {
* @param input <p>The input to check</p>
* @return <p>True if the value is empty</p>
*/
public static boolean isEmpty(String input) {
public static boolean isEmpty(@Nullable String input) {
return input == null || input.equalsIgnoreCase("null") || input.equals("\"\"") ||
input.isBlank() || input.equals("-1");
}
@ -30,7 +32,7 @@ public final class InputParsingHelper {
* @param input <p>The string to match to a material</p>
* @return <p>The material matching the string, or null if not found</p>
*/
public static Material matchMaterial(String input) {
public static @Nullable Material matchMaterial(@NotNull String input) {
return Material.matchMaterial(input.replace("-", "_"));
}
@ -40,7 +42,7 @@ public final class InputParsingHelper {
* @param input <p>The string to match to an enchantment</p>
* @return <p>The enchantment matching the string, or null if not found</p>
*/
public static Enchantment matchEnchantment(String input) {
public static @Nullable Enchantment matchEnchantment(@NotNull String input) {
try {
return Enchantment.getByKey(NamespacedKey.minecraft(
input.replace("-", "_").replace(" ", "_").toLowerCase()));
@ -56,7 +58,7 @@ public final class InputParsingHelper {
* @param input <p>The input to RegExIfy</p>
* @return <p>The converted input</p>
*/
public static String regExIfy(String input) {
public static @NotNull String regExIfy(@NotNull String input) {
return input.replace("*", ".*").toUpperCase().replace("-", "_");
}

View File

@ -1,9 +1,11 @@
package net.knarcraft.blacksmith.util;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@ -23,7 +25,7 @@ public final class ItemHelper {
* @param item <p>The item to check</p>
* @return <p>True if the item is repairable</p>
*/
public static boolean isRepairable(ItemStack item) {
public static boolean isRepairable(@NotNull ItemStack item) {
return item.getItemMeta() instanceof Damageable && getMaxDurability(item) > 0;
}
@ -33,7 +35,7 @@ public final class ItemHelper {
* @param itemStack <p>The item to get the durability of</p>
* @return <p>The max durability of the item</p>
*/
public static short getMaxDurability(ItemStack itemStack) {
public static short getMaxDurability(@NotNull ItemStack itemStack) {
return itemStack.getType().getMaxDurability();
}
@ -43,7 +45,7 @@ public final class ItemHelper {
* @param itemStack <p>The item to get the durability of</p>
* @return <p>The durability of the item</p>
*/
public static short getDurability(ItemStack itemStack) {
public static short getDurability(@NotNull ItemStack itemStack) {
Damageable damageable = (Damageable) itemStack.getItemMeta();
int maxDurability = getMaxDurability(itemStack);
if (damageable != null) {
@ -59,7 +61,7 @@ public final class ItemHelper {
* @param itemStack <p>The damage done to the item</p>
* @return <p>The damage done to the item</p>
*/
public static short getDamage(ItemStack itemStack) {
public static short getDamage(@NotNull ItemStack itemStack) {
Damageable damageable = (Damageable) itemStack.getItemMeta();
if (damageable != null) {
return (short) damageable.getDamage();
@ -75,7 +77,7 @@ public final class ItemHelper {
* @param newDamage <p>The new damage done</p>
* @return <p>True if the damage was updated. False if not damageable.</p>
*/
public static boolean updateDamage(ItemStack item, int newDamage) {
public static boolean updateDamage(@NotNull ItemStack item, int newDamage) {
ItemMeta meta = item.getItemMeta();
if (!(meta instanceof Damageable damageable)) {
return false;
@ -90,7 +92,7 @@ public final class ItemHelper {
*
* @return <p>A complete list of reforge-able materials</p>
*/
public static List<Material> getAllReforgeAbleMaterials() {
public static @NotNull List<Material> getAllReforgeAbleMaterials() {
List<Material> reforgeAbleMaterials = new ArrayList<>();
for (Material material : Material.values()) {
ItemStack item = new ItemStack(material);
@ -108,10 +110,49 @@ public final class ItemHelper {
* @param requireDamaged <p>Whether only a damaged anvil should count</p>
* @return <p>True if the given material is an anvil</p>
*/
public static boolean isAnvil(Material material, boolean requireDamaged) {
public static boolean isAnvil(@NotNull Material material, boolean requireDamaged) {
boolean isDamagedAnvil = material == Material.CHIPPED_ANVIL || material == Material.DAMAGED_ANVIL;
boolean isAnvil = isDamagedAnvil || material == Material.ANVIL;
return (requireDamaged && isDamagedAnvil) || (!requireDamaged && isAnvil);
}
/**
* Checks whether the given inventory is able to fit the given item
*
* @param inventory <p>The inventory to check</p>
* @param item <p>The item to check</p>
* @return <p>True if the inventory can fit the item</p>
*/
public static boolean canFitItem(@NotNull Inventory inventory, @NotNull ItemStack item) {
// If a slot is available, there is no problem
if (inventory.firstEmpty() != -1) {
return true;
}
// If the inventory doesn't contain the correct type of item, stacking is impossible
if (!inventory.contains(item.getType())) {
return false;
}
// Check if the item stack can fit in the inventory if stacked with existing items
int availableSlots = 0;
for (ItemStack itemStack : inventory.getStorageContents()) {
ItemMeta itemMeta = itemStack.getItemMeta();
ItemMeta targetMeta = item.getItemMeta();
// Skip items of a different type, or with metadata that would prevent stacking
if (itemStack.getType() != item.getType() ||
(itemMeta != null && targetMeta != null && !itemMeta.equals(targetMeta))) {
continue;
}
availableSlots += itemStack.getMaxStackSize() - itemStack.getAmount();
if (availableSlots < item.getAmount()) {
return true;
}
}
return false;
}
}

View File

@ -2,10 +2,13 @@ package net.knarcraft.blacksmith.util;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
@ -18,6 +21,20 @@ import java.util.Random;
*/
public final class SalvageHelper {
/**
* Gets the sum of all enchantment levels for the given item
*
* @param item <p>The item to check</p>
* @return <p>The total amount of enchantment levels on the item</p>
*/
public static int getTotalEnchantmentLevels(@NotNull ItemStack item) {
int expLevels = 0;
for (Enchantment enchantment : item.getEnchantments().keySet()) {
expLevels += item.getEnchantmentLevel(enchantment);
}
return expLevels;
}
/**
* Gets the items to return if salvaging the given item stack
*
@ -28,7 +45,8 @@ public final class SalvageHelper {
* @param ignoredSalvage <p>Any material which should not be returned as part of the salvage.</p>
* @return <p>The items to return to the user, or null if not salvageable</p>
*/
public static List<ItemStack> getSalvage(Server server, ItemStack salvagedItem, List<Material> ignoredSalvage) {
public static @Nullable List<ItemStack> getSalvage(@NotNull Server server, @Nullable ItemStack salvagedItem,
@NotNull List<Material> ignoredSalvage) {
if (salvagedItem == null || salvagedItem.getAmount() < 1 ||
!ItemHelper.isRepairable(salvagedItem)) {
return null;
@ -52,8 +70,8 @@ public final class SalvageHelper {
* @param ignoredSalvage <p>Any material which should not be returned as part of the salvage.</p>
* @return <p>A list of items, or null if not a valid type of recipe</p>
*/
private static List<ItemStack> getRecipeSalvage(Recipe recipe, ItemStack salvagedItem,
List<Material> ignoredSalvage) {
private static @Nullable List<ItemStack> getRecipeSalvage(@NotNull Recipe recipe, @NotNull ItemStack salvagedItem,
@NotNull List<Material> ignoredSalvage) {
List<ItemStack> ingredients;
if (recipe instanceof ShapedRecipe shapedRecipe) {
ingredients = getIngredients(shapedRecipe);
@ -67,9 +85,7 @@ public final class SalvageHelper {
ingredients = combineStacks(ingredients);
//Purge any ignored salvage to only calculate salvage using the remaining items
if (ignoredSalvage != null) {
ingredients.removeIf((item) -> ignoredSalvage.contains(item.getType()));
}
ingredients.removeIf((item) -> ignoredSalvage.contains(item.getType()));
Random random = new Random();
@ -90,7 +106,7 @@ public final class SalvageHelper {
* @param itemsToCopy <p>The items to make a copy of</p>
* @return <p>A copy of the given items</p>
*/
private static List<ItemStack> copyItems(List<ItemStack> itemsToCopy) {
private static @NotNull List<ItemStack> copyItems(@NotNull List<ItemStack> itemsToCopy) {
List<ItemStack> copies = new ArrayList<>(itemsToCopy.size());
for (ItemStack itemStack : itemsToCopy) {
copies.add(new ItemStack(itemStack.getType(), itemStack.getAmount()));
@ -106,10 +122,11 @@ public final class SalvageHelper {
* @param random <p>The randomness generator to use</p>
* @return <p>The items to be returned to the user as salvage</p>
*/
private static List<ItemStack> getSalvage(List<ItemStack> recipeItems, ItemStack salvagedItem, Random random) {
private static @NotNull List<ItemStack> getSalvage(@NotNull List<ItemStack> recipeItems,
@NotNull ItemStack salvagedItem, @NotNull Random random) {
double percentageRemaining = (ItemHelper.getDurability(salvagedItem) /
(double) ItemHelper.getMaxDurability(salvagedItem));
int totalItems = totalItems(recipeItems);
int totalItems = totalItemAmount(recipeItems);
//Get the amount of recipe items to be returned
int itemsToReturn = (int) Math.floor(percentageRemaining * totalItems);
int bound = recipeItems.size();
@ -137,7 +154,7 @@ public final class SalvageHelper {
* @param items <p>The items to get the sum of</p>
* @return <p>The total number of items</p>
*/
private static int totalItems(List<ItemStack> items) {
private static int totalItemAmount(@NotNull List<ItemStack> items) {
int sum = 0;
for (ItemStack itemStack : items) {
sum += itemStack.getAmount();
@ -154,7 +171,7 @@ public final class SalvageHelper {
* @param items <p>The items to combine</p>
* @return <p>The given items, but combined</p>
*/
private static List<ItemStack> combineStacks(List<ItemStack> items) {
private static @NotNull List<ItemStack> combineStacks(@NotNull List<ItemStack> items) {
Map<Material, Integer> itemAmounts = new HashMap<>();
for (ItemStack item : items) {
Material itemType = item.getType();
@ -174,7 +191,7 @@ public final class SalvageHelper {
* @param shapedRecipe <p>The shaped recipe to get ingredients for</p>
* @return <p>The items contained in the recipe</p>
*/
private static List<ItemStack> getIngredients(ShapedRecipe shapedRecipe) {
private static @NotNull List<ItemStack> getIngredients(@NotNull ShapedRecipe shapedRecipe) {
List<ItemStack> ingredients = new ArrayList<>();
Map<Character, ItemStack> ingredientMap = shapedRecipe.getIngredientMap();
//The shape is a list of the three rows' strings. Each string contains 3 characters.

View File

@ -5,6 +5,7 @@ import net.knarcraft.blacksmith.config.SmithPreset;
import net.knarcraft.blacksmith.config.SmithPresetFilter;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@ -24,7 +25,7 @@ public final class TabCompleteValuesHelper {
* @param valueType <p>The value type to get possible values for</p>
* @return <p>The values to show the user</p>
*/
public static List<String> getTabCompletions(SettingValueType valueType) {
public static @NotNull List<String> getTabCompletions(@NotNull SettingValueType valueType) {
return switch (valueType) {
case POSITIVE_INTEGER -> getPositiveIntegers();
case BOOLEAN -> getBooleans();
@ -43,7 +44,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>Some example enchantment block lists</p>
*/
private static List<String> getExampleEnchantmentBlockLists() {
private static @NotNull List<String> getExampleEnchantmentBlockLists() {
List<String> exampleBlockLists = new ArrayList<>();
exampleBlockLists.add(Enchantment.VANISHING_CURSE.getKey().getKey() + "," +
Enchantment.BINDING_CURSE.getKey().getKey() + "," + Enchantment.MENDING.getKey().getKey());
@ -58,7 +59,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>A complete list of reforge-able material names</p>
*/
private static List<String> getAllReforgeAbleMaterialNames() {
private static @NotNull List<String> getAllReforgeAbleMaterialNames() {
List<String> reforgeAbleMaterials = new ArrayList<>();
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
reforgeAbleMaterials.add(material.name());
@ -80,7 +81,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>A complete list of enchantments</p>
*/
private static List<String> getAllEnchantments() {
private static @NotNull List<String> getAllEnchantments() {
List<String> enchantments = new ArrayList<>();
for (Enchantment enchantment : Enchantment.values()) {
enchantments.add(enchantment.getKey().getKey());
@ -93,7 +94,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>Some example possible values for reforge-able materials</p>
*/
private static List<String> getReforgeAbleMaterials() {
private static @NotNull List<String> getReforgeAbleMaterials() {
List<String> stringLists = new ArrayList<>();
for (SmithPreset preset : SmithPreset.values()) {
stringLists.add("preset:" + preset.name());
@ -114,7 +115,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>Some example string values</p>
*/
private static List<String> getStrings() {
private static @NotNull List<String> getStrings() {
List<String> strings = new ArrayList<>(1);
strings.add("&aExample message. Use & for color tags.");
return strings;
@ -125,7 +126,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>Some example percentage values</p>
*/
private static List<String> getPercentages() {
private static @NotNull List<String> getPercentages() {
List<String> percentages = new ArrayList<>(6);
percentages.add("0");
percentages.add("10");
@ -141,7 +142,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>Some possible positive doubles</p>
*/
private static List<String> getPositiveDoubles() {
private static @NotNull List<String> getPositiveDoubles() {
List<String> positiveDoubles = new ArrayList<>(4);
positiveDoubles.add("0.0");
positiveDoubles.add("0.0001");
@ -156,7 +157,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>Some example positive integers</p>
*/
private static List<String> getPositiveIntegers() {
private static @NotNull List<String> getPositiveIntegers() {
List<String> positiveIntegers = new ArrayList<>(6);
positiveIntegers.add("0");
positiveIntegers.add("5");
@ -173,7 +174,7 @@ public final class TabCompleteValuesHelper {
*
* @return <p>The possible boolean values</p>
*/
private static List<String> getBooleans() {
private static @NotNull List<String> getBooleans() {
List<String> booleans = new ArrayList<>(2);
booleans.add("True");
booleans.add("False");

View File

@ -6,6 +6,8 @@ import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@ -26,7 +28,8 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is valid</p>
*/
public static boolean isValid(SettingValueType valueType, Object value, CommandSender sender) {
public static boolean isValid(@NotNull SettingValueType valueType, @Nullable Object value,
@Nullable CommandSender sender) {
try {
return switch (valueType) {
case POSITIVE_DOUBLE -> isPositiveDouble(value, sender);
@ -51,7 +54,7 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is a material</p>
*/
private static boolean isMaterial(Object value, CommandSender sender) {
private static boolean isMaterial(@Nullable Object value, @Nullable CommandSender sender) {
boolean isMaterial = value instanceof Material || (value instanceof String string &&
InputParsingHelper.matchMaterial(string) != null);
if (!isMaterial && sender != null) {
@ -68,7 +71,7 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is an enchantment</p>
*/
private static boolean isEnchantment(Object value, CommandSender sender) {
private static boolean isEnchantment(@Nullable Object value, @Nullable CommandSender sender) {
boolean isEnchantment = value instanceof Enchantment || (value instanceof String string &&
InputParsingHelper.matchEnchantment(string) != null);
if (!isEnchantment && sender != null) {
@ -85,7 +88,7 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is a string list</p>
*/
private static boolean isStringList(Object value, CommandSender sender) {
private static boolean isStringList(@Nullable Object value, @Nullable CommandSender sender) {
boolean isStringList = value instanceof String[] || value instanceof List<?> || value instanceof String;
if (!isStringList && sender != null) {
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
@ -101,9 +104,9 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is a percentage</p>
*/
private static boolean isPercentage(Object value, CommandSender sender) {
boolean isPercentage = isPositiveInteger(value, null) && ConfigHelper.asInt(value) >= 0 &&
ConfigHelper.asInt(value) <= 100;
private static boolean isPercentage(@Nullable Object value, @Nullable CommandSender sender) {
boolean isPercentage = value != null && isPositiveInteger(value, null) &&
ConfigHelper.asInt(value) >= 0 && ConfigHelper.asInt(value) <= 100;
if (!isPercentage && sender != null) {
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
BlacksmithTranslatableMessage.INPUT_PERCENTAGE_REQUIRED);
@ -118,7 +121,7 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is a non-empty string</p>
*/
private static boolean isNonEmptyString(Object value, CommandSender sender) {
private static boolean isNonEmptyString(@Nullable Object value, @Nullable CommandSender sender) {
boolean isString = value instanceof String string && !string.isBlank();
if (!isString && sender != null) {
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
@ -134,9 +137,9 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is a positive double</p>
*/
private static boolean isPositiveDouble(Object value, CommandSender sender) {
private static boolean isPositiveDouble(@Nullable Object value, @Nullable CommandSender sender) {
try {
return ConfigHelper.asDouble(value) >= 0.0;
return value != null && ConfigHelper.asDouble(value) >= 0.0;
} catch (NumberFormatException | NullPointerException exception) {
if (sender != null) {
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
@ -153,9 +156,9 @@ public final class TypeValidationHelper {
* @param sender <p>The command sender to use for printing error messages</p>
* @return <p>True if the value is a positive integer</p>
*/
private static boolean isPositiveInteger(Object value, CommandSender sender) {
private static boolean isPositiveInteger(@Nullable Object value, @Nullable CommandSender sender) {
try {
return ConfigHelper.asInt(value) >= 0;
return value != null && ConfigHelper.asInt(value) >= 0;
} catch (NumberFormatException | NullPointerException exception) {
if (sender != null) {
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,