Finishes the scrapper implementation
Some checks failed
EpicKnarvik97/Blacksmith/pipeline/head There was a failure building this commit

This commit is contained in:
2024-05-04 01:01:56 +02:00
parent 455db78988
commit 4012e532da
30 changed files with 501 additions and 216 deletions

View File

@ -1,6 +1,8 @@
package net.knarcraft.blacksmith;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.trait.TraitFactory;
import net.citizensnpcs.api.trait.TraitInfo;
import net.knarcraft.blacksmith.command.PresetCommand;
import net.knarcraft.blacksmith.command.PresetTabCompleter;
import net.knarcraft.blacksmith.command.blacksmith.BlackSmithConfigCommand;
@ -18,6 +20,7 @@ import net.knarcraft.blacksmith.listener.NPCClickListener;
import net.knarcraft.blacksmith.listener.PlayerListener;
import net.knarcraft.blacksmith.manager.EconomyManager;
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
import net.knarcraft.blacksmith.trait.ScrapperTrait;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.TranslatableTimeUnit;
import net.knarcraft.knarlib.formatting.Translator;
@ -38,6 +41,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.logging.Level;
@ -154,8 +158,9 @@ public class BlacksmithPlugin extends JavaPlugin {
}
//Register the blacksmith trait with Citizens
CitizensAPI.getTraitFactory().registerTrait(
net.citizensnpcs.api.trait.TraitInfo.create(BlacksmithTrait.class).withName("blacksmith"));
TraitFactory traitFactory = CitizensAPI.getTraitFactory();
traitFactory.registerTrait(TraitInfo.create(BlacksmithTrait.class).withName("blacksmith"));
traitFactory.registerTrait(TraitInfo.create(ScrapperTrait.class).withName("scrapper"));
//Register all commands
registerCommands();
@ -256,12 +261,12 @@ public class BlacksmithPlugin extends JavaPlugin {
*
* @param fileConfiguration <p>The config to read from and write to</p>
*/
private void migrateConfig(FileConfiguration fileConfiguration) {
private void migrateConfig(@NotNull FileConfiguration fileConfiguration) {
//Save the old config just in case something goes wrong
try {
fileConfiguration.save(getDataFolder() + "/config.yml.old");
} catch (IOException e) {
e.printStackTrace();
} catch (IOException exception) {
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, Arrays.toString(exception.getStackTrace()));
return;
}
@ -273,8 +278,8 @@ public class BlacksmithPlugin extends JavaPlugin {
migrationFields = FileHelper.readKeyValuePairs(FileHelper.getBufferedReaderFromInputStream(inputStream),
"=", ColorConversion.NORMAL);
}
} catch (IOException e) {
e.printStackTrace();
} catch (IOException exception) {
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, Arrays.toString(exception.getStackTrace()));
return;
}

View File

@ -131,7 +131,7 @@ public abstract class EditCommand<K extends CustomTrait<L>, L extends Setting> i
}
settings.changeValue(setting, newValue);
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
getValueChangedMessage(setting.getCommandName(), String.valueOf(newValue)));
getValueChangedMessage(setting.getCommandName(), newValue));
//Save the changes immediately to prevent data loss on server crash
CitizensAPI.getNPCRegistry().saveToStore();
}

View File

@ -215,7 +215,7 @@ public class BlackSmithConfigCommand implements CommandExecutor {
private void updateAllMatchedPrices(@NotNull GlobalBlacksmithSettings settings,
@NotNull BlacksmithSetting blacksmithSetting,
@NotNull String materialName, double newPrice) {
List<Material> materials = ItemHelper.getWildcardMatch(materialName);
List<Material> materials = ItemHelper.getWildcardMatch(materialName, false);
for (Material material : materials) {
if (blacksmithSetting == BlacksmithSetting.BASE_PRICE) {
settings.setBasePrice(material, newPrice);

View File

@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
/**
* An interface describing a setting
*/
@SuppressWarnings("unused")
public interface Setting {
/**
@ -12,42 +13,48 @@ public interface Setting {
*
* @return <p>The full config path for this setting</p>
*/
@NotNull String getPath();
@NotNull
String getPath();
/**
* Gets the config path without the root node
*
* @return <p>The config path without the root node</p>
*/
@NotNull String getChildPath();
@NotNull
String getChildPath();
/**
* Gets the value of this setting
*
* @return <p>The value of this setting</p>
*/
@NotNull Object getDefaultValue();
@NotNull
Object getDefaultValue();
/**
* The name of the command used to change this setting
*
* @return <p>The name of this setting's command</p>
*/
@NotNull String getCommandName();
@NotNull
String getCommandName();
/**
* Gets the value type for this setting
*
* @return <p>The value type for this setting</p>
*/
@NotNull SettingValueType getValueType();
@NotNull
SettingValueType getValueType();
/**
* Gets the description explaining the usage of this setting
*
* @return <p>This setting's description</p>
*/
@NotNull String getDescription();
@NotNull
String getDescription();
/**
* Gets whether this setting can be set per-NPC, or if it's set globally

View File

@ -1,5 +1,8 @@
package net.knarcraft.blacksmith.config;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* An interface describing an object for managing settings
*
@ -13,7 +16,7 @@ public interface Settings<K extends Setting> {
* @param setting <p>The setting to change</p>
* @param newValue <p>The new value of the setting</p>
*/
void changeValue(K setting, Object newValue);
void changeValue(@NotNull K setting, @Nullable Object newValue);
/**
* Gets the current raw value of the given global setting
@ -21,6 +24,6 @@ public interface Settings<K extends Setting> {
* @param setting <p>The setting to get</p>
* @return <p>The current raw setting value</p>
*/
Object getRawValue(K setting);
@NotNull Object getRawValue(@NotNull K setting);
}

View File

@ -4,6 +4,7 @@ import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.util.ItemHelper;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@ -46,7 +47,7 @@ public enum SmithPreset {
*
* @param filters <p>The filters applicable to this preset</p>
*/
SmithPreset(SmithPresetFilter[] filters) {
SmithPreset(@NotNull SmithPresetFilter[] filters) {
this.filters = filters;
}
@ -56,7 +57,7 @@ public enum SmithPreset {
* @param filter <p>The filter to check</p>
* @return <p>True if the filter is supported</p>
*/
public boolean supportsFilter(SmithPresetFilter filter) {
public boolean supportsFilter(@NotNull SmithPresetFilter filter) {
return List.of(filters).contains(filter);
}
@ -65,6 +66,7 @@ public enum SmithPreset {
*
* @return <p>The filters supported by this preset</p>
*/
@NotNull
public List<SmithPresetFilter> getSupportedFilters() {
return List.of(filters);
}
@ -74,6 +76,7 @@ public enum SmithPreset {
*
* @return <p>All available smith presets</p>
*/
@NotNull
public static List<String> getPresetNames() {
List<String> presetNames = new ArrayList<>();
for (SmithPreset preset : SmithPreset.values()) {
@ -88,7 +91,8 @@ public enum SmithPreset {
* @param possiblePreset <p>The string that might be a preset</p>
* @return <p>The string, possibly with the preset replaced</p>
*/
public static String replacePreset(String possiblePreset) {
@NotNull
public static String replacePreset(@NotNull String possiblePreset) {
boolean negated = false;
String upperCasedPreset = possiblePreset.replace('-', '_').toUpperCase();
@ -143,6 +147,7 @@ public enum SmithPreset {
* @param filter <p>The filter to use for filtering</p>
* @return <p>The materials included in this preset, filtered using the given filter</p>
*/
@NotNull
public List<Material> getFilteredMaterials(SmithPresetFilter filter) {
List<Material> materials = new ArrayList<>(this.getMaterials());
materials.removeIf((item) -> !filter.isIncluded(item));
@ -154,6 +159,7 @@ public enum SmithPreset {
*
* @return <p>All materials in this preset</p>
*/
@NotNull
public List<Material> getMaterials() {
return switch (this) {
case BLACKSMITH -> ItemHelper.getAllReforgeAbleMaterials();
@ -168,6 +174,7 @@ public enum SmithPreset {
*
* @return <p>All ranged weapon materials</p>
*/
@NotNull
private List<Material> getRanged() {
List<Material> ranged = new ArrayList<>();
ranged.add(Material.TRIDENT);
@ -181,6 +188,7 @@ public enum SmithPreset {
*
* @return <p>All tool materials</p>
*/
@NotNull
private List<Material> getTools() {
List<Material> tools = new ArrayList<>();
tools.addAll(Tag.ITEMS_HOES.getValues());
@ -198,6 +206,7 @@ public enum SmithPreset {
*
* @return <p>All weapon materials</p>
*/
@NotNull
private List<Material> getWeapons() {
List<Material> weapons = new ArrayList<>(getSwords());
weapons.addAll(getRanged());
@ -210,10 +219,17 @@ public enum SmithPreset {
*
* @return <p>All sword materials</p>
*/
@NotNull
private Set<Material> getSwords() {
return Tag.ITEMS_SWORDS.getValues();
}
/**
* Gets all types of armor
*
* @return <p>All armor types</p>
*/
@NotNull
private List<Material> getArmor() {
List<Material> armor = new ArrayList<>();
armor.addAll(getMaterialsEndingWith("HELMET"));
@ -230,7 +246,8 @@ public enum SmithPreset {
* @param end <p>The string to look for</p>
* @return <p>The resulting materials</p>
*/
private List<Material> getMaterialsEndingWith(String end) {
@NotNull
private List<Material> getMaterialsEndingWith(@NotNull String end) {
List<Material> matchedMaterials = new ArrayList<>();
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
if (!material.name().startsWith("LEGACY") && material.name().endsWith(end)) {
@ -245,6 +262,7 @@ public enum SmithPreset {
*
* @return <p>All material names for this smith</p>
*/
@NotNull
private List<String> getMaterialNames() {
return getNames(this.getMaterials());
}
@ -255,7 +273,8 @@ public enum SmithPreset {
* @param filter <p>The filter used for filtering materials</p>
* @return <p>All material names for this smith</p>
*/
private List<String> getMaterialNames(SmithPresetFilter filter) {
@NotNull
private List<String> getMaterialNames(@NotNull SmithPresetFilter filter) {
return getNames(this.getFilteredMaterials(filter));
}
@ -265,7 +284,8 @@ public enum SmithPreset {
* @param materials <p>The materials to get the names of</p>
* @return <p>The names of the materials</p>
*/
private List<String> getNames(List<Material> materials) {
@NotNull
private List<String> getNames(@NotNull List<Material> materials) {
List<String> items = new ArrayList<>();
for (Material material : materials) {
items.add(material.name().toLowerCase().replace("_", "-"));
@ -279,7 +299,8 @@ public enum SmithPreset {
* @param materials <p>The material names to negate</p>
* @return <p>The negated material names</p>
*/
private static List<String> negateMaterials(List<String> materials) {
@NotNull
private static List<String> negateMaterials(@NotNull List<String> materials) {
List<String> negatedMaterials = new ArrayList<>(materials.size());
materials.forEach((material) -> {
if (material != null && !material.isBlank()) {

View File

@ -9,6 +9,8 @@ import net.knarcraft.blacksmith.util.InputParsingHelper;
import net.knarcraft.blacksmith.util.ItemHelper;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
@ -22,7 +24,7 @@ import java.util.logging.Level;
public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
private final List<Material> reforgeAbleItems = new ArrayList<>();
private final List<Enchantment> enchantmentBlocklist = new ArrayList<>();
private final List<Enchantment> enchantmentBlockList = new ArrayList<>();
private final Map<BlacksmithSetting, Object> currentValues = new HashMap<>();
private final GlobalBlacksmithSettings globalBlacksmithSettings;
@ -46,7 +48,7 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
}
//Updates the list of reforge-able items/materials
updateReforgeAbleItems();
updateEnchantmentBlocklist();
updateEnchantmentBlockList();
}
/**
@ -61,7 +63,7 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
}
@Override
public void changeValue(BlacksmithSetting setting, Object newValue) {
public void changeValue(@NotNull BlacksmithSetting setting, @Nullable Object newValue) {
if (setting.getValueType() == SettingValueType.STRING_LIST ||
setting.getValueType() == SettingValueType.REFORGE_ABLE_ITEMS) {
//Workaround to make sure it's treated as the correct type
@ -72,8 +74,8 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
if (setting == BlacksmithSetting.REFORGE_ABLE_ITEMS) {
updateReforgeAbleItems();
}
if (setting == BlacksmithSetting.ENCHANTMENT_BLOCKLIST) {
updateEnchantmentBlocklist();
if (setting == BlacksmithSetting.ENCHANTMENT_BLOCK_LIST) {
updateEnchantmentBlockList();
}
}
@ -83,7 +85,7 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
* @param setting <p>The setting to get the value of</p>
* @return <p>The current value of the setting</p>
*/
public Object getRawValue(BlacksmithSetting setting) {
public @NotNull Object getRawValue(@NotNull BlacksmithSetting setting) {
return currentValues.get(setting);
}
@ -195,12 +197,12 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
*
* @return <p>The list of blocked enchantments</p>
*/
public List<Enchantment> getEnchantmentBlocklist() {
Object currentValue = currentValues.get(BlacksmithSetting.ENCHANTMENT_BLOCKLIST);
public List<Enchantment> getEnchantmentBlockList() {
Object currentValue = currentValues.get(BlacksmithSetting.ENCHANTMENT_BLOCK_LIST);
if (currentValue == null || String.valueOf(currentValue).isEmpty()) {
return globalBlacksmithSettings.getEnchantmentBlocklist();
return globalBlacksmithSettings.getEnchantmentBlockList();
} else {
return new ArrayList<>(this.enchantmentBlocklist);
return new ArrayList<>(this.enchantmentBlockList);
}
}
@ -356,11 +358,11 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
/**
* Updates the list of blocked enchantments
*/
private void updateEnchantmentBlocklist() {
this.enchantmentBlocklist.clear();
List<String> enchantments = ConfigHelper.asStringList(getValue(BlacksmithSetting.ENCHANTMENT_BLOCKLIST));
private void updateEnchantmentBlockList() {
this.enchantmentBlockList.clear();
List<String> enchantments = ConfigHelper.asStringList(getValue(BlacksmithSetting.ENCHANTMENT_BLOCK_LIST));
if (enchantments != null) {
this.enchantmentBlocklist.addAll(getEnchantmentBlocklist(enchantments));
this.enchantmentBlockList.addAll(getEnchantmentBlockList(enchantments));
}
}
@ -370,8 +372,8 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
* @param enchantments <p>The enchantment names to block</p>
* @return <p>The enchantments to be blocked</p>
*/
public static List<Enchantment> getEnchantmentBlocklist(List<String> enchantments) {
List<Enchantment> enchantmentBlocklist = new ArrayList<>();
public static List<Enchantment> getEnchantmentBlockList(List<String> enchantments) {
List<Enchantment> enchantmentBlockList = new ArrayList<>();
for (String item : enchantments) {
if (InputParsingHelper.isEmpty(item)) {
@ -380,13 +382,13 @@ public class BlacksmithNPCSettings implements TraitSettings<BlacksmithSetting> {
Enchantment enchantment = InputParsingHelper.matchEnchantment(item);
if (enchantment != null) {
enchantmentBlocklist.add(enchantment);
enchantmentBlockList.add(enchantment);
} else {
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to verify " + item +
" as a valid enchantment");
}
}
return enchantmentBlocklist;
return enchantmentBlockList;
}
/**

View File

@ -90,7 +90,7 @@ public enum BlacksmithSetting implements Setting {
/**
* The setting for the enchantments a blacksmith cannot apply to items
*/
ENCHANTMENT_BLOCKLIST("enchantmentBlocklist", SettingValueType.STRING_LIST, List.of("binding_curse",
ENCHANTMENT_BLOCK_LIST("enchantmentBlockList", SettingValueType.STRING_LIST, List.of("binding_curse",
"mending", "vanishing_curse"), "The enchantments a " +
"blacksmith is denied from applying to an item. Disable anything you find too op or annoying.",
true, false),

View File

@ -11,6 +11,7 @@ import net.knarcraft.blacksmith.util.ItemHelper;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
@ -29,7 +30,7 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
private final Map<Enchantment, Double> enchantmentCosts = new HashMap<>();
private final Map<BlacksmithSetting, Object> settings = new HashMap<>();
private final List<Material> defaultReforgeAbleMaterials = new ArrayList<>();
private final List<Enchantment> defaultEnchantmentBlocklist = new ArrayList<>();
private final List<Enchantment> defaultEnchantmentBlockList = new ArrayList<>();
private final YamlStorage defaultConfig;
@ -71,7 +72,7 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
* @param blacksmithSetting <p>The default NPC setting to change</p>
* @param newValue <p>The new value for the setting</p>
*/
public void changeValue(BlacksmithSetting blacksmithSetting, Object newValue) {
public void changeValue(@NotNull BlacksmithSetting blacksmithSetting, @Nullable Object newValue) {
if (blacksmithSetting.getValueType() == SettingValueType.STRING_LIST ||
blacksmithSetting.getValueType() == SettingValueType.REFORGE_ABLE_ITEMS) {
//Workaround to make sure it's treated as the correct type
@ -82,8 +83,8 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
save();
if (blacksmithSetting == BlacksmithSetting.REFORGE_ABLE_ITEMS) {
loadReforgeAbleItems();
} else if (blacksmithSetting == BlacksmithSetting.ENCHANTMENT_BLOCKLIST) {
loadEnchantmentBlocklist();
} else if (blacksmithSetting == BlacksmithSetting.ENCHANTMENT_BLOCK_LIST) {
loadEnchantmentBlockList();
}
}
@ -93,7 +94,7 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
* @param blacksmithSetting <p>The setting to get</p>
* @return <p>The current raw setting value</p>
*/
public Object getRawValue(BlacksmithSetting blacksmithSetting) {
public @NotNull Object getRawValue(@NotNull BlacksmithSetting blacksmithSetting) {
return this.settings.get(blacksmithSetting);
}
@ -248,12 +249,12 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
}
/**
* Gets the value of enchantmentBlocklist
* Gets the value of enchantmentBlockList
*
* @return <p>The value of enchantmentBlocklist</p>
* @return <p>The value of enchantmentBlockList</p>
*/
public @NotNull List<Enchantment> getEnchantmentBlocklist() {
return this.defaultEnchantmentBlocklist;
public @NotNull List<Enchantment> getEnchantmentBlockList() {
return this.defaultEnchantmentBlockList;
}
/**
@ -327,7 +328,7 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
}
}
loadReforgeAbleItems();
loadEnchantmentBlocklist();
loadEnchantmentBlockList();
//Load all base prices
loadBasePrices(root);
@ -465,14 +466,14 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
}
/**
* Loads the enchantment blocklist from the current value
* Loads the enchantment block list from the current value
*/
private void loadEnchantmentBlocklist() {
this.defaultEnchantmentBlocklist.clear();
private void loadEnchantmentBlockList() {
this.defaultEnchantmentBlockList.clear();
List<String> enchantmentNames = ConfigHelper.asStringList(settings.get(
BlacksmithSetting.ENCHANTMENT_BLOCKLIST));
BlacksmithSetting.ENCHANTMENT_BLOCK_LIST));
if (enchantmentNames != null) {
this.defaultEnchantmentBlocklist.addAll(BlacksmithNPCSettings.getEnchantmentBlocklist(enchantmentNames));
this.defaultEnchantmentBlockList.addAll(BlacksmithNPCSettings.getEnchantmentBlockList(enchantmentNames));
}
}

View File

@ -86,7 +86,7 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
* @param scrapperSetting <p>The setting to get</p>
* @return <p>The current raw setting value</p>
*/
public Object getRawValue(ScrapperSetting scrapperSetting) {
public @NotNull Object getRawValue(@NotNull ScrapperSetting scrapperSetting) {
return this.settings.get(scrapperSetting);
}
@ -104,7 +104,7 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
*
* @return <p>Whether to show exact time</p>
*/
public boolean getShowExactTime() {
public boolean showExactTime() {
return asBoolean(ScrapperSetting.SHOW_EXACT_TIME);
}
@ -173,10 +173,20 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
*
* @return <p>The value of salvageAbleItems</p>
*/
@NotNull
public List<Material> getSalvageAbleItems() {
return this.defaultSalvageableMaterials;
}
/**
* Gets the cost of using a scrapper
*
* @return <p>The cost of using a scrapper</p>
*/
public double getCost() {
return ConfigHelper.asDouble(getValue(ScrapperSetting.USE_COST));
}
/**
* Gets ignored salvage for the given material
*
@ -186,7 +196,8 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
* @param material <p>The material to get ignored salvage for</p>
* @return <p>The ignored salvage</p>
*/
public @Nullable Set<Material> getIgnoredSalvage(@NotNull Material material) {
@Nullable
public Set<Material> getIgnoredSalvage(@NotNull Material material) {
return this.ignoredSalvage.get(material);
}
@ -221,15 +232,15 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
// Parse all material names
String[] data = ignoredSalvageInfo.split(":");
String[] materialStrings = data[0].split(",");
String[] materialStrings = data[0].split(";");
List<Material> materials = new ArrayList<>();
for (String materialString : materialStrings) {
materials.addAll(ItemHelper.getWildcardMatch(materialString));
materials.addAll(ItemHelper.getWildcardMatch(materialString, true));
}
String[] ignoredSalvageStrings = data[1].split(",");
String[] ignoredSalvageStrings = data[1].split(";");
List<Material> ignored = new ArrayList<>();
for (String ignoredSalvageString : ignoredSalvageStrings) {
ignored.addAll(ItemHelper.getWildcardMatch(ignoredSalvageString));
ignored.addAll(ItemHelper.getWildcardMatch(ignoredSalvageString, true));
}
// Add the ignored salvage to all the matched materials

View File

@ -6,6 +6,8 @@ import net.knarcraft.blacksmith.config.TraitSettings;
import net.knarcraft.blacksmith.util.ConfigHelper;
import net.knarcraft.blacksmith.util.ItemHelper;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
@ -57,7 +59,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
* @param setting <p>The setting to change</p>
* @param newValue <p>The new value of the setting</p>
*/
public void changeValue(ScrapperSetting setting, Object newValue) {
public void changeValue(@NotNull ScrapperSetting setting, @Nullable Object newValue) {
if (setting.getValueType() == SettingValueType.STRING_LIST ||
setting.getValueType() == SettingValueType.REFORGE_ABLE_ITEMS) {
//Workaround to make sure it's treated as the correct type
@ -87,21 +89,24 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
* @param setting <p>The setting to get the value of</p>
* @return <p>The current value of the setting</p>
*/
public Object getRawValue(ScrapperSetting setting) {
public @NotNull Object getRawValue(@NotNull ScrapperSetting setting) {
return currentValues.get(setting);
}
@Override
@NotNull
public String getBusyWithPlayerMessage() {
return asString(ScrapperSetting.BUSY_WITH_PLAYER_MESSAGE);
}
@Override
@NotNull
public String getBusyWorkingMessage() {
return asString(ScrapperSetting.BUSY_WITH_SALVAGE_MESSAGE);
}
@Override
@NotNull
public String getStartWorkingMessage() {
return asString(ScrapperSetting.START_SALVAGE_MESSAGE);
}
@ -111,6 +116,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
*
* @return <p>The salvage success message</p>
*/
@NotNull
public String getSuccessMessage() {
return asString(ScrapperSetting.SUCCESS_SALVAGE_MESSAGE);
}
@ -120,11 +126,22 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
*
* @return <p>The salvage fail message</p>
*/
@NotNull
public String getFailMessage() {
return asString(ScrapperSetting.FAIL_SALVAGE_MESSAGE);
}
/**
* Gets the message to use for displaying salvage cost
*
* @return <p>The message to use for displaying salvage cost</p>
*/
public String getCostMessage() {
return asString(ScrapperSetting.COST_MESSAGE);
}
@Override
@NotNull
public String getCoolDownUnexpiredMessage() {
return asString(ScrapperSetting.COOL_DOWN_UNEXPIRED_MESSAGE);
}
@ -132,6 +149,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
/**
* The message displayed if a player presents a different item after seeing the price to salvage an item
*/
@NotNull
public String getItemChangedMessage() {
return asString(ScrapperSetting.ITEM_UNEXPECTEDLY_CHANGED_MESSAGE);
}
@ -177,15 +195,6 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
return asInt(ScrapperSetting.SALVAGE_COOL_DOWN) <= 0;
}
/**
* Gets whether to disable the delay between starting reforging and the reforging finishing
*
* @return <p>Whether to disable the reforge delay</p>
*/
public boolean getDisableDelay() {
return asInt(ScrapperSetting.MAX_SALVAGE_DELAY) <= 0;
}
/**
* Gets the chance of a salvaging to fail
*
@ -203,7 +212,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
* @param setting <p>The setting to get the value of</p>
* @return <p>The value of the given setting as an integer</p>
*/
private int asInt(ScrapperSetting setting) {
private int asInt(@NotNull ScrapperSetting setting) {
return ConfigHelper.asInt(getValue(setting));
}
@ -213,7 +222,8 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
* @param setting <p>The setting to get the value of</p>
* @return <p>The value of the given setting as a string</p>
*/
private String asString(ScrapperSetting setting) {
@NotNull
private String asString(@NotNull ScrapperSetting setting) {
return getValue(setting).toString();
}
@ -223,7 +233,8 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
* @param setting <p>The setting to get the value of</p>
* @return <p>The current value</p>
*/
private Object getValue(ScrapperSetting setting) {
@NotNull
private Object getValue(@NotNull ScrapperSetting setting) {
Object value = currentValues.get(setting);
//If not set, use the default value from the config.yml file
if (value == null) {
@ -244,6 +255,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
*
* @return <p>All salvageable items</p>
*/
@NotNull
public List<Material> getSalvageAbleItems() {
Object currentValue = currentValues.get(ScrapperSetting.SALVAGE_ABLE_ITEMS);
if (currentValue == null || String.valueOf(currentValue).isEmpty()) {
@ -257,7 +269,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
* Whether extended salvaging is enabled
*
* <p>When not extended, only repairable items can be salvaged. When extended, any item produced using a crafting
* recipe or a smithing transformation can be salvaged. This does not include smelting or similar.</p>
* recipe can be salvaged. This does not include smelting or similar.</p>
*
* @return <p>True if extended salvaging is enabled</p>
*/
@ -273,6 +285,7 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
*
* @return <p>The title of this scrapper NPC</p>
*/
@NotNull
public String getScrapperTitle() {
return asString(ScrapperSetting.SCRAPPER_TITLE);
}
@ -282,8 +295,19 @@ public class ScrapperNPCSettings implements TraitSettings<ScrapperSetting> {
*
* @return <p>The message to display</p>
*/
@NotNull
public String getInvalidItemMessage() {
return asString(ScrapperSetting.INVALID_ITEM_MESSAGE);
}
/**
* Gets the message to display if the player is unable to afford an item salvage
*
* @return <p>The message to display</p>
*/
@NotNull
public String getInsufficientFundsMessage() {
return asString(ScrapperSetting.INSUFFICIENT_FUNDS_MESSAGE);
}
}

View File

@ -140,10 +140,30 @@ public enum ScrapperSetting implements Setting {
START_SALVAGE_MESSAGE("startSalvageMessage", SettingValueType.STRING, "&eOk, let's see what I can do...",
"The message to display once the blacksmith starts re-forging", true, true),
/**
* The message displayed if a player is unable to pay the blacksmith
*/
INSUFFICIENT_FUNDS_MESSAGE("insufficientFundsMessage", SettingValueType.STRING,
"&cYou don't have enough money to salvage an item!",
"The message to display when a player cannot pay for the salvaging", true, true),
/**
* The message displayed when displaying the cost of reforging the held item to the player
*/
COST_MESSAGE("costMessage", SettingValueType.STRING,
"&eIt will cost &a{cost}&e to salvage that item! Click again to salvage!",
"The message to display when informing a player about the salvaging cost", true, true),
/*------------------
| Global settings |
------------------*/
/**
* The setting for the use cost of using the scrapper
*/
USE_COST("basePrice", SettingValueType.POSITIVE_DOUBLE, 0, "The cost of using a scrapper",
false, false),
/**
* Whether to display exact time in minutes and seconds when displaying a remaining cool-down
*/

View File

@ -65,6 +65,7 @@ public class PlayerListener implements Listener {
* @param <T> <p>The type of entity the player is looking at</p>
* @return <p>The entity the player is looking at, or null if no such entity exists</p>
*/
@Nullable
private static <T extends Entity> T getTarget(final @Nullable Entity entity, final @NotNull Iterable<T> entities) {
if (entity == null) {
return null;

View File

@ -48,7 +48,17 @@ public class EconomyManager {
* @return <p>Whether the player cannot pay for the reforge</p>
*/
public static boolean cannotPayForHeldItemReforge(@NotNull Player player) {
return !(economy.getBalance(player) - getHeldItemCost(player) >= 0);
return economy.getBalance(player) - getHeldItemCost(player) < 0;
}
/**
* Gets whether the given player cannot pay for salvaging an item
*
* @param player <p>The player holding an item</p>
* @return <p>Whether the player cannot pay for the salvage</p>
*/
public static boolean cannotPayForSalvage(@NotNull Player player) {
return economy.getBalance(player) - BlacksmithPlugin.getInstance().getGlobalScrapperSettings().getCost() < 0;
}
/**
@ -57,11 +67,23 @@ public class EconomyManager {
* @param player <p>The player holding an item</p>
* @return <p>The formatted cost</p>
*/
public static String formatCost(@NotNull Player player) {
@NotNull
public static String formatBlacksmithCost(@NotNull Player player) {
double cost = getHeldItemCost(player);
return economy.format(cost);
}
/**
* Gets the human-readable cost of salvaging an item
*
* @return <p>The formatted cost</p>
*/
@NotNull
public static String formatScrapperCost() {
double cost = BlacksmithPlugin.getInstance().getGlobalScrapperSettings().getCost();
return economy.format(cost);
}
/**
* Withdraws the reforging cost from the given player
*
@ -69,8 +91,23 @@ public class EconomyManager {
*
* @param player <p>The player to withdraw from</p>
*/
public static void withdraw(@NotNull Player player) {
economy.withdrawPlayer(player, getHeldItemCost(player));
public static void withdrawBlacksmith(@NotNull Player player) {
double cost = getHeldItemCost(player);
if (cost > 0) {
economy.withdrawPlayer(player, cost);
}
}
/**
* Withdraws the salvaging cost from the given player
*
* @param player <p>The player to withdraw from</p>
*/
public static void withdrawScrapper(Player player) {
double cost = BlacksmithPlugin.getInstance().getGlobalScrapperSettings().getCost();
if (cost > 0) {
economy.withdrawPlayer(player, cost);
}
}
/**

View File

@ -39,7 +39,8 @@ public class BlacksmithTrait extends CustomTrait<BlacksmithSetting> {
*
* @return <p>The current settings for this NPC</p>
*/
public @NotNull BlacksmithNPCSettings getSettings() {
@NotNull
public BlacksmithNPCSettings getSettings() {
return config;
}
@ -90,7 +91,7 @@ public class BlacksmithTrait extends CustomTrait<BlacksmithSetting> {
session = new ReforgeSession(this, player, npc, config);
//Tell the player the cost of repairing the item
String cost = EconomyManager.formatCost(player);
String cost = EconomyManager.formatBlacksmithCost(player);
String itemName = hand.getType().name().toLowerCase().replace('_', ' ');
sendNPCMessage(this.npc, player, config.getCostMessage().replace("{cost}", cost).replace("{item}",
itemName));

View File

@ -7,10 +7,12 @@ import net.knarcraft.blacksmith.config.Settings;
import net.knarcraft.blacksmith.config.TraitSettings;
import net.knarcraft.blacksmith.formatting.TimeFormatter;
import net.knarcraft.blacksmith.manager.EconomyManager;
import net.knarcraft.blacksmith.util.ItemHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -174,9 +176,17 @@ public abstract class CustomTrait<K extends Setting> extends Trait {
*/
private void startMainAction(@NotNull NPC npc, @NotNull Player player) {
sendNPCMessage(this.npc, player, config.getStartWorkingMessage());
// TODO: Differentiate between blacksmiths and scrappers when withdrawing money
EconomyManager.withdraw(player);
boolean isBlacksmith = this instanceof BlacksmithTrait;
if (isBlacksmith) {
EconomyManager.withdrawBlacksmith(player);
} else {
EconomyManager.withdrawScrapper(player);
}
session.scheduleAction();
PlayerInventory playerInventory = player.getInventory();
ItemStack heldItem = player.getInventory().getItemInMainHand();
//Display the item in the NPC's hand
@ -186,9 +196,16 @@ public abstract class CustomTrait<K extends Setting> extends Trait {
Objects.requireNonNull(((LivingEntity) npc.getEntity()).getEquipment()).setItemInMainHand(heldItem);
}
//Remove the item from the player's inventory
// TODO: For a scrapper with extended salvaging enabled, the item needs to be reduced with the amount specified
// in the recipe, or removed as normal in the case where the player has exactly enough items to run the salvage.
player.getInventory().setItemInMainHand(null);
if (!isBlacksmith) {
// For scrappers, just reduce the amounts of items, unless the remaining stack is salvaged
int amount = ItemHelper.getRequiredAmountForSalvage(player.getServer(), heldItem);
if (amount != heldItem.getAmount()) {
heldItem.setAmount(heldItem.getAmount() - amount);
playerInventory.setItemInMainHand(heldItem);
return;
}
}
playerInventory.setItemInMainHand(null);
}
}

View File

@ -178,7 +178,7 @@ public class ReforgeSession extends Session implements Runnable {
}
}
//Remove any enchantments in the block list
usableEnchantments.removeAll(blacksmithTrait.getSettings().getEnchantmentBlocklist());
usableEnchantments.removeAll(blacksmithTrait.getSettings().getEnchantmentBlockList());
//In case all usable enchantments have been blocked, abort
if (usableEnchantments.isEmpty()) {

View File

@ -1,11 +1,10 @@
package net.knarcraft.blacksmith.trait;
import net.citizensnpcs.api.npc.NPC;
import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.config.scrapper.ScrapperNPCSettings;
import net.knarcraft.blacksmith.manager.EconomyManager;
import net.knarcraft.blacksmith.util.ItemHelper;
import net.knarcraft.blacksmith.util.SalvageHelper;
import org.bukkit.Material;
import org.bukkit.entity.Damageable;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@ -13,17 +12,15 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
import static net.knarcraft.blacksmith.util.ItemHelper.updateDamage;
/**
* A representation of the session between a player and a blacksmith
* A representation of the session between a player and a scrapper
*/
public class SalvageSession extends Session implements Runnable {
@ -38,28 +35,19 @@ public class SalvageSession extends Session implements Runnable {
/**
* Instantiates a new session
*
* @param scrapperTrait <p>A reference to the blacksmith trait</p>
* @param scrapperTrait <p>A reference to the scrapper trait</p>
* @param player <p>The player initiating the session</p>
* @param npc <p>The Blacksmith NPC involved in the session</p>
* @param npc <p>The scrapper NPC involved in the session</p>
* @param config <p>The config to use for the session</p>
*/
SalvageSession(@NotNull ScrapperTrait scrapperTrait, @NotNull Player player, @NotNull NPC npc,
@NotNull ScrapperNPCSettings config) {
@NotNull ScrapperNPCSettings config, @NotNull List<ItemStack> salvage) {
super(player);
this.scrapperTrait = scrapperTrait;
this.npc = npc;
this.itemToSalvage = player.getInventory().getItemInMainHand();
this.config = config;
// Get the salvage, for the item, but ignore some materials if set, and the item isn't at full durability
Set<Material> ignoredSalvage = BlacksmithPlugin.getInstance().getGlobalScrapperSettings().getIgnoredSalvage(
this.itemToSalvage.getType());
if (ignoredSalvage == null || ItemHelper.getDamage(this.itemToSalvage) == 0) {
ignoredSalvage = new HashSet<>();
}
this.salvage = SalvageHelper.getSalvage(BlacksmithPlugin.getInstance().getServer(), this.itemToSalvage,
ignoredSalvage);
this.salvage = salvage;
this.enchantmentLevels = SalvageHelper.getTotalEnchantmentLevels(this.itemToSalvage);
}
@ -71,7 +59,11 @@ public class SalvageSession extends Session implements Runnable {
sendNPCMessage(this.npc, player, config.getItemChangedMessage());
return true;
}
// TODO: Add economy check
if (EconomyManager.cannotPayForSalvage(player)) {
sendNPCMessage(this.npc, player, config.getInsufficientFundsMessage());
return true;
}
return false;
}
@ -93,7 +85,7 @@ public class SalvageSession extends Session implements Runnable {
public void run() {
sendNPCMessage(this.npc, player, salvageItem() ? config.getSuccessMessage() : config.getFailMessage());
//Stop the reforged item from displaying in the blacksmith's hand
//Stop the reforged item from displaying in the scrapper's hand
if (npc.getEntity() instanceof Player) {
((Player) npc.getEntity()).getInventory().setItemInMainHand(null);
} else {
@ -126,10 +118,10 @@ public class SalvageSession extends Session implements Runnable {
}
/**
* The method to run when a blacksmith fails re-forging an item
* The method to run when a crapper fails salvaging an item
*/
private void failSalvage() {
if (itemToSalvage instanceof Damageable) {
if (itemToSalvage.getItemMeta() instanceof Damageable) {
//Damage the item
short currentItemDurability = ItemHelper.getDurability(itemToSalvage);
short newDurability = (short) (currentItemDurability + (currentItemDurability * random.nextInt(8)));
@ -150,7 +142,7 @@ public class SalvageSession extends Session implements Runnable {
*/
private void giveSalvage() {
// TODO: Find a better calculation than 1 enchantment level = 1 exp level
// Gives the player back some of the XP used on an item
// Gives the player back some of the EXP used on an item
player.giveExpLevels(enchantmentLevels);
if (config.getDropItem() || !player.isOnline() || player.getInventory().firstEmpty() == -1) {
// If the player isn't online, or the player cannot fit the item, drop the item to prevent it from

View File

@ -4,16 +4,21 @@ import net.citizensnpcs.api.util.DataKey;
import net.knarcraft.blacksmith.BlacksmithPlugin;
import net.knarcraft.blacksmith.config.scrapper.ScrapperNPCSettings;
import net.knarcraft.blacksmith.config.scrapper.ScrapperSetting;
import net.knarcraft.blacksmith.manager.EconomyManager;
import net.knarcraft.blacksmith.util.ItemHelper;
import net.knarcraft.blacksmith.util.SalvageHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import org.apache.commons.lang.NotImplementedException;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
@ -22,8 +27,6 @@ import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.send
*/
public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
//TODO: A scrapper will take items and turn them into the base ingredients
//TODO: If an item is enchanted, give an appropriate amount of exp
private final ScrapperNPCSettings config;
/**
@ -37,15 +40,6 @@ public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
super.setTraitSettings(this.config);
}
/**
* Gets the current settings for this NPC
*
* @return <p>The current settings for this NPC</p>
*/
public ScrapperNPCSettings getSettings() {
return config;
}
/**
* Loads all config values stored in citizens' config file for this NPC
*
@ -75,25 +69,58 @@ public class ScrapperTrait extends CustomTrait<ScrapperSetting> {
ItemStack itemInHand = player.getInventory().getItemInMainHand();
List<Material> salvageAbleItems = this.config.getSalvageAbleItems();
boolean extended = this.config.extendedSalvageEnabled();
List<ItemStack> salvage = getSalvage(player.getServer(), itemInHand, salvageAbleItems, extended);
// If extended mode is disabled, only allow repairable items to be salvaged
boolean notHoldingSalvageable = !ItemHelper.isSalvageable(player.getServer(), itemInHand) ||
(!salvageAbleItems.isEmpty() && !salvageAbleItems.contains(itemInHand.getType())) ||
(!extended && !ItemHelper.isRepairable(itemInHand));
boolean notHoldingSalvageable = salvage == null || salvage.isEmpty();
if (notHoldingSalvageable) {
String invalidMessage = StringFormatter.replacePlaceholder(config.getInvalidItemMessage(),
"{title}", config.getScrapperTitle());
sendNPCMessage(this.npc, player, invalidMessage);
return;
}
// TODO: Mark the session start
// TODO: Initialize a new session
// TODO: Tell player about the required cost
throw new NotImplementedException();
//Start a new scrapper session for the player
currentSessionStartTime = System.currentTimeMillis();
session = new SalvageSession(this, player, npc, config, salvage);
//Tell the player the cost of repairing the item
String cost = EconomyManager.formatScrapperCost();
sendNPCMessage(this.npc, player, config.getCostMessage().replace("{cost}", cost));
}
@Override
protected boolean showExactTime() {
return BlacksmithPlugin.getInstance().getGlobalScrapperSettings().getShowExactTime();
return BlacksmithPlugin.getInstance().getGlobalScrapperSettings().showExactTime();
}
/**
* Gets salvage for an item, if it's salvage-able
*
* @param server <p>The server to get recipes from</p>
* @param item <p>The item to calculate salvage for</p>
* @param salvageAbleItems <p>The items this scrapper can salvage</p>
* @param extended <p>Whether extended salvage is enabled</p>
* @return <p>The possible salvage, or null if not salvage-able</p>
*/
@Nullable
private List<ItemStack> getSalvage(@NotNull Server server, @NotNull ItemStack item,
@NotNull List<Material> salvageAbleItems, boolean extended) {
boolean isSalvageable = (extended || ItemHelper.isRepairable(item)) && ItemHelper.isSalvageable(server, item) &&
(salvageAbleItems.isEmpty() || salvageAbleItems.contains(item.getType()));
if (!isSalvageable) {
return null;
}
// Get the salvage, for the item, but ignore some materials if set, and the item isn't at full durability
Set<Material> ignoredSalvage = BlacksmithPlugin.getInstance().getGlobalScrapperSettings().getIgnoredSalvage(
item.getType());
// Don't ignore salvage for fully repaired items
if (ignoredSalvage == null || ItemHelper.getDamage(item) == 0) {
ignoredSalvage = new HashSet<>();
}
return SalvageHelper.getSalvage(BlacksmithPlugin.getInstance().getServer(), item, ignoredSalvage, extended);
}
}

View File

@ -8,7 +8,6 @@ import org.bukkit.inventory.CraftingRecipe;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.SmithingTransformRecipe;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
@ -46,7 +45,11 @@ public final class ItemHelper {
* @return <p>The max durability of the item</p>
*/
public static short getMaxDurability(@NotNull ItemStack itemStack) {
return itemStack.getType().getMaxDurability();
if (itemStack.getItemMeta() instanceof Damageable) {
return itemStack.getType().getMaxDurability();
} else {
return 0;
}
}
/**
@ -56,12 +59,11 @@ public final class ItemHelper {
* @return <p>The durability of the item</p>
*/
public static short getDurability(@NotNull ItemStack itemStack) {
Damageable damageable = (Damageable) itemStack.getItemMeta();
int maxDurability = getMaxDurability(itemStack);
if (damageable != null) {
if (itemStack.getItemMeta() instanceof Damageable damageable) {
int maxDurability = getMaxDurability(itemStack);
return (short) (maxDurability - damageable.getDamage());
} else {
return (short) maxDurability;
return 0;
}
}
@ -72,8 +74,7 @@ public final class ItemHelper {
* @return <p>The damage done to the item</p>
*/
public static short getDamage(@NotNull ItemStack itemStack) {
Damageable damageable = (Damageable) itemStack.getItemMeta();
if (damageable != null) {
if (itemStack.getItemMeta() instanceof Damageable damageable) {
return (short) damageable.getDamage();
} else {
return 0;
@ -173,26 +174,49 @@ public final class ItemHelper {
* @return <p>True if the item can be salvaged</p>
*/
public static boolean isSalvageable(@NotNull Server server, @NotNull ItemStack item) {
for (Recipe recipe : server.getRecipesFor(item)) {
// Only crafting recipes, and smithing transform recipes (diamond -> netherite) are allowed.
if (recipe instanceof CraftingRecipe || recipe instanceof SmithingTransformRecipe &&
item.getAmount() >= recipe.getResult().getAmount()) {
for (Recipe recipe : server.getRecipesFor(new ItemStack(item.getType(), item.getAmount()))) {
// Only crafting recipes are allowed.
if ((recipe instanceof CraftingRecipe) && item.getAmount() >= recipe.getResult().getAmount()) {
return true;
}
}
return false;
}
/**
* Gets the amount of an item that's required to salvage that item
*
* @param server <p>The server to get recipes from</p>
* @param item <p>The item to check</p>
* @return <p>The number of items required for salvage, or -1 if the recipe was not found</p>
*/
public static int getRequiredAmountForSalvage(@NotNull Server server, @NotNull ItemStack item) {
for (Recipe recipe : server.getRecipesFor(new ItemStack(item.getType(), item.getAmount()))) {
// Only crafting recipes are allowed.
if (recipe instanceof CraftingRecipe) {
return recipe.getResult().getAmount();
}
}
return -1;
}
/**
* Gets all materials matching the given material wildcard
*
* @param materialName <p>The material name or material wildcard to match</p>
* @param extended <p>Whether to use an extended match, allowing any material</p>
* @return <p>The matched material(s)</p>
*/
public static @NotNull List<Material> getWildcardMatch(@NotNull String materialName) {
public static @NotNull List<Material> getWildcardMatch(@NotNull String materialName, boolean extended) {
String search = InputParsingHelper.regExIfy(materialName);
List<Material> materials = new ArrayList<>();
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
List<Material> all;
if (extended) {
all = List.of(Material.values());
} else {
all = ItemHelper.getAllReforgeAbleMaterials();
}
for (Material material : all) {
if (material.name().matches(search)) {
materials.add(material);
}
@ -249,7 +273,7 @@ public final class ItemHelper {
}
/**
* Replaces smoth presets in the given list of strings
* Replaces smith presets in the given list of strings
*
* @param stringList <p>The value specified by a user</p>
* @return <p>The value with smith presets replaced</p>

View File

@ -22,6 +22,8 @@ import java.util.Random;
*/
public final class SalvageHelper {
private static final Random random = new Random();
/**
* Gets the sum of all enchantment levels for the given item
*
@ -44,19 +46,22 @@ public final class SalvageHelper {
* @param server <p>The server to get recipes from</p>
* @param salvagedItem <p>The item stack to salvage</p>
* @param ignoredSalvage <p>Any material which should not be returned as part of the salvage.</p>
* @param extended <p>Whether to enable extended salvage, ignoring the repairable restriction</p>
* @return <p>The items to return to the user, or null if not salvageable</p>
*/
public static @Nullable List<ItemStack> getSalvage(@NotNull Server server, @Nullable ItemStack salvagedItem,
@NotNull Collection<Material> ignoredSalvage) {
@NotNull Collection<Material> ignoredSalvage, boolean extended) {
if (salvagedItem == null || salvagedItem.getAmount() < 1 ||
!ItemHelper.isRepairable(salvagedItem)) {
(!extended && !ItemHelper.isRepairable(salvagedItem))) {
return null;
}
for (Recipe recipe : server.getRecipesFor(salvagedItem)) {
List<ItemStack> salvage = getRecipeSalvage(recipe, salvagedItem, ignoredSalvage);
if (salvage != null) {
return salvage;
for (Recipe recipe : server.getRecipesFor(new ItemStack(salvagedItem.getType(), salvagedItem.getAmount()))) {
if (recipe instanceof ShapedRecipe || recipe instanceof ShapelessRecipe) {
List<ItemStack> salvage = getRecipeSalvage(recipe, salvagedItem, ignoredSalvage);
if (salvage != null && !salvage.isEmpty()) {
return salvage;
}
}
}
@ -88,15 +93,7 @@ public final class SalvageHelper {
//Purge any ignored salvage to only calculate salvage using the remaining items
ingredients.removeIf((item) -> ignoredSalvage.contains(item.getType()));
Random random = new Random();
//Make sure to give salvage for all items if a stack > 1 is provided
List<ItemStack> allSalvage = new ArrayList<>();
for (int i = 0; i < salvagedItem.getAmount(); i++) {
allSalvage.addAll(getSalvage(copyItems(ingredients), salvagedItem, random));
}
return combineStacks(allSalvage);
return combineStacks(getSalvage(copyItems(ingredients), salvagedItem));
}
/**
@ -120,21 +117,30 @@ public final class SalvageHelper {
*
* @param recipeItems <p>All items required for crafting the item to salvage</p>
* @param salvagedItem <p>The item to be salvaged</p>
* @param random <p>The randomness generator to use</p>
* @return <p>The items to be returned to the user as salvage</p>
*/
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));
@NotNull
private static List<ItemStack> getSalvage(@NotNull List<ItemStack> recipeItems,
@NotNull ItemStack salvagedItem) {
int durability = ItemHelper.getDurability(salvagedItem);
int maxDurability = ItemHelper.getMaxDurability(salvagedItem);
// Prevent divide by zero for items that don't have a set max durability
if (maxDurability == 0) {
maxDurability = 1;
durability = 1;
}
double percentageRemaining = (double) durability / maxDurability;
int totalItems = totalItemAmount(recipeItems);
//Get the amount of recipe items to be returned
int itemsToReturn = (int) Math.floor(percentageRemaining * totalItems);
int bound = recipeItems.size();
List<ItemStack> salvage = new ArrayList<>();
List<ItemStack> salvage = new ArrayList<>();
for (int i = 0; i < itemsToReturn; i++) {
int itemIndex = random.nextInt(bound);
int itemIndex = SalvageHelper.random.nextInt(bound);
ItemStack itemStack = recipeItems.get(itemIndex);
//Make sure to never give more of one item than the amount which exists in the recipe
@ -192,7 +198,8 @@ 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 @NotNull List<ItemStack> getIngredients(@NotNull ShapedRecipe shapedRecipe) {
@NotNull
private static 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,4 +5,5 @@ scrapper.defaults.delaysInSeconds.maximum=scrapper.defaults.maxSalvageWaitTimeSe
scrapper.defaults.delaysInSeconds.salvageCoolDown=scrapper.defaults.salvageCoolDownSeconds
blacksmith.defaults.delaysInSeconds.minimum=blacksmith.defaults.minReforgeWaitTimeSeconds
blacksmith.defaults.delaysInSeconds.maximum=blacksmith.defaults.maxReforgeWaitTimeSeconds
blacksmith.defaults.delaysInSeconds.reforgeCoolDown=blacksmith.defaults.reforgeCoolDownSeconds
blacksmith.defaults.delaysInSeconds.reforgeCoolDown=blacksmith.defaults.reforgeCoolDownSeconds
blacksmith.defaults.enchantmentBlocklist=blacksmith.defaults.enchantmentBlockList

View File

@ -48,7 +48,7 @@ blacksmith:
reforgeAbleItems: [ ]
# The enchantments a blacksmith is denied from applying to an item. Disable anything you find too op or annoying.
enchantmentBlocklist: [ "binding_curse", "mending", "vanishing_curse" ]
enchantmentBlockList: [ "binding_curse", "mending", "vanishing_curse" ]
# The chance to fail reforging an item, which only repairs the item a tiny bit or not at all (0-100)
failReforgeChance: 10 # Default = 10%
@ -114,7 +114,7 @@ blacksmith:
# Settings for the scrapper trait
scrapper:
# The settings which apply to all Scrapper NPCs. These can also be changed using the /scrapperconfig command
# The settings which apply to all Scrapper NPCs. These can also be changed using the /scrapperConfig command
global:
# Exact time displays the exact number of seconds and minutes remaining as part of the scrapping cool-down and
# scrapping delay messages, instead of just vaguely hinting at the remaining time.
@ -123,12 +123,16 @@ scrapper:
# Whether enchanted salvaged items should return some amount of exp upon salvage
giveExperience: true
# Items ignored during salvage calculation. This follows the format: "MATERIAL[,MATERIAL2][,MATERIAL3]:IGNORED", so
# the material or materials listed will ignore the material specified after the ":" when calculating salvage
# Items ignored during salvage calculation. This follows the format:
# "MATERIAL[;MATERIAL2][;MATERIAL3]:IGNORED_MATERIAL[;IGNORED_MATERIAL2]",
# so the material or materials listed will ignore the material specified after the ":" when calculating salvage
# (* matches any character). This causes the player to lose some items during salvaging, but can prevent cases
# where a diamond pickaxe is salvaged and only sticks are returned.
ignoredSalvage:
- "*_SHOVEL,*_PICKAXE,*_AXE,*_HOE,*_SWORD:STICK"
- "*_SHOVEL;*_PICKAXE;*_AXE;*_HOE;*_SWORD:STICK"
# The cost of using the scrapper
basePrice: 0
# The settings which are set to any new scrapper NPC. To change any of these settings for an existing NPC, you must
# change the Citizens NPC file, or use the /scrapper command

View File

@ -13,7 +13,7 @@ commands:
permission: blacksmith.edit
usage: /<command> <option> [new value]
description: Used for configuring the selected blacksmith NPC
blacksmithconfig:
blacksmithConfig:
permission: blacksmith.admin
usage: /<command> <option/reload> [new value]
description: Used for configuring default blacksmith settings, or global blacksmith settings
@ -21,7 +21,7 @@ commands:
permission: blacksmith.edit
usage: /<command> <option> [new value]
description: Used for configuring the selected scrapper NPC
scrapperconfig:
scrapperConfig:
permission: blacksmith.admin
usage: /<command> <option/reload> [new value]
description: Used for configuring default scrapper settings, or global scrapper settings

View File

@ -1,5 +1,5 @@
# The english translation of internal strings. To add your own language, copy everything below, and change "en" to your
# own language's code, and change each string. Afterwards, copy this file to Blacksmith's plugin folder, and change the
# own language's code, and change each string. Afterward, copy this file to Blacksmith's plugin folder, and change the
# language in config.yml to your language's language code.
en:
# The format used to display when a setting's value has been changed