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

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

View File

@ -26,41 +26,57 @@ fee. Costs are highly customizable.
To create a new blacksmith, simply add the blacksmith trait to an NPC by selecting it with `/npc select`, and then using
`/trait add Blacksmith` (See Citizens' documentation for more details).
Right-clicking the NPC will tell you if the currently held item is repairable by the blacksmith. If it is, the
blacksmith should give a price quote. Right-clicking again starts the repair. The item should be given back or dropped
after a random delay according to the set limits.
To create a new scrapper, simply add the scrapper trait to an NPC by selecting it with `/npc select`, and then using
`/trait add Scrapper` (See Citizens' documentation for more details).
While costs are always set globally (no blacksmith can do the same job for cheaper), the blacksmith's messages,
cool-down between each reforge, whether the item is dropped or given, the chance of failing or adding an enchantment,
the maximum number of added enchantments, max and min delays, the length of the cool-down and which items the blacksmith
is able to reforge can be changed individually.
Right-clicking the NPC will tell you if the currently held item is repairable by the blacksmith / salvageable by the
scrapper. If it is, the blacksmith / scrapper should give a price quote. Right-clicking again starts the repair /
salvage. The item should be given back or dropped after a random delay according to the set limits.
While costs are always set globally (no blacksmith or scrapper can do the same job for cheaper), the blacksmith /
scrapper's messages, cool-down between each reforge / salvage, whether the item is dropped or given, the chance of
failing or adding an enchantment, the maximum number of added enchantments, max and min delays, the length of the
cool-down and which items the blacksmith is able to reforge / salvage can be changed individually.
Also note: As a change from the original plugin, unless a value for an NPC has been explicitly set for that NPC, it will
mirror the values set in config.yml. This also means that configuration values aren't populated automatically in
citizen's NPC save file. While you can manually set the values using the same keys as in config.yml, you should use the
/blacksmith command when possible.
`/blacksmith` or `/scrapper` command when possible.
### Special behavior
In addition to just being able to repair items, blacksmiths have some random features which can be cool or annoying:
In addition to just being able to repair items, blacksmiths / scrappers have some random features which can be cool or
annoying:
- There is a chance that blacksmiths fail to repair an item, leaving it at about the same durability as before. Use
- There is a chance that blacksmiths / scrappers fail to repair an item, leaving it at about the same durability as
before (scrappers with `extendedSalvageEnabled` turned on might cause items in a stack to be lost). Use
failReforgeChance to control the chance. Set it to 0 to remove the feature.
- There is a chance a blacksmith may add an enchantment to a reforged item. You can control the probability using
extraEnchantmentChance, and set the maximum number of enchantments using maxEnchantments. EnchantmentBlocklist can be
extraEnchantmentChance, and set the maximum number of enchantments using maxEnchantments. EnchantmentBlockList can be
used to block any enchantments you don't want to randomly grant.
### Scrapper basics
A scrapper will produce salvage for a damage-able item by calculating the amount of items returned based on items in the
recipe, and the percentage of durability left on the item. To avoid returning relatively worthless items instead of
valuable items, `ignoredSalvage` can be configured. If the item is fully repaired, the worthless items will be returned
as well, but otherwise, only the valuable items are considered as possible salvage. A scrapper will by default only
salvage damage-able items (same as blacksmiths), but enabling `extendedSalvageEnabled` for a scrapper will allow it to
salvage any crafting table recipe. Note that to salvage for example planks into wood, four wood will be taken.
When an item is salvaged, EXP will be returned based on enchantments on the item.
## Commands
| Command | Arguments | Description |
|-------------------|-------------------------------|----------------------------------------------------------------------------------------------|
| /blacksmith | \<option> \[new-value] | Changes a configuration option for the selected blacksmith (use Citizens' /npc select first) |
| /blacksmithconfig | \<reload/option> \[new-value] | Changes a default/global blacksmith configuration value |
| /blacksmithConfig | \<reload/option> \[new-value] | Changes a default/global blacksmith configuration value |
| /scrapper | \<option> \[new-value] | Changes a configuration option for the selected scrapper (use Citizens' /npc select first) |
| /scrapperconfig | \<reload/option> \[new-value] | Changes a default/global scrapper configuration value |
| /scrapperConfig | \<reload/option> \[new-value] | Changes a default/global scrapper configuration value |
| /preset | \<preset>\[:filter] | Displays all materials included in the given preset, after applying the filter if set |
For /blacksmith, /blacksmithconfig, /scrapper and /scrapperconfig, if a new value isn't specified, a description of the
For /blacksmith, /blacksmithConfig, /scrapper and /scrapperConfig, if a new value isn't specified, a description of the
configuration option, and the current value, is displayed instead.
For /blacksmith or /scrapper, using -1 or null as the value will clear a custom value, making the NPC use the default
@ -171,15 +187,15 @@ All currently supported presets, and available filters for each preset:
| failReforgeRemovesEnchantments | true/false | Whether a failed reforge should remove or downgrade all enchantments on the item. |
| extraEnchantmentChance | 0-100 | The chance of the blacksmith adding an enchantment to an item. |
| maxEnchantments | 0-10 | The maximum number of different enchantments a blacksmith can add. |
| maxReforgeDelay | 0-3600 | The maximum number of seconds a player needs to wait for an item to be repaired. |
| minReforgeDelay | 0-3600 | The minimum number of seconds a player needs to wait for an item to be repaired. |
| reforgeCoolDown | 0-3600 | The cool-down, in seconds, a player has to wait between each time they use one specific blacksmith. |
| maxReforgeWaitTimeSeconds | 0-3600 | The maximum number of seconds a player needs to wait for an item to be repaired. |
| minReforgeWaitTimeSeconds | 0-3600 | The minimum number of seconds a player needs to wait for an item to be repaired. |
| reforgeCoolDownSeconds | 0-3600 | The cool-down, in seconds, a player has to wait between each time they use one specific blacksmith. |
| reforgeAbleItems | DIAMOND_LEGGINGS,GOLD-pickaxe,bow, etc. | Specifies which items this blacksmith is able to reforge. If set to "" or null, all normally repairable items can be repaired. If set to a list of items, only the items specified can be repaired. Some presets have been included for ease of use. Use a preset by specifying "preset:sword-smith" instead of a material such as "gold-pickaxe". |
| blacksmithTitle | text string | The title displayed as part of the message explaining that a blacksmith doesn't recognize a player's held item |
| enchantmentBlocklist | string list | A string list of all enchantments a blacksmith should not be allowed to add to items. |
| enchantmentBlockList | string list | A string list of all enchantments a blacksmith should not be allowed to add to items. |
| reforgeAnvils | true/false | Whether to allow the blacksmith to reforge anvils. If enabled, chipped and damaged anvils will be replaced with a normal anvil. |
#### Blacksmith per-npc messages (with default values set in config.yml)
#### Messages
| Message Key | Explanation |
|--------------------------|-----------------------------------------------------------------------------------------------------------------|
@ -195,6 +211,46 @@ All currently supported presets, and available filters for each preset:
| successMessage | The message displayed when a blacksmith successfully repairs an item |
| notDamagedMessage | The message displayed if a player tries to reforge an item with full durability |
### Scrapper global-only options
| Key | Value type | Description |
|----------------|----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| basePrice | positive decimal number | The cost of using a scrapper |
| showExactTime | true/false | If true, scrappers will display exact time remaining in minutes and seconds, instead of vague expressions |
| giveExperience | true/false | If true, each enchantment level on the salvaged item will give one EXP level as salvage |
| ignoredSalvage | TARGET_MATERIAL:IGNORED_MATERIAL | The items that should be ignored when calculating partial salvage. Because receiving just the sticks when salvaging a diamond pickaxe is kind of sad, this allows specifying for example: `*_SHOVEL;*_PICKAXE;*_AXE;*_HOE;*_SWORD:STICK` (the default) for ignoring sticks in salvage for shovels, pickaxes, axes, hoes and swords. A `:` character splits selected items and the ignored salvage. Different item specifications are split by a `;` character. Use `,` to split separate ignored salvages, like: `SHIELD:STICK,BOW_STRING` |
### Scrapper per-npc (with default values set in config.yml)
#### Configuration values
| Key | Value type | Description |
|---------------------------|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| dropItem | true/false | Whether the scrapper should drop the repaired item on the ground (instead of putting it into the player's inventory). |
| failSalvageChance | 0-100 | The chance of the scrapper failing to salvage an item, either further damaging the item, partly repairing the item or causing some items to disappear. |
| salvageAbleItems | DIAMOND_LEGGINGS,GOLD-pickaxe,bow, etc. | Specifies which items this scrapper is able to salvage. If set to "" or null, all normally repairable items can be salvaged. If set to a list of items, only the items specified can be salvaged. Some presets have been included for ease of use. Use a preset by specifying "preset:sword-smith" instead of a material such as "gold-pickaxe". |
| maxSalvageWaitTimeSeconds | 0-3600 | The maximum number of seconds a player needs to wait for an item to be salvaged. |
| minSalvageWaitTimeSeconds | 0-3600 | The minimum number of seconds a player needs to wait for an item to be salvaged. |
| salvageCoolDownSeconds | 0-3600 | The cool-down, in seconds, a player has to wait between each time they use one specific scrapper. |
| scrapperTitle | text string | The title displayed as part of the message explaining that a scrapper doesn't recognize a player's held item |
| extendedSalvageEnabled | true/false | Whether to enable the extended salvage behavior for this scrapper. As long as it is allowed by salvageAbleItems and it can be crafted in a crafting table, it can be salvaged. This includes things like four planks salvaged into wood. |
#### Messages
| Message Key | Explanation |
|-----------------------------|---------------------------------------------------------------------------------------------------------------|
| busyPlayerMessage | The message displayed when the scrapper is serving another player |
| busySalvageMessage | The message displayed when the scrapper is busy salvaging an item |
| coolDownUnexpiredMessage | The message displayed when the player has to wait for the cool-down to expire before using the scrapper again |
| invalidItemMessage | The message displayed when a scrapper is presented an item which it cannot salvage |
| tooDamagedForSalvageMessage | The message displayed when a scrapper is presented with an item too damaged to produce salvage. |
| successSalvagedMessage | The message displayed when a scrapper successfully repairs an item |
| failSalvageMessage | The message displayed when a scrapper fails to salvage an item |
| itemChangedMessage | The message displayed when a player changes their item after being shown the salvage cost |
| startSalvageMessage | The message displayed when a scrapper starts salvaging an item |
| insufficientFundsMessage | The message displayed when a player is unable to pay for scrapping an item |
| costMessage | The message displayed when telling a player about the cost of scrapping an item |
## Language customization
All strings, even time units, are customizable. If you place a strings.yml file in the plugin folder, it will take

20
pom.xml
View File

@ -75,7 +75,7 @@
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<version>1.7.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -119,7 +119,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
@ -128,6 +128,16 @@
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<relocations>
<relocation>
<pattern>net.knarcraft.knarlib</pattern>
<shadedPattern>net.knarcraft.blacksmith.lib.knarlib</shadedPattern>
</relocation>
<relocation>
<pattern>org.jetbrains.annotations</pattern>
<shadedPattern>net.knarcraft.blacksmith.lib.annotations</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>net.knarcraft:knarlib</artifact>
@ -135,6 +145,12 @@
<include>net/knarcraft/knarlib/**</include>
</includes>
</filter>
<filter>
<artifact>org.jetbrains:annotations</artifact>
<includes>
<include>org/jetbrains/annotations/**</include>
</includes>
</filter>
<filter>
<excludes>
<exclude>*.MF</exclude>

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) {
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();
if (itemStack.getItemMeta() instanceof Damageable damageable) {
int maxDurability = getMaxDurability(itemStack);
if (damageable != null) {
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,21 +46,24 @@ 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)) {
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) {
if (salvage != null && !salvage.isEmpty()) {
return salvage;
}
}
}
return null;
}
@ -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

@ -6,3 +6,4 @@ scrapper.defaults.delaysInSeconds.salvageCoolDown=scrapper.defaults.salvageCoolD
blacksmith.defaults.delaysInSeconds.minimum=blacksmith.defaults.minReforgeWaitTimeSeconds
blacksmith.defaults.delaysInSeconds.maximum=blacksmith.defaults.maxReforgeWaitTimeSeconds
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

View File

@ -16,7 +16,9 @@ import java.util.List;
*/
public class CustomServerMock extends ServerMock {
public @NotNull List<Recipe> getRecipesFor(@NotNull ItemStack itemStack) {
@Override
@NotNull
public List<Recipe> getRecipesFor(@NotNull ItemStack itemStack) {
List<Recipe> validRecipes = new ArrayList<>();
if (itemStack.getType() == Material.DIAMOND_PICKAXE) {
ShapedRecipe recipe = new ShapedRecipe(NamespacedKey.minecraft("diamond_pickaxe"), itemStack);
@ -24,6 +26,12 @@ public class CustomServerMock extends ServerMock {
recipe.setIngredient('d', Material.DIAMOND);
recipe.setIngredient('s', Material.STICK);
validRecipes.add(recipe);
} else if (itemStack.getType() == Material.TNT) {
ShapedRecipe recipe = new ShapedRecipe(NamespacedKey.minecraft("tnt"), itemStack);
recipe.shape("gsg", "sgs", "gsg");
recipe.setIngredient('g', Material.GUNPOWDER);
recipe.setIngredient('s', Material.SAND);
validRecipes.add(recipe);
}
return validRecipes;
}

View File

@ -86,7 +86,7 @@ public class ItemHelperTest {
@Test
public void getAllReforgeAbleMaterialsTest() {
List<Material> materials = ItemHelper.getAllReforgeAbleMaterials();
assertTrue(materials.size() > 0);
assertFalse(materials.isEmpty());
for (Material material : materials) {
assertTrue(ItemHelper.getMaxDurability(new ItemStack(material, 1)) > 0);

View File

@ -41,14 +41,14 @@ public class SalvageHelperTest {
@Test
public void getNullForInvalidItemTest() {
//Assert that a non-reforge-able item will return null
assertNull(SalvageHelper.getSalvage(server, new ItemStack(Material.POTATO, 1), new ArrayList<>()));
assertNull(SalvageHelper.getSalvage(server, new ItemStack(Material.POTATO, 1), new ArrayList<>(), false));
}
@Test
public void getNullForLessThanOneItemTest() {
//Assert that 0 or 1 items will return null
assertNull(SalvageHelper.getSalvage(server, new ItemStack(Material.IRON_AXE, 0), new ArrayList<>()));
assertNull(SalvageHelper.getSalvage(server, new ItemStack(Material.IRON_SWORD, -1), new ArrayList<>()));
assertNull(SalvageHelper.getSalvage(server, new ItemStack(Material.IRON_AXE, 0), new ArrayList<>(), false));
assertNull(SalvageHelper.getSalvage(server, new ItemStack(Material.IRON_SWORD, -1), new ArrayList<>(), false));
}
@Test
@ -58,7 +58,7 @@ public class SalvageHelperTest {
expectedSalvage.add(new ItemStack(Material.STICK, 2));
ItemStack itemToSalvage = new ItemStack(Material.DIAMOND_PICKAXE, 1);
//Note: Conversion to sets makes sure the order doesn't matter
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, new ArrayList<>());
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, new ArrayList<>(), false);
if (salvage == null) {
fail();
} else {
@ -67,13 +67,13 @@ public class SalvageHelperTest {
}
@Test
public void getSeveralFullSalvageTest() {
public void getExtendedSalvageTest() {
Set<ItemStack> expectedSalvage = new HashSet<>();
expectedSalvage.add(new ItemStack(Material.DIAMOND, 21));
expectedSalvage.add(new ItemStack(Material.STICK, 14));
ItemStack itemToSalvage = new ItemStack(Material.DIAMOND_PICKAXE, 7);
expectedSalvage.add(new ItemStack(Material.GUNPOWDER, 5));
expectedSalvage.add(new ItemStack(Material.SAND, 4));
ItemStack itemToSalvage = new ItemStack(Material.TNT, 1);
//Note: Conversion to sets makes sure the order doesn't matter
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, new ArrayList<>());
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, new ArrayList<>(), true);
if (salvage == null) {
fail();
} else {
@ -93,7 +93,7 @@ public class SalvageHelperTest {
damageable.setDamage(100);
}
itemToSalvage.setItemMeta(meta);
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, new ArrayList<>());
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, new ArrayList<>(), false);
//Assert that some items are given
assertNotEquals(salvage, new ArrayList<>());
//Assert that a damaged item won't give full salvage
@ -113,7 +113,7 @@ public class SalvageHelperTest {
damageable.setDamage(100);
}
itemToSalvage.setItemMeta(meta);
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, ignoredSalvage);
List<ItemStack> salvage = SalvageHelper.getSalvage(server, itemToSalvage, ignoredSalvage, false);
//Assert that some items are given
assertNotEquals(salvage, new ArrayList<>());
//Assert that a damaged diamond pickaxe with sticks ignored returns 2 diamonds a salvage