Repair rewrite continues

This commit is contained in:
nossr50 2019-06-19 23:28:11 -07:00
parent 458e198fdb
commit b41a30fa26
25 changed files with 511 additions and 155 deletions

11
pom.xml
View File

@ -216,10 +216,15 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot</artifactId>
<version>1.14.2-R0.1-SNAPSHOT</version> <version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>org.spigotmc</groupId>-->
<!-- <artifactId>spigot-api</artifactId>-->
<!-- <version>1.14.2-R0.1-SNAPSHOT</version>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>com.sk89q.worldguard</groupId> <groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-core</artifactId> <artifactId>worldguard-core</artifactId>

View File

@ -629,7 +629,6 @@ public final class ExperienceAPI {
* @param skillType The skill to get the level for * @param skillType The skill to get the level for
* @return the level of a given skill * @return the level of a given skill
* @throws InvalidSkillException if the given skill is not valid * @throws InvalidSkillException if the given skill is not valid
* @deprecated Use getLevel(Player player, PrimarySkillType skillType) instead
*/ */
@Deprecated @Deprecated
public static int getLevel(Player player, String skillType) { public static int getLevel(Player player, String skillType) {

View File

@ -0,0 +1,19 @@
package com.gmail.nossr50.bukkit;
import com.gmail.nossr50.datatypes.items.BukkitMMOItem;
import com.gmail.nossr50.util.nbt.RawNBT;
/**
* Used to convert or construct platform independent types into Bukkit types
*/
public class BukkitFactory {
/**
* Creates a BukkitMMOItem which contains Bukkit implementations for the type MMOItem
* @return a new BukkitMMOItem
*/
public static BukkitMMOItem createBukkitMMOItem(String namespaceKey, int amount, RawNBT rawNBT) {
return new BukkitMMOItem(namespaceKey, amount, rawNBT);
}
}

View File

@ -39,7 +39,7 @@ import com.gmail.nossr50.config.hocon.skills.ranks.SkillRankProperty;
import com.gmail.nossr50.config.hocon.skills.repair.ConfigRepair; import com.gmail.nossr50.config.hocon.skills.repair.ConfigRepair;
import com.gmail.nossr50.skills.repair.RepairCost; import com.gmail.nossr50.skills.repair.RepairCost;
import com.gmail.nossr50.skills.repair.RepairTransaction; import com.gmail.nossr50.skills.repair.RepairTransaction;
import com.gmail.nossr50.skills.repair.RepairWildcard; import com.gmail.nossr50.datatypes.items.ItemWildcards;
import com.gmail.nossr50.config.hocon.skills.salvage.ConfigSalvage; import com.gmail.nossr50.config.hocon.skills.salvage.ConfigSalvage;
import com.gmail.nossr50.config.hocon.skills.smelting.ConfigSmelting; import com.gmail.nossr50.config.hocon.skills.smelting.ConfigSmelting;
import com.gmail.nossr50.config.hocon.skills.swords.ConfigSwords; import com.gmail.nossr50.config.hocon.skills.swords.ConfigSwords;
@ -280,7 +280,7 @@ public final class ConfigManager {
customSerializers.registerType(TypeToken.of(PlayerNotificationSettings.class), new PlayerNotificationSerializer()); customSerializers.registerType(TypeToken.of(PlayerNotificationSettings.class), new PlayerNotificationSerializer());
customSerializers.registerType(TypeToken.of(SoundSetting.class), new SoundSettingSerializer()); customSerializers.registerType(TypeToken.of(SoundSetting.class), new SoundSettingSerializer());
customSerializers.registerType(TypeToken.of(ItemStack.class), new ItemStackSerializer()); customSerializers.registerType(TypeToken.of(ItemStack.class), new ItemStackSerializer());
customSerializers.registerType(TypeToken.of(RepairWildcard.class), new RepairWildcardSerializer()); customSerializers.registerType(TypeToken.of(ItemWildcards.class), new RepairWildcardSerializer());
customSerializers.registerType(TypeToken.of(RepairCost.class), new RepairCostSerializer()); customSerializers.registerType(TypeToken.of(RepairCost.class), new RepairCostSerializer());
customSerializers.registerType(TypeToken.of(RepairTransaction.class), new RepairTransactionSerializer()); customSerializers.registerType(TypeToken.of(RepairTransaction.class), new RepairTransactionSerializer());
} }

View File

@ -1,6 +1,6 @@
package com.gmail.nossr50.config.hocon.serializers; package com.gmail.nossr50.config.hocon.serializers;
import com.gmail.nossr50.skills.repair.RepairWildcard; import com.gmail.nossr50.datatypes.items.ItemWildcards;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.ValueType; import ninja.leaping.configurate.ValueType;
@ -12,30 +12,30 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Set; import java.util.Set;
public class RepairWildcardSerializer implements TypeSerializer<RepairWildcard> { public class RepairWildcardSerializer implements TypeSerializer<ItemWildcards> {
private static final String WILDCARD_IDENTIFIER_NAME = "Wildcard-Identifier-Name"; private static final String WILDCARD_IDENTIFIER_NAME = "Wildcard-Identifier-Name";
private static final String MATCHING_ITEMS = "Matching-Items"; private static final String MATCHING_ITEMS = "Matching-Items";
@Nullable @Nullable
@Override @Override
public RepairWildcard deserialize(@NonNull TypeToken<?> type, @NonNull ConfigurationNode value) throws ObjectMappingException { public ItemWildcards deserialize(@NonNull TypeToken<?> type, @NonNull ConfigurationNode value) throws ObjectMappingException {
String wildCardName = value.getNode(WILDCARD_IDENTIFIER_NAME).getValue(TypeToken.of(String.class)); String wildCardName = value.getNode(WILDCARD_IDENTIFIER_NAME).getValue(TypeToken.of(String.class));
if(value.getNode(WILDCARD_IDENTIFIER_NAME).getNode(MATCHING_ITEMS).getValueType() != ValueType.NULL) { if(value.getNode(WILDCARD_IDENTIFIER_NAME).getNode(MATCHING_ITEMS).getValueType() != ValueType.NULL) {
Set<ItemStack> matchCandidates = value.getNode(WILDCARD_IDENTIFIER_NAME).getNode(MATCHING_ITEMS).getValue(new TypeToken<Set<ItemStack>>() {}); Set<ItemStack> matchCandidates = value.getNode(WILDCARD_IDENTIFIER_NAME).getNode(MATCHING_ITEMS).getValue(new TypeToken<Set<ItemStack>>() {});
return new RepairWildcard(wildCardName, matchCandidates); return new ItemWildcards(wildCardName, matchCandidates);
} }
return null; return null;
} }
@Override @Override
public void serialize(@NonNull TypeToken<?> type, @Nullable RepairWildcard obj, @NonNull ConfigurationNode value) throws ObjectMappingException { public void serialize(@NonNull TypeToken<?> type, @Nullable ItemWildcards obj, @NonNull ConfigurationNode value) throws ObjectMappingException {
value.getNode(WILDCARD_IDENTIFIER_NAME).setValue(obj.getWildcardName()); value.getNode(WILDCARD_IDENTIFIER_NAME).setValue(obj.getWildcardName());
value.getNode(WILDCARD_IDENTIFIER_NAME).getNode(MATCHING_ITEMS).setValue(obj.getMatchingItems()); value.getNode(WILDCARD_IDENTIFIER_NAME).getNode(MATCHING_ITEMS).setValue(obj.getItemTargets());
} }
} }

View File

@ -24,7 +24,7 @@ public class RepairableSerializer implements TypeSerializer<Repairable> {
private static final String STRICT_MATCH_ITEM = "Strict-Match-Item"; private static final String STRICT_MATCH_ITEM = "Strict-Match-Item";
private static final String STRICT_MATCHING_REPAIR_TRANSACTION = "Strict-Matching-Repair-Transaction"; private static final String STRICT_MATCHING_REPAIR_TRANSACTION = "Strict-Matching-Repair-Transaction";
private static final String REPAIR_COUNT = "Repair-Count"; private static final String REPAIR_COUNT = "Repair-Count";
private static final String NBT = "NBT"; // private static final String NBT = "NBT";
private static final String PERMISSION = "Permission"; private static final String PERMISSION = "Permission";
private static final String MINIMUM_LEVEL = "Minimum-Level"; private static final String MINIMUM_LEVEL = "Minimum-Level";
@ -34,7 +34,7 @@ public class RepairableSerializer implements TypeSerializer<Repairable> {
RepairableBuilder builder = new RepairableBuilder(itemStack) RepairableBuilder builder = new RepairableBuilder(itemStack)
.repairTransaction(value.getNode(REPAIR_TRANSACTION).getValue(TypeToken.of(RepairTransaction.class))) .repairTransaction(value.getNode(REPAIR_TRANSACTION).getValue(TypeToken.of(RepairTransaction.class)))
.strictMatchingItem(value.getNode(STRICT_MATCH_ITEM).getValue(TypeToken.of(Boolean.class))) .strictMatchingItem(value.getNode(STRICT_MATCH_ITEM).getValue(TypeToken.of(Boolean.class)))
.strictMatchingRepairTransaction(value.getNode(STRICT_MATCHING_REPAIR_TRANSACTION).getValue(TypeToken.of(Boolean.class))) // .strictMatchingRepairTransaction(value.getNode(STRICT_MATCHING_REPAIR_TRANSACTION).getValue(TypeToken.of(Boolean.class)))
.baseXP(value.getNode(BASE_XP).getValue(TypeToken.of(Integer.class))) .baseXP(value.getNode(BASE_XP).getValue(TypeToken.of(Integer.class)))
.repairCount(value.getNode(REPAIR_COUNT).getValue(TypeToken.of(Integer.class))); .repairCount(value.getNode(REPAIR_COUNT).getValue(TypeToken.of(Integer.class)));
@ -58,7 +58,7 @@ public class RepairableSerializer implements TypeSerializer<Repairable> {
value.getNode(ITEM).setValue(obj.getItem()); value.getNode(ITEM).setValue(obj.getItem());
value.getNode(REPAIR_TRANSACTION).setValue(obj.getRepairTransaction()); value.getNode(REPAIR_TRANSACTION).setValue(obj.getRepairTransaction());
value.getNode(STRICT_MATCH_ITEM).setValue(obj.isStrictMatchingItem()); value.getNode(STRICT_MATCH_ITEM).setValue(obj.isStrictMatchingItem());
value.getNode(STRICT_MATCHING_REPAIR_TRANSACTION).setValue(obj.isStrictMatchingRepairTransaction()); // value.getNode(STRICT_MATCHING_REPAIR_TRANSACTION).setValue(obj.isStrictMatchingRepairTransaction());
value.getNode(BASE_XP).setValue(obj.getBaseXP()); value.getNode(BASE_XP).setValue(obj.getBaseXP());
value.getNode(REPAIR_COUNT).setValue(obj.getRepairCount()); value.getNode(REPAIR_COUNT).setValue(obj.getRepairCount());

View File

@ -4,7 +4,7 @@ import com.gmail.nossr50.config.ConfigConstants;
import com.gmail.nossr50.config.hocon.skills.repair.general.ConfigRepairGeneral; import com.gmail.nossr50.config.hocon.skills.repair.general.ConfigRepairGeneral;
import com.gmail.nossr50.config.hocon.skills.repair.repairmastery.ConfigRepairRepairMastery; import com.gmail.nossr50.config.hocon.skills.repair.repairmastery.ConfigRepairRepairMastery;
import com.gmail.nossr50.config.hocon.skills.repair.subskills.ConfigRepairSubSkills; import com.gmail.nossr50.config.hocon.skills.repair.subskills.ConfigRepairSubSkills;
import com.gmail.nossr50.skills.repair.RepairWildcard; import com.gmail.nossr50.datatypes.items.ItemWildcards;
import com.gmail.nossr50.skills.repair.repairables.Repairable; import com.gmail.nossr50.skills.repair.repairables.Repairable;
import ninja.leaping.configurate.objectmapping.Setting; import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable; import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ -18,7 +18,7 @@ import static org.bukkit.Material.*;
public class ConfigRepair { public class ConfigRepair {
public static final ArrayList<Repairable> CONFIG_REPAIRABLES_DEFAULTS; public static final ArrayList<Repairable> CONFIG_REPAIRABLES_DEFAULTS;
public static final HashSet<RepairWildcard> REPAIR_WILDCARDS_DEFAULTS; public static final HashSet<ItemWildcards> REPAIR_WILDCARDS_DEFAULTS;
// public static final Material[] PLANKS = new Material[]{OAK_PLANKS, BIRCH_PLANKS, DARK_OAK_PLANKS, ACACIA_PLANKS, JUNGLE_PLANKS, SPRUCE_PLANKS}; // public static final Material[] PLANKS = new Material[]{OAK_PLANKS, BIRCH_PLANKS, DARK_OAK_PLANKS, ACACIA_PLANKS, JUNGLE_PLANKS, SPRUCE_PLANKS};
static { static {
@ -28,7 +28,7 @@ public class ConfigRepair {
new ItemStack(BIRCH_PLANKS, 1), new ItemStack(DARK_OAK_PLANKS, 1), new ItemStack(BIRCH_PLANKS, 1), new ItemStack(DARK_OAK_PLANKS, 1),
new ItemStack(ACACIA_PLANKS, 1), new ItemStack(JUNGLE_PLANKS, 1), new ItemStack(ACACIA_PLANKS, 1), new ItemStack(JUNGLE_PLANKS, 1),
new ItemStack(SPRUCE_PLANKS, 1)}); new ItemStack(SPRUCE_PLANKS, 1)});
RepairWildcard planksWildCard = new RepairWildcard("Planks", new HashSet<>(planksList)); ItemWildcards planksWildCard = new ItemWildcards("Planks", new HashSet<>(planksList));
REPAIR_WILDCARDS_DEFAULTS.add(planksWildCard); REPAIR_WILDCARDS_DEFAULTS.add(planksWildCard);
CONFIG_REPAIRABLES_DEFAULTS = new ArrayList<>(); CONFIG_REPAIRABLES_DEFAULTS = new ArrayList<>();
@ -102,7 +102,7 @@ public class ConfigRepair {
private ArrayList<Repairable> configRepairablesList = CONFIG_REPAIRABLES_DEFAULTS; private ArrayList<Repairable> configRepairablesList = CONFIG_REPAIRABLES_DEFAULTS;
@Setting(value = "Z-Repairables-Wildcards", comment = "Used to define an alias that can be matched to several materials.") @Setting(value = "Z-Repairables-Wildcards", comment = "Used to define an alias that can be matched to several materials.")
private HashSet<RepairWildcard> repairWildcards = new HashSet<>(); private HashSet<ItemWildcards> itemWildcards = new HashSet<>();
public ConfigRepairGeneral getRepairGeneral() { public ConfigRepairGeneral getRepairGeneral() {
return repairGeneral; return repairGeneral;
@ -128,7 +128,7 @@ public class ConfigRepair {
return configRepairablesList; return configRepairablesList;
} }
public HashSet<RepairWildcard> getRepairWildcards() { public HashSet<ItemWildcards> getItemWildcards() {
return repairWildcards; return itemWildcards;
} }
} }

View File

@ -0,0 +1,61 @@
package com.gmail.nossr50.datatypes.items;
import com.gmail.nossr50.util.nbt.RawNBT;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class BukkitMMOItem implements MMOItem<ItemStack> {
private ItemStack itemImplementation;
private RawNBT rawNBT;
public BukkitMMOItem(String namespaceKey, int amount, RawNBT rawNBT) throws NullPointerException {
ItemStack itemStack;
Material material = Material.matchMaterial(namespaceKey);
if(material == null) {
throw new NullPointerException("Material for user defined item could not be found in the server software.");
}
itemStack = new ItemStack(material);
//Get default item meta
ItemMeta itemMeta = Bukkit.getItemFactory().getItemMeta(itemStack.getType());
//Set default item meta
itemStack.setItemMeta(itemMeta);
//Set amount
itemStack.setAmount(amount);
//Set item implementation
this.itemImplementation = itemStack;
//Set raw NBT
if(rawNBT != null)
this.rawNBT = rawNBT;
}
@Override
public ItemStack getItemImplementation() {
return itemImplementation;
}
@Override
public String getNamespaceKey() {
return itemImplementation.getType().getKey().toString();
}
@Override
public int getItemAmount() {
return itemImplementation.getAmount();
}
@Override
public RawNBT getRawNBT() {
return rawNBT;
}
}

View File

@ -0,0 +1,13 @@
package com.gmail.nossr50.datatypes.items;
public interface CustomItemMatching {
/**
* Determines whether or not an item matches this one
* Behaviours for matching can vary based on the implementation
* @param otherItem target item to compare itself to
* @return true if this item matches the target item
*/
boolean isMatch(MMOItem otherItem);
}

View File

@ -0,0 +1,62 @@
package com.gmail.nossr50.datatypes.items;
import java.util.HashSet;
/**
* This type contains data and rules which govern equating equivalency between one item and another in Minecraft.
*
* In mcMMO it is sometimes needed to match one item to another, but items contain a lot of metadata
* Some of this metadata is important, some of it isn't, and whether something is important or not when
* considering two items to be similar enough to be considered matching items is not strictly defined and is in fact different from server to server.
*
* mcMMO employs a flexible system where users can define which properties of an items metadata (often its NBT)
* are important for matching and mcMMO will respect those properties when comparing one item to another.
*
* If a user does not define a property as being important for matching mcMMO will ignore that property when matching
* two or more items, even if that property is not equivalent between the items. This type will contain information
* on which properties are to be considered important for matching purposes.
*
* The main goal of this system is accommodate for the vast majority of custom item modifications a server can employ,
* these custom items are often defined in irregular ways server to server, thus why this type was made.
*
* In summary, this type serves several purposes...
* 1) Abstract away platform specific implementations of MC Items
* 2) Contain information about an item and which properties of said item that are considered important and thus will be used to equate equivalency to another item when doing comparisons
*/
public class CustomItemTarget implements CustomItemMatching {
private MMOItem item; //Abstract representation of the item
private HashSet<ItemMatchProperty> itemMatchProperties; //Item properties used for matching
public CustomItemTarget(MMOItem item) {
this.item = item;
itemMatchProperties = new HashSet<>();
}
public CustomItemTarget(MMOItem item, HashSet<ItemMatchProperty> itemMatchProperties) {
this.item = item;
this.itemMatchProperties = itemMatchProperties;
}
public MMOItem getItem() {
return item;
}
public HashSet<ItemMatchProperty> getItemMatchProperties() {
return itemMatchProperties;
}
/**
* Determines whether or not an item matches this one
* Behaviours for matching can vary based on the implementation
* @param otherItem target item to compare itself to
* @return true if this item matches the target item
*/
@Override
public boolean isMatch(MMOItem otherItem) {
//First compare the basic things that need to match between each item
if(item.equals(otherItem)) {
}
}
}

View File

@ -0,0 +1,33 @@
package com.gmail.nossr50.datatypes.items;
/**
* Represents a property of an item which is used in strict matching
* Typically this represents and NBT field and its value
* All NBT entries have an ID and a value, this value can be one of many types
*/
public class ItemMatchProperty {
final private Object propertyValue;
final private String nbtID;
public ItemMatchProperty(Object propertyValue, String nbtID) {
this.propertyValue = propertyValue;
this.nbtID = nbtID;
}
/**
* The expected value for this NBT entry
* @return the expected value for this NBT entry
*/
public Object getPropertyValue() {
return propertyValue;
}
/**
* The ID (name) of this NBT entry
* @return the ID (name) of this NBT entry
*/
public String getID() {
return nbtID;
}
}

View File

@ -0,0 +1,61 @@
package com.gmail.nossr50.datatypes.items;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet;
import java.util.Objects;
/**
* Represents a series of items that are all acceptable inputs for a behaviour
* Wildcards have a unique name that defines them, no two wildcards should share the same name.
* The name is important as it is used to identify the wildcard to the player.
*
* One example of the purpose of this Datatype:
*
* As an example, in Repair users are allowed to define a repair cost that can specify wildcards
* One such example is wood planks, many variants exist in Minecraft and they can all be used to repair Wooden tools
*
* ItemWildcards is a flexible datatype and won't be used just for Repair, but at the time of writing it was created
* to solve a problem with Repair. Given its flexible nature it can be used for many purposes.
*
*/
public class ItemWildcards {
private String wildcardName;
private HashSet<CustomItemTarget> itemTargets;
public ItemWildcards(String wildcardName, HashSet<CustomItemTarget> itemTargets) {
this.wildcardName = wildcardName;
this.itemTargets = itemTargets;
}
public int getItemCount() {
return itemTargets.size();
}
public HashSet<ItemStack> getItemTargets() {
return itemTargets;
}
public void setItemTargets(HashSet<CustomItemTarget> itemTargets) {
this.itemTargets = itemTargets;
}
public String getWildcardName() {
return wildcardName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ItemWildcards)) return false;
ItemWildcards that = (ItemWildcards) o;
return getWildcardName().equals(that.getWildcardName()) &&
getItemTargets().equals(that.getItemTargets());
}
@Override
public int hashCode() {
return Objects.hash(getWildcardName(), getItemTargets());
}
}

View File

@ -0,0 +1,40 @@
package com.gmail.nossr50.datatypes.items;
import com.gmail.nossr50.util.nbt.RawNBT;
/**
* Represents the abstracted form of an item in Minecraft which can be used to construct an item implementation per platform
* Return types of this object are not platform specific
* Only requires a namespace key to be defined, all other properties will be default initialized
*/
public interface MMOItem<T> {
/**
* Gets the item implementation of this type for this object
* @return the item implementation
*/
T getItemImplementation();
/**
* Get the Minecraft fully qualified namespace (FQN) key for this item
* Typically the FQN will read like this 'minecraft:name_here'
* @return the fully qualified namespace key for this item
*/
String getNamespaceKey();
/**
* Get the amount of this Item
* Items in Minecraft are technically stacks of items with the minimum amount being 1 in most cases
* The amount is used for matching purposes, and should default to 1 if undefined
* @return the amount for this Item
*/
int getItemAmount();
/**
* Get the RawNBT for this item if it has any
* This can be null
* @return the raw NBT if it exists, null otherwise
*/
RawNBT getRawNBT();
}

View File

@ -0,0 +1,13 @@
package com.gmail.nossr50.datatypes.nbt;
/**
* Platform independent representation of a Entity in Minecraft
* @param <T> the platform specific type of this Entity
*/
public interface MMOEntity<T> {
/**
* Get the platform specific implementation of this entity
* @return the platform specific implementation of this entity
*/
T getImplementation();
}

View File

@ -0,0 +1,26 @@
package com.gmail.nossr50.datatypes.nbt;
import com.gmail.nossr50.util.nbt.RawNBT;
/**
* Many things in Minecraft make use of the NBT System
* You can read about the NBT System here - https://wiki.vg/NBT
*
* Types that support NBT will implement this interface
*/
public interface NBTHolder {
/**
* Get the RawNBT for this object
* @return the RawNBT for this object
*/
RawNBT getRawNBT();
/**
* Determine whether or not this object has the specific NBT entry and matching value
* @param id the ID fof the NBT entry
* @param value the value of the NBT entry
* @return returns true if the NBT of id exists and its value matches
*/
boolean hasNBTValue(String id, Object value);
}

View File

@ -11,9 +11,15 @@ public interface RepairCost {
/** /**
* Searches a player inventory for a matching ItemStack that can be used to pay for the repair transaction * Searches a player inventory for a matching ItemStack that can be used to pay for the repair transaction
* @param playerInventory inventory of player attempting to pay the cost * @param playerInventory inventory of player attempting to pay the cost
* @param strictMatching whether or not to match repair cost items strictly with items in a players inventory
* @return any compatible payment items if found * @return any compatible payment items if found
*/ */
ItemStack findPayment(PlayerInventory playerInventory, boolean strictMatching); ItemStack findPayment(PlayerInventory playerInventory);
/**
* Whether or not this repair cost is strictly matched
* Strict matching compares Items by using metadata and material type
* @return true if the RepairCost uses strict matching
*/
boolean hasStrictMatching();
} }

View File

@ -1,51 +0,0 @@
package com.gmail.nossr50.skills.repair;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import java.util.Objects;
public class RepairCostItem implements RepairCost {
private ItemStack repairCostItem;
public RepairCostItem(ItemStack repairCostItem) {
this.repairCostItem = repairCostItem;
}
@Override
public ItemStack findPayment(PlayerInventory playerInventory, boolean strictMatching) {
for(ItemStack itemStack : playerInventory.getContents()) {
if(itemStack == null || itemStack.getType() == Material.AIR) {
continue;
}
//Attempt to match the item in the inventory to any of the compatible repair items
if(strictMatching) {
//TODO: Replace with strict matching code
if(itemStack.isSimilar(repairCostItem))
return itemStack;
} else {
if(itemStack.getType() == repairCostItem.getType()) {
return itemStack;
}
}
}
return null;
}
@Override
public int hashCode() {
return Objects.hash(repairCostItem);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RepairCostItem)) return false;
RepairCostItem that = (RepairCostItem) o;
return repairCostItem.equals(that.repairCostItem);
}
}

View File

@ -1,9 +1,12 @@
package com.gmail.nossr50.skills.repair; package com.gmail.nossr50.skills.repair;
import com.gmail.nossr50.datatypes.items.ItemWildcards;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.PlayerInventory;
import java.util.HashSet;
/** /**
* Represents a piece of a RepairTransaction * Represents a piece of a RepairTransaction
* Multiple RepairCost pieces are used to pay for a RepairTransaction * Multiple RepairCost pieces are used to pay for a RepairTransaction
@ -12,25 +15,28 @@ import org.bukkit.inventory.PlayerInventory;
*/ */
public class RepairCostWildcard implements RepairCost { public class RepairCostWildcard implements RepairCost {
private RepairWildcard repairWildcard; private HashSet<SimpleRepairCost> simpleRepairCosts;
private ItemWildcards itemWildcards;
public RepairCostWildcard(ItemWildcards itemWildcards) {
this.itemWildcards = itemWildcards;
simpleRepairCosts = new HashSet<>();
for(ItemStack itemStack : )
}
@Override @Override
public ItemStack findPayment(PlayerInventory playerInventory, boolean strictMatching) { public ItemStack findPayment(PlayerInventory playerInventory) {
for(ItemStack itemStack : playerInventory.getContents()) { for(ItemStack itemStack : playerInventory.getContents()) {
if(itemStack == null || itemStack.getType() == Material.AIR) { if(itemStack == null || itemStack.getType() == Material.AIR) {
continue; continue;
} }
for(ItemStack wildCardItem : repairWildcard.getMatchingItems()) { for(SimpleRepairCost simpleRepairCost : simpleRepairCosts) {
//Attempt to match the item in the inventory to any of the compatible repair items //Attempt to match the item in the inventory to any of the compatible repair items
if(strictMatching) { if(simpleRepairCost.findPayment(playerInventory) != null) {
//TODO: Replace with strict matching code return simpleRepairCost.findPayment(playerInventory);
if(itemStack.isSimilar(wildCardItem))
return itemStack;
} else {
if(itemStack.getType() == wildCardItem.getType()) {
return itemStack;
}
} }
} }
} }
@ -38,12 +44,12 @@ public class RepairCostWildcard implements RepairCost {
return null; return null;
} }
public RepairWildcard getRepairWildcard() { public ItemWildcards getItemWildcards() {
return repairWildcard; return itemWildcards;
} }
public void setRepairWildcard(RepairWildcard repairWildcard) { public void setItemWildcards(ItemWildcards itemWildcards) {
this.repairWildcard = repairWildcard; this.itemWildcards = itemWildcards;
} }
} }

View File

@ -4,10 +4,18 @@ package com.gmail.nossr50.skills.repair;
import java.util.HashSet; import java.util.HashSet;
/** /**
* Represents a complete repair transaction * Represents a complete "repair transaction"
* A repair transaction is made up of a multiple RepairCost objects *
* A RepairCost object is used to find a matching ItemStack in a players inventory if one exists * I will define a "repair transaction" as such
* A RepairCost object can be a single item or it can be multiple items representing a range of compatible items to pay that part of the RepairTransaction * - The items used to pay the cost of repairing an item in mcMMO via the Repair Skill
*
* A single "RepairTransaction" is made up of a multiple RepairCost objects
* No two RepairCosts contained within this type can be exact duplicates
*
* A RepairCost is used to find a matching ItemStack in a players inventory if one exists to pay its cost
*
* A RepairCost can be a single item or it can be multiple items representing a range of compatible items
* to pay that part of the RepairTransaction
*/ */
public class RepairTransaction { public class RepairTransaction {
private HashSet<RepairCost> repairItems; private HashSet<RepairCost> repairItems;

View File

@ -1,43 +0,0 @@
package com.gmail.nossr50.skills.repair;
import org.bukkit.inventory.ItemStack;
import java.util.Objects;
import java.util.Set;
public class RepairWildcard {
private String wildcardName;
private Set<ItemStack> matchingItems;
public RepairWildcard(String wildcardName, Set<ItemStack> matchingItems) {
this.wildcardName = wildcardName;
this.matchingItems = matchingItems;
}
public Set<ItemStack> getMatchingItems() {
return matchingItems;
}
public void setMatchingItems(Set<ItemStack> matchingItems) {
this.matchingItems = matchingItems;
}
public String getWildcardName() {
return wildcardName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof RepairWildcard)) return false;
RepairWildcard that = (RepairWildcard) o;
return getWildcardName().equals(that.getWildcardName()) &&
getMatchingItems().equals(that.getMatchingItems());
}
@Override
public int hashCode() {
return Objects.hash(getWildcardName(), getMatchingItems());
}
}

View File

@ -0,0 +1,66 @@
package com.gmail.nossr50.skills.repair;
import com.gmail.nossr50.datatypes.items.ItemMatchProperty;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import java.util.Objects;
/**
* Implementation of RepairCost
* <p>
* A SimpleRepairCost can be one or more items, any one of which can be used to pay for a RepairTransaction
* If a SimpleRepairCost is more than one item, then only one of the items are required to represent its cost.
*
* This type is strictly for use with RepairTransaction, which represents the full cost of a Repair.
* @see com.gmail.nossr50.skills.repair.RepairTransaction for more details
*/
public class SimpleRepairCost implements RepairCost {
private ItemMatchProperty itemMatchProperty;
public SimpleRepairCost(ItemMatchProperty itemMatchProperty) {
this.itemMatchProperty = itemMatchProperty;
}
@Override
public ItemStack findPayment(PlayerInventory playerInventory) {
for(ItemStack itemStack : playerInventory.getContents()) {
if(itemStack == null || itemStack.getType() == Material.AIR) {
continue;
}
//Attempt to match the item in the inventory to any of the compatible repair items
if(hasStrictMatching()) {
//TODO: Replace with strict matching code
if(item)
return itemStack;
} else {
if(itemStack.getType() == itemMatchProperty.getType()) {
return itemStack;
}
}
}
return null;
}
@Override
public int hashCode() {
return Objects.hash(itemMatchProperty);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SimpleRepairCost)) return false;
SimpleRepairCost that = (SimpleRepairCost) o;
return itemMatchProperty.equals(that.itemMatchProperty);
}
@Override
public boolean hasStrictMatching() {
return strictMatching;
}
}

View File

@ -12,7 +12,7 @@ public class Repairable {
private short maximumDurability; private short maximumDurability;
private RepairTransaction repairTransaction; private RepairTransaction repairTransaction;
private boolean strictMatchingItem = false; private boolean strictMatchingItem = false;
private boolean strictMatchingRepairTransaction = false; // private boolean strictMatchingRepairTransaction = false;
private int baseXP = 0; private int baseXP = 0;
private RawNBT rawNBT; private RawNBT rawNBT;
private int repairCount = 1; private int repairCount = 1;
@ -20,13 +20,13 @@ public class Repairable {
private boolean hasPermission = false; private boolean hasPermission = false;
private boolean hasNBT = false; private boolean hasNBT = false;
public Repairable(ItemStack item, int minimumLevel, short maximumDurability, RepairTransaction repairTransaction, boolean strictMatchingItem, boolean strictMatchingRepairTransaction, int baseXP, int repairCount) { public Repairable(ItemStack item, int minimumLevel, short maximumDurability, RepairTransaction repairTransaction, boolean strictMatchingItem, int baseXP, int repairCount) {
this.item = item; this.item = item;
this.minimumLevel = minimumLevel; this.minimumLevel = minimumLevel;
this.maximumDurability = maximumDurability; this.maximumDurability = maximumDurability;
this.repairTransaction = repairTransaction; this.repairTransaction = repairTransaction;
this.strictMatchingItem = strictMatchingItem; this.strictMatchingItem = strictMatchingItem;
this.strictMatchingRepairTransaction = strictMatchingRepairTransaction; // this.strictMatchingRepairTransaction = strictMatchingRepairTransaction;
this.baseXP = baseXP; this.baseXP = baseXP;
this.repairCount = repairCount; this.repairCount = repairCount;
} }
@ -67,13 +67,13 @@ public class Repairable {
this.strictMatchingItem = strictMatchingItem; this.strictMatchingItem = strictMatchingItem;
} }
public boolean isStrictMatchingRepairTransaction() { // public boolean isStrictMatchingRepairTransaction() {
return strictMatchingRepairTransaction; // return strictMatchingRepairTransaction;
} // }
//
public void setStrictMatchingRepairTransaction(boolean strictMatchingRepairTransaction) { // public void setStrictMatchingRepairTransaction(boolean strictMatchingRepairTransaction) {
this.strictMatchingRepairTransaction = strictMatchingRepairTransaction; // this.strictMatchingRepairTransaction = strictMatchingRepairTransaction;
} // }
public int getBaseXP() { public int getBaseXP() {
return baseXP; return baseXP;

View File

@ -12,7 +12,7 @@ public class RepairableBuilder {
private short maximumDurability; private short maximumDurability;
private RepairTransaction repairTransaction; private RepairTransaction repairTransaction;
private boolean strictMatchingItem = false; private boolean strictMatchingItem = false;
private boolean strictMatchingRepairTransaction = false; // private boolean strictMatchingRepairTransaction = false;
private int baseXP = 0; private int baseXP = 0;
private RawNBT rawNBT; private RawNBT rawNBT;
private int repairCount = 1; private int repairCount = 1;
@ -43,10 +43,10 @@ public class RepairableBuilder {
return this; return this;
} }
public RepairableBuilder strictMatchingRepairTransaction(Boolean strictMatchingRepairTransaction) { // public RepairableBuilder strictMatchingRepairTransaction(Boolean strictMatchingRepairTransaction) {
this.strictMatchingRepairTransaction = strictMatchingRepairTransaction; // this.strictMatchingRepairTransaction = strictMatchingRepairTransaction;
return this; // return this;
} // }
public RepairableBuilder baseXP(Integer baseXP) { public RepairableBuilder baseXP(Integer baseXP) {
this.baseXP = baseXP; this.baseXP = baseXP;
@ -74,7 +74,7 @@ public class RepairableBuilder {
private Repairable makeRepairable() { private Repairable makeRepairable() {
Repairable repairable = new Repairable(item, minimumLevel, maximumDurability, repairTransaction, Repairable repairable = new Repairable(item, minimumLevel, maximumDurability, repairTransaction,
strictMatchingItem, strictMatchingRepairTransaction, baseXP, repairCount); strictMatchingItem, baseXP, repairCount);
if(permissionWrapper != null) { if(permissionWrapper != null) {
repairable.setPermissionWrapper(permissionWrapper); repairable.setPermissionWrapper(permissionWrapper);

View File

@ -1,6 +1,26 @@
package com.gmail.nossr50.util.nbt; package com.gmail.nossr50.util.nbt;
import com.gmail.nossr50.mcMMO;
import net.minecraft.server.v1_13_R2.NBTBase;
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftItem;
import org.bukkit.craftbukkit.v1_13_R2.util.CraftNBTTagConfigSerializer;
import org.bukkit.inventory.ItemStack;
public class NBTUtils { public class NBTUtils {
public RawNBT<?> constructNBT(String nbtString) {
try {
return new RawNBT<NBTBase>(nbtString, CraftNBTTagConfigSerializer.deserialize(nbtString));
} catch (Exception e) {
e.printStackTrace();
mcMMO.p.getLogger().severe("mcMMO was unable parse the NBT string from your config! Double check that it is proper NBT!");
return null;
}
}
public boolean hasNBT(ItemStack itemStack) {
if(CraftItem)
}
} }

View File

@ -1,10 +1,22 @@
package com.gmail.nossr50.util.nbt; package com.gmail.nossr50.util.nbt;
public class RawNBT { /**
String nbtContents; * A simple class that acts as a container for raw NBT data
* NBT data will be constructed from the raw NBT string using server internals
* This type is mostly used to take a raw string of NBT and transform it into the NBT data type used by internals
* the transformed data can then be used to check NBT data of entities in Minecraft
*
* One use of this type is as follows
* 1) Read partial or complete NBT from the config file for an item
* 2) Check an items NBT tree for this NBT data during runtime once transformed
*/
public class RawNBT<T> {
private String nbtContents;
private T nbtTree; //Will be constructed using server internals to make matching NBT easier
public RawNBT(String nbtContents) { public RawNBT(String nbtContents, T nbtTree) {
this.nbtContents = nbtContents; this.nbtContents = nbtContents;
NBTUtils
} }
public String getNbtContents() { public String getNbtContents() {