From 64438f01ec6833970ade5e0c8cbc32bf8554b0cb Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Wed, 4 Sep 2019 12:57:47 -0400 Subject: [PATCH 01/14] Update dependencies, and move titanium version declaration to gradle.properties --- build.gradle | 36 ++++++++++++++++++++++++++---------- gradle.properties | 7 ++++--- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 5c1e2d0..67016b7 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,9 @@ sourceSets { } configurations { + //Inform the alternate sourcesets about forge apiCompile.extendsFrom(compile) + testCompile.extendsFrom(compile) } test { @@ -60,14 +62,32 @@ minecraft { runs { client { workingDirectory project.file("run") - source sourceSets.main - source sourceSets.api + mods { + epos { + source sourceSets.main + source sourceSets.api + } + } } server { workingDirectory project.file("run") - source sourceSets.main - source sourceSets.api + mods { + epos { + source sourceSets.main + source sourceSets.api + } + } + } + + data { + workingDirectory project.file("run") + mods { + epos { + source sourceSets.main + source sourceSets.api + } + } } } } @@ -83,7 +103,7 @@ dependencies { testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_version}" minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - compile fg.deobf('com.hrznstudio:titanium:2.1.+') + compile fg.deobf("com.hrznstudio:titanium:${titanium_version}") } task srcJar(type: Jar) { @@ -166,8 +186,4 @@ static String getBuildNumber() { buildNumber = System.getenv("bamboo_buildNumber") != null ? System.getenv("bamboo_buildNumber") : "" } return buildNumber -} - -configurations { - apiCompile.extendsFrom(compile) -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index f68e20f..d0f3b2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,10 @@ minecraft_version=1.14.4 -forge_version=28.0.45 -mappings_version=20190810-1.14.3 +forge_version=28.0.91 +mappings_version=20190904-1.14.3 base_version=4.0.0 -junit_version=5.5.0 +junit_version=5.5.1 +titanium_version=2.1.+ team=Team Acronym Coders group=com.teamacronymcoders From fd7170bd9c4cdaf07857c1a2460530961b023310 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Wed, 4 Sep 2019 13:41:23 -0400 Subject: [PATCH 02/14] Initial port/rebase of #1 with a few minor improvements/namings --- .../teamacronymcoders/epos/api/EposAPI.java | 3 + .../epos/api/locks/IGenericFuzzyLockType.java | 4 + .../epos/api/locks/ILockKeyCreator.java | 17 ++ .../epos/api/locks/LockRegistry.java | 121 ++++++++++++++ .../epos/api/locks/keys/GenericLockKey.java | 26 +++ .../epos/api/locks/keys/IFuzzyLockKey.java | 26 +++ .../epos/api/locks/keys/ILockKey.java | 4 + .../epos/api/locks/keys/IParentLockKey.java | 19 +++ .../epos/api/locks/keys/NBTLockKey.java | 150 ++++++++++++++++++ .../epos/api/requirements/IRequirement.java | 6 + .../epos/locks/DefaultLocks.java | 59 +++++++ .../epos/locks/FuzzyLockKeyTypes.java | 14 ++ .../epos/locks/keys/ArmorLockKey.java | 74 +++++++++ .../locks/keys/ArmorToughnessLockKey.java | 74 +++++++++ .../epos/locks/keys/AttackDamageLockKey.java | 77 +++++++++ .../epos/locks/keys/DimensionTypeLockKey.java | 40 +++++ .../epos/locks/keys/GenericNBTLockKey.java | 47 ++++++ .../epos/locks/keys/HungerLockKey.java | 79 +++++++++ .../epos/locks/keys/ItemLockKey.java | 55 +++++++ .../epos/locks/keys/ModLockKey.java | 102 ++++++++++++ .../epos/locks/keys/SaturationLockKey.java | 82 ++++++++++ .../locks/keys/entity/EntityDamageKey.java | 24 +++ .../epos/locks/keys/entity/EntityLockKey.java | 37 +++++ .../locks/keys/entity/EntityMountKey.java | 24 +++ .../epos/locks/keys/entity/EntityTameKey.java | 24 +++ .../keys/harvest/BlockHarvestLockKey.java | 61 +++++++ .../locks/keys/harvest/HarvestLockKey.java | 21 +++ .../keys/harvest/ToolHarvestLockKey.java | 104 ++++++++++++ .../epos/locks/keys/tag/ParentTagLockKey.java | 82 ++++++++++ .../epos/locks/keys/tag/TagLockKey.java | 46 ++++++ .../com/teamacronymcoders/epos/JUnitTest.java | 15 ++ .../com/teamacronymcoders/epos/TestJUnit.java | 14 -- .../epos/api/locks/LockAPITest.java | 43 +++++ .../epos/api/locks/LocksTest.java | 9 ++ .../epos/api/locks/keys/DoubleLockKey.java | 63 ++++++++ .../epos/api/locks/keys/IntegerLockKey.java | 57 +++++++ .../epos/api/locks/keys/ListLockKey.java | 38 +++++ .../epos/api/locks/keys/StringLockKey.java | 23 +++ .../api/requirements/SimpleRequirement.java | 33 ++++ 39 files changed, 1783 insertions(+), 14 deletions(-) create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/IGenericFuzzyLockType.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/IFuzzyLockKey.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/ILockKey.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/FuzzyLockKeyTypes.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java create mode 100644 src/test/java/com/teamacronymcoders/epos/JUnitTest.java delete mode 100644 src/test/java/com/teamacronymcoders/epos/TestJUnit.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/keys/DoubleLockKey.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/keys/IntegerLockKey.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java diff --git a/src/api/java/com/teamacronymcoders/epos/api/EposAPI.java b/src/api/java/com/teamacronymcoders/epos/api/EposAPI.java index b945f97..6df1a20 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/EposAPI.java +++ b/src/api/java/com/teamacronymcoders/epos/api/EposAPI.java @@ -1,6 +1,7 @@ package com.teamacronymcoders.epos.api; import com.teamacronymcoders.epos.api.feat.Feat; +import com.teamacronymcoders.epos.api.locks.LockRegistry; import com.teamacronymcoders.epos.api.path.IPath; import com.teamacronymcoders.epos.api.path.MissingPath; import com.teamacronymcoders.epos.api.pathfeature.PathFeatureProvider; @@ -20,4 +21,6 @@ public class EposAPI { RegistryManager.ACTIVE.getRegistry(Feat.class); public static final IForgeRegistry PATH_FEATURE_PROVIDER_REGISTRY = RegistryManager.ACTIVE.getRegistry(PathFeatureProvider.class); + + public static final LockRegistry LOCK_REGISTRY = new LockRegistry(); } diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/IGenericFuzzyLockType.java b/src/api/java/com/teamacronymcoders/epos/api/locks/IGenericFuzzyLockType.java new file mode 100644 index 0000000..cb49fe5 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/IGenericFuzzyLockType.java @@ -0,0 +1,4 @@ +package com.teamacronymcoders.epos.api.locks; + +public interface IGenericFuzzyLockType { +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java b/src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java new file mode 100644 index 0000000..a9d9dc7 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java @@ -0,0 +1,17 @@ +package com.teamacronymcoders.epos.api.locks; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +@FunctionalInterface +public interface ILockKeyCreator { + + /** + * @return null if it cannot be used to create a type. + * + * @implNote IMPORTANT: fail fast where possible, and ensure it is actually the type going to be used + */ + @Nullable + KEY createFrom(@Nonnull Object o); +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java new file mode 100644 index 0000000..bbc4bcb --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java @@ -0,0 +1,121 @@ +package com.teamacronymcoders.epos.api.locks; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.api.locks.keys.IParentLockKey; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nonnull; + +public class LockRegistry { + + private static final List EMPTY_REQUIREMENTS = Collections.emptyList(); + + private final List> keyCreators = new ArrayList<>(); + private final Map> locks = new HashMap<>(); + private final Map> fuzzyLockInfo = new HashMap<>(); + + public void registerLockType(@Nonnull ILockKeyCreator creator) { + keyCreators.add(creator); + //Unlike the 1.12 system this has it so that each lock key has one registration for each type it can be created from + //Each one has to be checked when getting by type rather than knowing it "should" be good for that type already + //Does this have any negative performance impact + } + + public void addLockByKey(@Nonnull ILockKey key, @Nonnull List requirements) { + if (key instanceof GenericLockKey || requirements.isEmpty()) { + //Don't allow having locks on the generic key that is just for when there isn't enough information about a fuzzy lock key + return; + } + locks.put(key, requirements); + + if (key instanceof IFuzzyLockKey) { + IFuzzyLockKey fuzzy = (IFuzzyLockKey) key; + if (!fuzzy.isNotFuzzy()) { + //Store the fuzzy instance in a list for the specific item + fuzzyLockInfo.computeIfAbsent(fuzzy.getNotFuzzy(), k -> new HashSet<>()).add(fuzzy); + } + } + } + + @Nonnull + public List getRequirementsByKey(@Nonnull ILockKey key) { + if (key instanceof IFuzzyLockKey) { + return getFuzzyRequirements((IFuzzyLockKey) key); + } + return locks.getOrDefault(key, EMPTY_REQUIREMENTS); + } + + @Nonnull + public List getFuzzyRequirements(@Nonnull IFuzzyLockKey key) { + List requirements = new ArrayList<>(); + if (key.isNotFuzzy()) { + addRequirementsFromLock(requirements, key); + } else { + ILockKey baseLock = key.getNotFuzzy(); + //Add the base lock's requirements + addRequirementsFromLock(requirements, baseLock); + Set fuzzyLookup = fuzzyLockInfo.get(baseLock); + if (fuzzyLookup != null) { + for (IFuzzyLockKey fuzzyLock : fuzzyLookup) { + if (key.fuzzyEquals(fuzzyLock)) { //Build up the best match + //fuzzy is the given object and has all info and fuzzyLock is the partial information + addRequirementsFromLock(requirements, fuzzyLock); + } + } + } + } + return requirements; + } + + //Helper method to add a lock's requirements to the requirement list if it has them + private void addRequirementsFromLock(@Nonnull List requirements, @Nonnull ILockKey key) { + List reqs = locks.get(key); + if (reqs != null) { + //If there are locks for the key add them + requirements.addAll(reqs); + } + } + + @Nonnull + public List getLocks(@Nonnull Collection objects) { + //TODO: Helper method for combining the locks of multiple same type objects (Maybe even allow of different type objects) + // If it doesn't support different type objects should there be some optimization so it doesn't recheck all the types + List requirements = new ArrayList<>(); + for (Object object : objects) { + requirements.addAll(getLocks(object)); + } + return requirements; + } + + @Nonnull + public List getLocks(@Nonnull Object object) { + List requirements = new ArrayList<>(); + for (ILockKeyCreator keyCreator : keyCreators) { + ILockKey lockKey = keyCreator.createFrom(object); + if (lockKey == null) { + //We failed to create a lock key with our object, continue to next type of lock key + continue; + } + if (lockKey instanceof IFuzzyLockKey) { + requirements.addAll(getFuzzyRequirements((IFuzzyLockKey) lockKey)); + } else { + addRequirementsFromLock(requirements, lockKey); + } + if (lockKey instanceof IParentLockKey) { + //Add all the sub requirements the lock key may have + // (if there is one that matches the key itself it will have been caught above) + requirements.addAll(((IParentLockKey) lockKey).getSubRequirements()); + } + } + return requirements; + } +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java new file mode 100644 index 0000000..b551fbd --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java @@ -0,0 +1,26 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import com.teamacronymcoders.epos.api.locks.IGenericFuzzyLockType; +import javax.annotation.Nonnull; + +public final class GenericLockKey implements ILockKey { + + @Nonnull + private IGenericFuzzyLockType type; + + public GenericLockKey(@Nonnull IGenericFuzzyLockType type) { + this.type = type; + } + + @Override + public boolean equals(Object o) { + //TODO: Verify this is correct even when used via an enum + return o == this || o instanceof GenericLockKey && type.equals(((GenericLockKey) o).type); + } + + @Override + public int hashCode() { + //TODO: Verify this is the same even when used via an enum + return type.hashCode(); + } +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IFuzzyLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IFuzzyLockKey.java new file mode 100644 index 0000000..b2a3531 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IFuzzyLockKey.java @@ -0,0 +1,26 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import javax.annotation.Nonnull; + +public interface IFuzzyLockKey extends ILockKey { + + /** + * Self is the full lock and other is the partial data. + * + * @param other The FuzzyLockKey to check. + * + * @return True if the two objects count as equals, false otherwise. + */ + boolean fuzzyEquals(@Nonnull IFuzzyLockKey other); + + /** + * @return True if the fuzzy data is not used in the current instance of the object, false otherwise. + */ + boolean isNotFuzzy(); + + /** + * @return A non fuzzy "generic" variant of the key. If there is no generic type return a GenericLockKey instead. Allows for getting partial locks + */ + @Nonnull + ILockKey getNotFuzzy(); +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/ILockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/ILockKey.java new file mode 100644 index 0000000..b3aeb5a --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/ILockKey.java @@ -0,0 +1,4 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +public interface ILockKey { +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java new file mode 100644 index 0000000..aeeb1f4 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java @@ -0,0 +1,19 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import com.teamacronymcoders.epos.api.locks.LockRegistry; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import java.util.List; +import javax.annotation.Nonnull; + +public interface IParentLockKey extends ILockKey { + + /** + * Retrieves any sub requirements this key may have. This usually can be implemented by calling {@link LockRegistry#getLocks(Class, Object[])} + * + * @return A RequirementHolder of the sub requirements. + */ + @Nonnull + List getSubRequirements(); + //TODO: Update javadocs reason this is a list is so that the higher tier logic handlers can decide how to merge ALL the different requirements together + // This is not a set in case something wants to know if there are duplicates and merge them differently +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java new file mode 100644 index 0000000..74b4a26 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java @@ -0,0 +1,150 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.nbt.ByteArrayNBT; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.nbt.IntArrayNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.LongArrayNBT; +import net.minecraftforge.common.util.Constants; + +public abstract class NBTLockKey implements IFuzzyLockKey { + + @Nullable + protected CompoundNBT nbt; + + protected NBTLockKey(@Nullable CompoundNBT nbt) { + this.nbt = nbt == null || nbt.isEmpty() ? null : nbt; + } + + //TODO: Re-evaluate this and try to deduplicate the code and make sure tag list isn't checking duplicates + protected static boolean similarNBT(@Nullable INBT full, @Nullable INBT partial) { + if (full == null) { + return partial == null; + } + if (partial == null) { + return true; + } + if (full.getId() != partial.getId()) { + return false; + } + if (full.equals(partial)) { + return true; + } + switch (full.getId()) { + case Constants.NBT.TAG_COMPOUND: + CompoundNBT fullTag = (CompoundNBT) full; + CompoundNBT partialTag = (CompoundNBT) partial; + Set ptKeys = partialTag.keySet(); + for (String partialKey : ptKeys) { + //One of the keys is missing OR the tags are different types OR they do not match + if (!fullTag.contains(partialKey, partialTag.getTagId(partialKey)) || !similarNBT(fullTag.get(partialKey), partialTag.get(partialKey))) { + return false; + } + } + return true; + case Constants.NBT.TAG_LIST: + ListNBT fTagList = (ListNBT) full; + ListNBT pTagList = (ListNBT) partial; + if (fTagList.isEmpty() && !pTagList.isEmpty() || fTagList.getTagType() != pTagList.getTagType()) { + return false; + } + for (int i = 0; i < pTagList.size(); i++) { + INBT pTag = pTagList.get(i); + boolean hasTag = false; + for (int j = 0; j < fTagList.size(); j++) { + if (similarNBT(fTagList.get(j), pTag)) { + hasTag = true; + break; + } + } + if (!hasTag) { + return false; + } + } + return true; + case Constants.NBT.TAG_BYTE_ARRAY: + byte[] fByteArray = ((ByteArrayNBT) full).getByteArray(); + byte[] pByteArray = ((ByteArrayNBT) partial).getByteArray(); + List hits = new ArrayList<>(); + for (byte pByte : pByteArray) { + boolean hasMatch = false; + for (int i = 0; i < fByteArray.length; i++) { + if (!hits.contains(i) && pByte == fByteArray[i]) { + hits.add(i); + hasMatch = true; + break; + } + } + if (!hasMatch) { + return false; + } + } + return true; + case Constants.NBT.TAG_INT_ARRAY: + int[] fIntArray = ((IntArrayNBT) full).getIntArray(); + int[] pIntArray = ((IntArrayNBT) partial).getIntArray(); + hits = new ArrayList<>(); + for (int pInt : pIntArray) { + boolean hasMatch = false; + for (int i = 0; i < fIntArray.length; i++) { + if (!hits.contains(i) && pInt == fIntArray[i]) { + hits.add(i); + hasMatch = true; + break; + } + } + if (!hasMatch) { + return false; + } + } + return true; + case Constants.NBT.TAG_LONG_ARRAY: + long[] fLongArray = ((LongArrayNBT) full).getAsLongArray(); + long[] pLongArray = ((LongArrayNBT) partial).getAsLongArray(); + hits = new ArrayList<>(); + for (long pLong : pLongArray) { + boolean hasMatch = false; + for (int i = 0; i < fLongArray.length; i++) { + if (!hits.contains(i) && pLong == fLongArray[i]) { + hits.add(i); + hasMatch = true; + break; + } + } + if (!hasMatch) { + return false; + } + } + return true; + default: + return false; + } + } + + @Nullable + public CompoundNBT getNBT() { + return this.nbt; + } + + @Override + public boolean isNotFuzzy() { + return this.nbt == null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey other) { + if (other == this) { + return true; + } + if (other instanceof NBTLockKey) { + return similarNBT(getNBT(), ((NBTLockKey) other).getNBT()); + } + return false; + } +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java new file mode 100644 index 0000000..7b63ea1 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java @@ -0,0 +1,6 @@ +package com.teamacronymcoders.epos.api.requirements; + +//TODO: Actually implement this and other stuff, this package and this interface are currently +// Just placeholders so that the lock logic has something to reference +public interface IRequirement { +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java new file mode 100644 index 0000000..04170e9 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java @@ -0,0 +1,59 @@ +package com.teamacronymcoders.epos.locks; + +import com.teamacronymcoders.epos.api.EposAPI; +import com.teamacronymcoders.epos.locks.keys.ArmorLockKey; +import com.teamacronymcoders.epos.locks.keys.ArmorToughnessLockKey; +import com.teamacronymcoders.epos.locks.keys.AttackDamageLockKey; +import com.teamacronymcoders.epos.locks.keys.DimensionTypeLockKey; +import com.teamacronymcoders.epos.locks.keys.GenericNBTLockKey; +import com.teamacronymcoders.epos.locks.keys.HungerLockKey; +import com.teamacronymcoders.epos.locks.keys.ItemLockKey; +import com.teamacronymcoders.epos.locks.keys.ModLockKey; +import com.teamacronymcoders.epos.locks.keys.SaturationLockKey; +import com.teamacronymcoders.epos.locks.keys.entity.EntityDamageKey; +import com.teamacronymcoders.epos.locks.keys.entity.EntityMountKey; +import com.teamacronymcoders.epos.locks.keys.entity.EntityTameKey; +import com.teamacronymcoders.epos.locks.keys.harvest.BlockHarvestLockKey; +import com.teamacronymcoders.epos.locks.keys.harvest.ToolHarvestLockKey; +import com.teamacronymcoders.epos.locks.keys.tag.ParentTagLockKey; +import net.minecraft.item.ItemStack; + +public class DefaultLocks { + + //TODO: Call this from somewhere + public static void registerKeyLookups() { + //ItemLockKey + EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ItemLockKey.fromItemStack((ItemStack) object) : null); + //ModLockKey + EposAPI.LOCK_REGISTRY.registerLockType(ModLockKey::fromObject); + //Generic lock based entirely on NBT + EposAPI.LOCK_REGISTRY.registerLockType(GenericNBTLockKey::fromObject); + + //Ones that probably will be in an addon but for now are from CompatSkills for more test cases of seeing how the system works + + //DimensionTypeLockKey + EposAPI.LOCK_REGISTRY.registerLockType(DimensionTypeLockKey::fromObject); + //EntityDamageKey + EposAPI.LOCK_REGISTRY.registerLockType(EntityDamageKey::fromObject); + //EntityMountKey + EposAPI.LOCK_REGISTRY.registerLockType(EntityMountKey::fromObject); + //EntityTameKey + EposAPI.LOCK_REGISTRY.registerLockType(EntityTameKey::fromObject); + //ArmorLockKey + EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ArmorLockKey.fromItemStack((ItemStack) object) : null); + //ArmorToughnessKey + EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ArmorToughnessLockKey.fromItemStack((ItemStack) object) : null); + //AttackDamageLockKey + EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? AttackDamageLockKey.fromItemStack((ItemStack) object) : null); + //HungerLockKey + EposAPI.LOCK_REGISTRY.registerLockType(HungerLockKey::fromObject); + //SaturationLockKey + EposAPI.LOCK_REGISTRY.registerLockType(SaturationLockKey::fromObject); + //BlockHarvestLockKey + EposAPI.LOCK_REGISTRY.registerLockType(BlockHarvestLockKey::fromObject); + //ToolHarvestLockKey + EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ToolHarvestLockKey.fromItemStack((ItemStack) object) : null); + //ParentTagLockKey + EposAPI.LOCK_REGISTRY.registerLockType(ParentTagLockKey::fromObject); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/FuzzyLockKeyTypes.java b/src/main/java/com/teamacronymcoders/epos/locks/FuzzyLockKeyTypes.java new file mode 100644 index 0000000..a28e36e --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/FuzzyLockKeyTypes.java @@ -0,0 +1,14 @@ +package com.teamacronymcoders.epos.locks; + +import com.teamacronymcoders.epos.api.locks.IGenericFuzzyLockType; + +public enum FuzzyLockKeyTypes implements IGenericFuzzyLockType { + ARMOR, + ARMOR_TOUGHNESS, + ATTACK_DAMAGE, + BLOCK_HARVEST, + GENERIC_NBT, + HUNGER, + SATURATION, + TOOL_HARVEST +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java new file mode 100644 index 0000000..65460ce --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java @@ -0,0 +1,74 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Collection; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class ArmorLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.ARMOR); + + private final double armor; + + public ArmorLockKey(double armor) { + if (armor < 0) { + //TODO: Add whatever information is needed here for a better error message + throw new IllegalArgumentException(); + } + this.armor = armor; + } + + @Nullable + public static ArmorLockKey fromItemStack(@Nonnull ItemStack stack) { + if (stack.isEmpty()) { + return null; + } + Item item = stack.getItem(); + if (item instanceof ArmorItem) { + ArmorItem armorItem = (ArmorItem) item; + double armor = armorItem.getDamageReduceAmount(); + Collection protection = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack).get(SharedMonsterAttributes.ARMOR.getName()); + if (!protection.isEmpty()) { + armor += protection.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D); + } + return new ArmorLockKey(armor); + } + return null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof ArmorLockKey && armor >= ((ArmorLockKey) o).armor; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof ArmorLockKey && armor == ((ArmorLockKey) o).armor; + } + + @Override + public int hashCode() { + return Objects.hash(armor); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java new file mode 100644 index 0000000..c8a079a --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java @@ -0,0 +1,74 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Collection; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.item.ArmorItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class ArmorToughnessLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.ARMOR_TOUGHNESS); + + private final double toughness; + + public ArmorToughnessLockKey(double toughness) { + if (toughness < 0) { + //TODO: Add whatever information is needed here for a better error message + throw new IllegalArgumentException(); + } + this.toughness = toughness; + } + + @Nullable + public static ArmorToughnessLockKey fromItemStack(@Nonnull ItemStack stack) { + if (stack.isEmpty()) { + return null; + } + Item item = stack.getItem(); + if (item instanceof ArmorItem) { + ArmorItem armorItem = (ArmorItem) item; + double toughness = armorItem.getToughness(); + Collection protection = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack).get(SharedMonsterAttributes.ARMOR_TOUGHNESS.getName()); + if (!protection.isEmpty()) { + toughness += protection.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D); + } + return new ArmorToughnessLockKey(toughness); + } + return null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof ArmorToughnessLockKey && toughness >= ((ArmorToughnessLockKey) o).toughness; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof ArmorToughnessLockKey && toughness == ((ArmorToughnessLockKey) o).toughness; + } + + @Override + public int hashCode() { + return Objects.hash(toughness); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java new file mode 100644 index 0000000..73aaca5 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java @@ -0,0 +1,77 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.google.common.collect.Multimap; +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Collection; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.inventory.EquipmentSlotType; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class AttackDamageLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.ATTACK_DAMAGE); + + private final double attackDamage; + + public AttackDamageLockKey(double attackDamage) { + if (attackDamage < 0) { + //TODO: Add whatever information is needed here for a better error message + throw new IllegalArgumentException(); + } + this.attackDamage = attackDamage; + } + + @Nullable + public static AttackDamageLockKey fromItemStack(@Nonnull ItemStack stack) { + if (stack.isEmpty()) { + return null; + } + Item item = stack.getItem(); + //TODO: Decide if we should also check offhand + Multimap attributeModifiers = item.getAttributeModifiers(EquipmentSlotType.MAINHAND, stack); + Collection damage = attributeModifiers.get(SharedMonsterAttributes.ATTACK_DAMAGE.getName()); + /* + //TODO: This is for compat with TConstruct's ranged weapons probably can just be deleted or something + if (damage.isEmpty() && TinkersCompatHandler.ENABLED) {//For ranged tinker's weapons like the shuriken + if (item instanceof slimeknights.tconstruct.library.tools.ranged.IProjectile) { + attributeModifiers = ((slimeknights.tconstruct.library.tools.ranged.IProjectile) item).getProjectileAttributeModifier(stack); + damage = attributeModifiers.get(SharedMonsterAttributes.ATTACK_DAMAGE.getName()); + } + }*/ + return damage.isEmpty() ? null : new AttackDamageLockKey(damage.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D)); + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof AttackDamageLockKey && attackDamage >= ((AttackDamageLockKey) o).attackDamage; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof AttackDamageLockKey && attackDamage == ((AttackDamageLockKey) o).attackDamage; + } + + @Override + public int hashCode() { + return Objects.hash(attackDamage); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java new file mode 100644 index 0000000..90d08ec --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java @@ -0,0 +1,40 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.world.IWorld; +import net.minecraft.world.dimension.Dimension; +import net.minecraft.world.dimension.DimensionType; + +public class DimensionTypeLockKey implements ILockKey { + + @Nonnull + private final DimensionType dimension; + + public DimensionTypeLockKey(@Nonnull DimensionType dimension) { + this.dimension = dimension; + } + + @Nullable + public static DimensionTypeLockKey fromObject(@Nonnull Object object) { + if (object instanceof DimensionType) { + return new DimensionTypeLockKey((DimensionType) object); + } else if (object instanceof Dimension) { + return new DimensionTypeLockKey(((Dimension) object).getType()); + } else if (object instanceof IWorld) { + return new DimensionTypeLockKey(((IWorld) object).getDimension().getType()); + } + return null; + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof DimensionTypeLockKey && dimension.equals(((DimensionTypeLockKey) obj).dimension); + } + + @Override + public int hashCode() { + return dimension.hashCode(); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java new file mode 100644 index 0000000..ec85e4c --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java @@ -0,0 +1,47 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; + +public class GenericNBTLockKey extends NBTLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.GENERIC_NBT); + + public GenericNBTLockKey(@Nullable CompoundNBT nbt) { + super(nbt); + } + + @Nullable + public static GenericNBTLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + return stack.isEmpty() ? null : new GenericNBTLockKey(((ItemStack) object).getTag()); + } else if (object instanceof CompoundNBT) { + return new GenericNBTLockKey((CompoundNBT) object); + } + return null; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof GenericNBTLockKey && Objects.equals(nbt, ((GenericNBTLockKey) o).nbt); + } + + @Override + public int hashCode() { + return nbt == null ? super.hashCode() : nbt.hashCode(); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java new file mode 100644 index 0000000..0e73ac5 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java @@ -0,0 +1,79 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.item.Food; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class HungerLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.HUNGER); + + private final int hunger; + + public HungerLockKey(int hunger) { + if (hunger < 0) { + //TODO: Add whatever information is needed here for a better error message + throw new IllegalArgumentException(); + } + this.hunger = hunger; + } + + @Nullable + public static HungerLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + return fromItem(stack.getItem()); + } else if (object instanceof Item) { + return fromItem((Item) object); + } else if (object instanceof Food) { + return fromFood((Food) object); + } + return null; + } + + @Nullable + private static HungerLockKey fromItem(@Nonnull Item item) { + return item.isFood() ? fromFood(item.getFood()) : null; + } + + @Nullable + private static HungerLockKey fromFood(@Nullable Food food) { + return food == null ? null : new HungerLockKey(food.getHealing()); + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof HungerLockKey && hunger >= ((HungerLockKey) o).hunger; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public int hashCode() { + return Objects.hash(hunger); + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof HungerLockKey && hunger == ((HungerLockKey) o).hunger; + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java new file mode 100644 index 0000000..ad74882 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java @@ -0,0 +1,55 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; + +public class ItemLockKey extends NBTLockKey { + + @Nonnull + private Item item; + + public ItemLockKey(@Nonnull Item item) { + this(item, null); + } + + public ItemLockKey(@Nonnull Item item, @Nullable CompoundNBT nbt) { + super(nbt); + this.item = item; + } + + @Nullable + public static ItemLockKey fromItemStack(@Nonnull ItemStack stack) { + return stack.isEmpty() ? null : new ItemLockKey(stack.getItem(), stack.getTag()); + + //TODO: Add case for block and for blockstate (or maybe just add a BlockStateLockKey) + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return isNotFuzzy() ? this : new ItemLockKey(item); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof ItemLockKey)) { + return false; + } + ItemLockKey other = (ItemLockKey) o; + return item == other.item && Objects.equals(nbt, other.nbt); + } + + @Override + public int hashCode() { + return Objects.hash(item, nbt); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java new file mode 100644 index 0000000..6afdbb1 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java @@ -0,0 +1,102 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; + +public class ModLockKey extends NBTLockKey { + + @Nonnull + private final String modName; + + public ModLockKey(@Nonnull String modName) { + this(modName, null); + } + + public ModLockKey(@Nonnull String modName, @Nullable CompoundNBT nbt) { + super(nbt); + this.modName = modName.toLowerCase(); + } + + @Nullable + public static ModLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + return fromItem(stack.getItem(), stack.getTag()); + } else if (object instanceof Item) { + return fromItem((Item) object, null); + } else if (object instanceof BlockState) { + return fromRegistryName(((BlockState) object).getBlock().getRegistryName(), null); + } else if (object instanceof Block) { + return fromRegistryName(((Block) object).getRegistryName(), null); + } else if (object instanceof FluidStack) { + FluidStack stack = (FluidStack) object; + if (stack.isEmpty()) { + return null; + } + return fromFluid(stack.getFluid(), stack.getTag()); + } else if (object instanceof Fluid) { + return fromFluid((Fluid) object, null); + } else if (object instanceof FluidState) { + return fromFluid(((FluidState) object).getFluid(), null); + } + //TODO: Support getting from things that implement IForgeRegistry?? + return null; + } + + @Nullable + private static ModLockKey fromItem(@Nonnull Item item, @Nullable CompoundNBT nbt) { + return item == Items.AIR ? null : fromRegistryName(item.getRegistryName(), nbt); + } + + @Nullable + private static ModLockKey fromFluid(@Nonnull Fluid fluid, @Nullable CompoundNBT nbt) { + return fluid == Fluids.EMPTY ? null : fromRegistryName(fluid.getRegistryName(), nbt); + } + + @Nullable + private static ModLockKey fromRegistryName(@Nullable ResourceLocation registryName, @Nullable CompoundNBT nbt) { + //If the registry name is somehow null we can't instantiate a new mod lock + // Should never happen but gets rid of the null pointer warning + return registryName == null ? null : new ModLockKey(registryName.getNamespace(), nbt); + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return isNotFuzzy() ? this : new ModLockKey(modName); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ModLockKey) { + ModLockKey other = (ModLockKey) o; + return modName.equals(other.modName) && Objects.equals(nbt, other.nbt); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(modName, nbt); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java new file mode 100644 index 0000000..5cd0c64 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java @@ -0,0 +1,82 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.item.Food; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +public class SaturationLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.SATURATION); + + private final float saturation; + + public SaturationLockKey(float saturation) { + if (saturation < 0) { + //TODO: Add whatever information is needed here for a better error message + throw new IllegalArgumentException(); + } + this.saturation = saturation; + } + + @Nullable + public static SaturationLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + return fromItem(stack.getItem()); + } else if (object instanceof Item) { + return fromItem((Item) object); + } else if (object instanceof Food) { + return fromFood((Food) object); + } + return null; + } + + @Nullable + private static SaturationLockKey fromItem(@Nonnull Item item) { + return item.isFood() ? fromFood(item.getFood()) : null; + } + + @Nullable + private static SaturationLockKey fromFood(@Nullable Food food) { + //TODO: Check if the saturation is accurate or if it is what used to be saturation modifier + // If it is old equiv then it should be + // saturation = food.getHealing() * food.getSaturation() * 2f; + return food == null ? null : new SaturationLockKey(food.getSaturation()); + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof SaturationLockKey && saturation >= ((SaturationLockKey) o).saturation; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public int hashCode() { + return Objects.hash(saturation); + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof SaturationLockKey && saturation == ((SaturationLockKey) o).saturation; + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java new file mode 100644 index 0000000..9b40b23 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java @@ -0,0 +1,24 @@ +package com.teamacronymcoders.epos.locks.keys.entity; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; + +public class EntityDamageKey extends EntityLockKey { + + public EntityDamageKey(EntityType entityType) { + super(entityType); + } + + @Nullable + public static EntityDamageKey fromObject(@Nonnull Object object) { + EntityType type = getEntityType(object); + return type == null ? null : new EntityDamageKey<>(type); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof EntityDamageKey && super.equals(obj); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityLockKey.java new file mode 100644 index 0000000..7f99c28 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityLockKey.java @@ -0,0 +1,37 @@ +package com.teamacronymcoders.epos.locks.keys.entity; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; + +public abstract class EntityLockKey implements ILockKey { + + @Nonnull + private final EntityType entityType; + + protected EntityLockKey(@Nonnull EntityType entityType) { + this.entityType = entityType; + } + + @Nullable + protected static EntityType getEntityType(@Nonnull Object object) { + if (object instanceof Entity) { + return ((Entity) object).getType(); + } else if (object instanceof EntityType) { + return (EntityType) object; + } + return null; + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof EntityLockKey && entityType.equals(((EntityLockKey) obj).entityType); + } + + @Override + public int hashCode() { + return entityType.hashCode(); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java new file mode 100644 index 0000000..1385000 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java @@ -0,0 +1,24 @@ +package com.teamacronymcoders.epos.locks.keys.entity; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; + +public class EntityMountKey extends EntityLockKey { + + public EntityMountKey(EntityType entityType) { + super(entityType); + } + + @Nullable + public static EntityMountKey fromObject(@Nonnull Object object) { + EntityType type = getEntityType(object); + return type == null ? null : new EntityMountKey<>(type); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof EntityMountKey && super.equals(obj); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java new file mode 100644 index 0000000..2e8911d --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java @@ -0,0 +1,24 @@ +package com.teamacronymcoders.epos.locks.keys.entity; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; + +public class EntityTameKey extends EntityLockKey { + + public EntityTameKey(EntityType entityType) { + super(entityType); + } + + @Nullable + public static EntityTameKey fromObject(@Nonnull Object object) { + EntityType type = getEntityType(object); + return type == null ? null : new EntityTameKey<>(type); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof EntityTameKey && super.equals(obj); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java new file mode 100644 index 0000000..f035f01 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java @@ -0,0 +1,61 @@ +package com.teamacronymcoders.epos.locks.keys.harvest; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.ItemStack; + +public class BlockHarvestLockKey extends HarvestLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.BLOCK_HARVEST); + + public BlockHarvestLockKey(int harvestLevel) { + super(harvestLevel); + } + + @Nullable + public static BlockHarvestLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + Block block = Block.getBlockFromItem(stack.getItem()); + return block == Blocks.AIR ? null : new BlockHarvestLockKey(block.getHarvestLevel(block.getDefaultState())); + } else if (object instanceof BlockState) { + return new BlockHarvestLockKey(((BlockState) object).getHarvestLevel()); + } else if (object instanceof Block) { + Block block = (Block) object; + return new BlockHarvestLockKey(block.getHarvestLevel(block.getDefaultState())); + } + return null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof BlockHarvestLockKey && harvestLevel >= ((BlockHarvestLockKey) o).harvestLevel; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof BlockHarvestLockKey && harvestLevel == ((BlockHarvestLockKey) o).harvestLevel; + } + + @Override + public int hashCode() { + return Objects.hash(harvestLevel); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java new file mode 100644 index 0000000..0e2d244 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java @@ -0,0 +1,21 @@ +package com.teamacronymcoders.epos.locks.keys.harvest; + +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; + +public abstract class HarvestLockKey implements IFuzzyLockKey { + + protected final int harvestLevel; + + protected HarvestLockKey(int harvestLevel) { + if (harvestLevel < 0) { + //TODO: Add whatever information is needed here for a better error message + throw new IllegalArgumentException(); + } + this.harvestLevel = harvestLevel; + } + + @Override + public boolean isNotFuzzy() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java new file mode 100644 index 0000000..43d87fd --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java @@ -0,0 +1,104 @@ +package com.teamacronymcoders.epos.locks.keys.harvest; + +import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.ToolType; + +//TODO: Add back in some form of support based on tool type +// Or should that be part of the logic handler abilities that merges this with another for handling specific tool types +public class ToolHarvestLockKey extends HarvestLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.TOOL_HARVEST); + + @Nonnull + private final Map typeLevels; + @Nullable + private final ToolType toolType; + + public ToolHarvestLockKey(@Nullable ToolType toolType, int harvestLevel) { + super(harvestLevel); + this.toolType = toolType; + this.typeLevels = new HashMap<>(); + } + + private ToolHarvestLockKey(@Nonnull Map typeLevels, int harvestLevel) { + super(harvestLevel); + this.toolType = null; + this.typeLevels = typeLevels; + } + + @Nullable + public static ToolHarvestLockKey fromItemStack(@Nonnull ItemStack stack) { + if (stack.isEmpty()) { + return null; + } + int highestLevel = -1; + Item item = stack.getItem(); + Map typeLevels = new HashMap<>(); + for (ToolType type : item.getToolTypes(stack)) { + int level = item.getHarvestLevel(stack, type, null, null); + if (level < 0) { + continue; + } + typeLevels.put(type, level); + if (level > highestLevel) { + highestLevel = level; + } + } + //TODO: Decide if it matches only one tool type if it should just be that type instead of it as a map + // Note: Would have to rewrite fuzzyEquals implementation + return highestLevel == -1 ? null : new ToolHarvestLockKey(typeLevels, highestLevel); + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + if (o == this) { + return true; + } + if (o instanceof ToolHarvestLockKey) { + ToolHarvestLockKey toolLock = (ToolHarvestLockKey) o; + if (harvestLevel >= toolLock.harvestLevel) { + if (toolLock.toolType == null) { + return toolType == null; + } + return toolLock.typeLevels.keySet().stream().noneMatch(s -> !typeLevels.containsKey(s) || typeLevels.get(s) < toolLock.typeLevels.get(s)); + } + } + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ToolHarvestLockKey) { + ToolHarvestLockKey toolLock = (ToolHarvestLockKey) o; + if (toolType == null) { + return toolLock.toolType == null && harvestLevel == toolLock.harvestLevel; + } + return harvestLevel == toolLock.harvestLevel && toolType.equals(toolLock.toolType); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(toolType, harvestLevel); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java new file mode 100644 index 0000000..6f832b3 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java @@ -0,0 +1,82 @@ +package com.teamacronymcoders.epos.locks.keys.tag; + +import com.teamacronymcoders.epos.api.EposAPI; +import com.teamacronymcoders.epos.api.locks.keys.IParentLockKey; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.FluidState; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; + +//TODO: Javadoc, this is basically a wrapper for TagLockKey to be able to get the requirements of all the different tags on an item/block/etc +public class ParentTagLockKey implements IParentLockKey { + + @Nonnull + private final Collection tags; + @Nullable + private final CompoundNBT nbt; + + public ParentTagLockKey(@Nonnull Collection tags) { + this(tags, null); + } + + public ParentTagLockKey(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { + this.tags = tags; + this.nbt = nbt == null || nbt.isEmpty() ? null : nbt; + } + + @Nullable + public static ParentTagLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + return fromItem(stack.getItem(), stack.getTag()); + } else if (object instanceof Item) { + return fromItem((Item) object, null); + } else if (object instanceof BlockState) { + return fromTags(((BlockState) object).getBlock().getTags()); + } else if (object instanceof Block) { + return fromTags(((Block) object).getTags()); + } else if (object instanceof FluidStack) { + return fromTags((((FluidStack) object).getFluid()).getTags()); + } else if (object instanceof Fluid) { + return fromTags(((Fluid) object).getTags()); + } else if (object instanceof FluidState) { + return fromTags(((FluidState) object).getFluid().getTags()); + } + return null; + } + + @Nullable + private static ParentTagLockKey fromItem(@Nonnull Item item, @Nullable CompoundNBT nbt) { + Collection tags = item.getTags(); + return tags.isEmpty() ? null : new ParentTagLockKey(tags, nbt); + } + + @Nullable + private static ParentTagLockKey fromTags(@Nonnull Collection tags) { + return tags.isEmpty() ? null : new ParentTagLockKey(tags); + } + + @Nonnull + @Override + public List getSubRequirements() { + List requirements = new ArrayList<>(); + for (ResourceLocation location : tags) { + requirements.addAll(EposAPI.LOCK_REGISTRY.getFuzzyRequirements(new TagLockKey(location, nbt))); + } + return requirements; + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java new file mode 100644 index 0000000..43e5e14 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java @@ -0,0 +1,46 @@ +package com.teamacronymcoders.epos.locks.keys.tag; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ResourceLocation; + +//TODO: Do we want a param that says "what type" the tag is for (would it even make sense to have one like that) +public class TagLockKey extends NBTLockKey { + + private final ResourceLocation tag; + + public TagLockKey(ResourceLocation tag) { + this(tag, null); + } + + public TagLockKey(@Nonnull ResourceLocation tag, @Nullable CompoundNBT nbt) { + super(nbt); + this.tag = tag; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return isNotFuzzy() ? this : new TagLockKey(tag); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof TagLockKey && tag.equals(((TagLockKey) o).tag)) { + return getNBT() == null ? ((TagLockKey) o).getNBT() == null : getNBT().equals(((TagLockKey) o).getNBT()); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(tag, nbt); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/JUnitTest.java b/src/test/java/com/teamacronymcoders/epos/JUnitTest.java new file mode 100644 index 0000000..89e81ff --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/JUnitTest.java @@ -0,0 +1,15 @@ +package com.teamacronymcoders.epos; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Test JUnit") +class JUnitTest { + + @Test + @DisplayName("Ensure JUnit is working properly") + void test() { + Assertions.assertTrue(true); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/TestJUnit.java b/src/test/java/com/teamacronymcoders/epos/TestJUnit.java deleted file mode 100644 index 05e0e54..0000000 --- a/src/test/java/com/teamacronymcoders/epos/TestJUnit.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.teamacronymcoders.epos; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -public class TestJUnit { - - @Test - public void test() { - //Ensure JUnit is working properly - assertTrue(true); - } -} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java new file mode 100644 index 0000000..30848fb --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java @@ -0,0 +1,43 @@ +package com.teamacronymcoders.epos.api.locks; + +import com.teamacronymcoders.epos.api.EposAPI; +import com.teamacronymcoders.epos.api.locks.keys.DoubleLockKey; +import com.teamacronymcoders.epos.api.locks.keys.IntegerLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ListLockKey; +import com.teamacronymcoders.epos.api.locks.keys.StringLockKey; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.SimpleRequirement; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Test Lock Registry.") +class LockAPITest { + + @BeforeAll + static void registerLockTypes() { + EposAPI.LOCK_REGISTRY.registerLockType(DoubleLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerLockType(IntegerLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerLockType(ListLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof String ? new StringLockKey((String) object) : null); + } + + @Test + @DisplayName("Test adding, and then retrieving by a simple lock key") + void simpleAddRetrieve() { + StringLockKey lockKey = new StringLockKey("Key"); + List requirements = new ArrayList<>(); + String name = "Requirement"; + requirements.add(new SimpleRequirement(name)); + EposAPI.LOCK_REGISTRY.addLockByKey(lockKey, requirements); + List fromKey = EposAPI.LOCK_REGISTRY.getRequirementsByKey(lockKey); + Assertions.assertEquals(requirements.size(), fromKey.size()); + //It is not empty as we know it is the same size as our initial + IRequirement requirement = fromKey.get(0); + Assertions.assertTrue(requirement instanceof SimpleRequirement); + Assertions.assertEquals(name, ((SimpleRequirement) requirement).getName()); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java new file mode 100644 index 0000000..dd2ff69 --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java @@ -0,0 +1,9 @@ +package com.teamacronymcoders.epos.api.locks; + +import org.junit.jupiter.api.DisplayName; + +@DisplayName("Test Lock Implementation.") +class LocksTest { + + //TODO: Add a test for NBT comparision, but mainly this is waiting for the MC JUnit support stuff +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/DoubleLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/DoubleLockKey.java new file mode 100644 index 0000000..8c6ba67 --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/DoubleLockKey.java @@ -0,0 +1,63 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import com.teamacronymcoders.epos.api.locks.IGenericFuzzyLockType; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class DoubleLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(new IGenericFuzzyLockType() {}); + + private final double value; + + public DoubleLockKey(double value) { + this.value = value; + } + + @Nullable + public static DoubleLockKey fromObject(@Nonnull Object object) { + if (object instanceof Double) { + return new DoubleLockKey((Double) object); + } else if (object instanceof Integer) { + return new DoubleLockKey((Integer) object); + } else if (object instanceof Long) { + return new DoubleLockKey((Long) object); + } else if (object instanceof Float) { + return new DoubleLockKey((Float) object); + } else if (object instanceof String) { + try { + return new DoubleLockKey(Double.parseDouble((String) object)); + } catch (NumberFormatException ignored) { + //Not a valid double + } + } + return null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof DoubleLockKey && value >= ((DoubleLockKey) o).value; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Nonnull + @Override + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof DoubleLockKey && value == ((DoubleLockKey) o).value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/IntegerLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/IntegerLockKey.java new file mode 100644 index 0000000..67e3953 --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/IntegerLockKey.java @@ -0,0 +1,57 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import com.teamacronymcoders.epos.api.locks.IGenericFuzzyLockType; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class IntegerLockKey implements IFuzzyLockKey { + + private static final GenericLockKey NOT_FUZZY = new GenericLockKey(new IGenericFuzzyLockType() {}); + + private final int value; + + public IntegerLockKey(int value) { + this.value = value; + } + + @Nullable + public static IntegerLockKey fromObject(@Nonnull Object object) { + if (object instanceof Integer) { + return new IntegerLockKey((Integer) object); + } else if (object instanceof String) { + try { + return new IntegerLockKey(Integer.parseInt((String) object)); + } catch (NumberFormatException ignored) { + //Not a valid integer + } + } + return null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof IntegerLockKey && value >= ((IntegerLockKey) o).value; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Nonnull + @Override + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof IntegerLockKey && value == ((IntegerLockKey) o).value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java new file mode 100644 index 0000000..cf959d7 --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java @@ -0,0 +1,38 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import com.teamacronymcoders.epos.api.EposAPI; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ListLockKey implements IParentLockKey { + + private final List values; + + private ListLockKey(List values) { + this.values = values; + } + + @Nullable + public static ListLockKey fromObject(@Nonnull Object object) { + if (object instanceof List) { + return new ListLockKey<>((List) object); + } else if (object instanceof String) { + return new ListLockKey<>(Arrays.asList(((String) object).split("\\s*,\\s*"))); + } + return null; + } + + @Nonnull + @Override + public List getSubRequirements() { + List requirements = new ArrayList<>(); + for (TYPE value : values) { + requirements.addAll(EposAPI.LOCK_REGISTRY.getLocks(value)); + } + return requirements; + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java new file mode 100644 index 0000000..9e65f6a --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java @@ -0,0 +1,23 @@ +package com.teamacronymcoders.epos.api.locks.keys; + +import javax.annotation.Nonnull; + +public class StringLockKey implements ILockKey { + + @Nonnull + private final String value; + + public StringLockKey(@Nonnull String value) { + this.value = value; + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof StringLockKey && value.equals(((StringLockKey) obj).value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java new file mode 100644 index 0000000..38efc8e --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java @@ -0,0 +1,33 @@ +package com.teamacronymcoders.epos.api.requirements; + +import javax.annotation.Nonnull; + +/** + * Simple implementation of IRequirement that can be compared by the name it got passed. + * + * Used for testing locks + */ +public class SimpleRequirement implements IRequirement { + + @Nonnull + private final String name; + + public SimpleRequirement(@Nonnull String name) { + this.name = name; + } + + @Nonnull + public String getName() { + return name; + } + + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof SimpleRequirement && name.equals(((SimpleRequirement) obj).name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} \ No newline at end of file From f675c2bf0095caa7d691680507daaf45cfc2a1fd Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Wed, 4 Sep 2019 14:54:59 -0400 Subject: [PATCH 03/14] Cleanup a bunch of TODOs and sketch out ideas for some more tests --- .../epos/api/locks/LockRegistry.java | 8 ++++ .../epos/api/locks/keys/GenericLockKey.java | 2 - .../epos/api/locks/keys/IParentLockKey.java | 7 ++-- .../java/com/teamacronymcoders/epos/Epos.java | 3 ++ .../epos/locks/DefaultLocks.java | 1 - .../epos/locks/keys/ArmorLockKey.java | 3 +- .../locks/keys/ArmorToughnessLockKey.java | 3 +- .../epos/locks/keys/AttackDamageLockKey.java | 12 +----- .../epos/locks/keys/HungerLockKey.java | 3 +- .../epos/locks/keys/ItemLockKey.java | 1 - .../epos/locks/keys/ModLockKey.java | 38 +++++-------------- .../epos/locks/keys/SaturationLockKey.java | 8 +--- .../locks/keys/harvest/HarvestLockKey.java | 3 +- .../epos/locks/keys/tag/ParentTagLockKey.java | 21 ++++------ .../epos/api/locks/LockAPITest.java | 27 +++++++++++++ .../epos/api/locks/LocksTest.java | 2 +- .../epos/api/locks/NBTLockKeyTest.java | 34 +++++++++++++++++ 17 files changed, 101 insertions(+), 75 deletions(-) create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java index bbc4bcb..77818fa 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java @@ -30,6 +30,14 @@ public void registerLockType(@Nonnull ILockKeyCreator requirements) { if (key instanceof GenericLockKey || requirements.isEmpty()) { //Don't allow having locks on the generic key that is just for when there isn't enough information about a fuzzy lock key diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java index b551fbd..ddebb18 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/GenericLockKey.java @@ -14,13 +14,11 @@ public GenericLockKey(@Nonnull IGenericFuzzyLockType type) { @Override public boolean equals(Object o) { - //TODO: Verify this is correct even when used via an enum return o == this || o instanceof GenericLockKey && type.equals(((GenericLockKey) o).type); } @Override public int hashCode() { - //TODO: Verify this is the same even when used via an enum return type.hashCode(); } } \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java index aeeb1f4..53ca9c0 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java @@ -2,18 +2,17 @@ import com.teamacronymcoders.epos.api.locks.LockRegistry; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import java.util.Collection; import java.util.List; import javax.annotation.Nonnull; public interface IParentLockKey extends ILockKey { /** - * Retrieves any sub requirements this key may have. This usually can be implemented by calling {@link LockRegistry#getLocks(Class, Object[])} + * Retrieves any sub requirements this key may have. This usually can be implemented by calling {@link LockRegistry#getLocks(Collection)}}. * - * @return A RequirementHolder of the sub requirements. + * @return A List of all the sub requirements. */ @Nonnull List getSubRequirements(); - //TODO: Update javadocs reason this is a list is so that the higher tier logic handlers can decide how to merge ALL the different requirements together - // This is not a set in case something wants to know if there are duplicates and merge them differently } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/Epos.java b/src/main/java/com/teamacronymcoders/epos/Epos.java index 73269af..1a9d14a 100644 --- a/src/main/java/com/teamacronymcoders/epos/Epos.java +++ b/src/main/java/com/teamacronymcoders/epos/Epos.java @@ -9,6 +9,7 @@ import com.teamacronymcoders.epos.characterstats.CharacterStats; import com.teamacronymcoders.epos.configs.EposClientConfig; import com.teamacronymcoders.epos.feature.EposModules; +import com.teamacronymcoders.epos.locks.DefaultLocks; import com.teamacronymcoders.epos.json.JsonLoader; import com.teamacronymcoders.epos.json.jsondirector.RegistryJsonDirector; import com.teamacronymcoders.epos.json.jsonprovider.PathJsonProvider; @@ -47,6 +48,8 @@ protected void initModules() { @SuppressWarnings("unused") private void setup(final FMLCommonSetupEvent event) { CapabilityManager.INSTANCE.register(ICharacterStats.class, NBTCapabilityStorage.create(), CharacterStats::new); + + DefaultLocks.registerKeyLookups(); } private void serverStart(FMLServerAboutToStartEvent event) { diff --git a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java index 04170e9..0c22393 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java @@ -20,7 +20,6 @@ public class DefaultLocks { - //TODO: Call this from somewhere public static void registerKeyLookups() { //ItemLockKey EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ItemLockKey.fromItemStack((ItemStack) object) : null); diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java index 65460ce..ab7e878 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java @@ -22,8 +22,7 @@ public class ArmorLockKey implements IFuzzyLockKey { public ArmorLockKey(double armor) { if (armor < 0) { - //TODO: Add whatever information is needed here for a better error message - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Armor value must be greater than or equal to zero. Received: '" + armor + "'."); } this.armor = armor; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java index c8a079a..b2ce91a 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java @@ -22,8 +22,7 @@ public class ArmorToughnessLockKey implements IFuzzyLockKey { public ArmorToughnessLockKey(double toughness) { if (toughness < 0) { - //TODO: Add whatever information is needed here for a better error message - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Armor toughness must be greater than or equal to zero. Received: '" + toughness + "'."); } this.toughness = toughness; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java index 73aaca5..466fb75 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java @@ -23,8 +23,7 @@ public class AttackDamageLockKey implements IFuzzyLockKey { public AttackDamageLockKey(double attackDamage) { if (attackDamage < 0) { - //TODO: Add whatever information is needed here for a better error message - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Damage value must be greater than or equal to zero. Received: '" + attackDamage + "'."); } this.attackDamage = attackDamage; } @@ -35,17 +34,8 @@ public static AttackDamageLockKey fromItemStack(@Nonnull ItemStack stack) { return null; } Item item = stack.getItem(); - //TODO: Decide if we should also check offhand Multimap attributeModifiers = item.getAttributeModifiers(EquipmentSlotType.MAINHAND, stack); Collection damage = attributeModifiers.get(SharedMonsterAttributes.ATTACK_DAMAGE.getName()); - /* - //TODO: This is for compat with TConstruct's ranged weapons probably can just be deleted or something - if (damage.isEmpty() && TinkersCompatHandler.ENABLED) {//For ranged tinker's weapons like the shuriken - if (item instanceof slimeknights.tconstruct.library.tools.ranged.IProjectile) { - attributeModifiers = ((slimeknights.tconstruct.library.tools.ranged.IProjectile) item).getProjectileAttributeModifier(stack); - damage = attributeModifiers.get(SharedMonsterAttributes.ATTACK_DAMAGE.getName()); - } - }*/ return damage.isEmpty() ? null : new AttackDamageLockKey(damage.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D)); } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java index 0e73ac5..99cd612 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java @@ -19,8 +19,7 @@ public class HungerLockKey implements IFuzzyLockKey { public HungerLockKey(int hunger) { if (hunger < 0) { - //TODO: Add whatever information is needed here for a better error message - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Hunger value must be greater than or equal to zero. Received: '" + hunger + "'."); } this.hunger = hunger; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java index ad74882..6b4a416 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java @@ -26,7 +26,6 @@ public ItemLockKey(@Nonnull Item item, @Nullable CompoundNBT nbt) { @Nullable public static ItemLockKey fromItemStack(@Nonnull ItemStack stack) { return stack.isEmpty() ? null : new ItemLockKey(stack.getItem(), stack.getTag()); - //TODO: Add case for block and for blockstate (or maybe just add a BlockStateLockKey) } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java index 6afdbb1..cd9a6b0 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java @@ -5,17 +5,13 @@ import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.fluid.Fluid; import net.minecraft.fluid.FluidState; -import net.minecraft.fluid.Fluids; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.registries.IForgeRegistryEntry; public class ModLockKey extends NBTLockKey { @@ -33,47 +29,33 @@ public ModLockKey(@Nonnull String modName, @Nullable CompoundNBT nbt) { @Nullable public static ModLockKey fromObject(@Nonnull Object object) { - if (object instanceof ItemStack) { + if (object instanceof IForgeRegistryEntry) { + return fromRegistryEntry((IForgeRegistryEntry) object, null); + } else if (object instanceof ItemStack) { ItemStack stack = (ItemStack) object; if (stack.isEmpty()) { return null; } - return fromItem(stack.getItem(), stack.getTag()); - } else if (object instanceof Item) { - return fromItem((Item) object, null); + return fromRegistryEntry(stack.getItem(), stack.getTag()); } else if (object instanceof BlockState) { - return fromRegistryName(((BlockState) object).getBlock().getRegistryName(), null); - } else if (object instanceof Block) { - return fromRegistryName(((Block) object).getRegistryName(), null); + return fromRegistryEntry(((BlockState) object).getBlock(), null); } else if (object instanceof FluidStack) { FluidStack stack = (FluidStack) object; if (stack.isEmpty()) { return null; } - return fromFluid(stack.getFluid(), stack.getTag()); - } else if (object instanceof Fluid) { - return fromFluid((Fluid) object, null); + return fromRegistryEntry(stack.getFluid(), stack.getTag()); } else if (object instanceof FluidState) { - return fromFluid(((FluidState) object).getFluid(), null); + return fromRegistryEntry(((FluidState) object).getFluid(), null); } - //TODO: Support getting from things that implement IForgeRegistry?? return null; } @Nullable - private static ModLockKey fromItem(@Nonnull Item item, @Nullable CompoundNBT nbt) { - return item == Items.AIR ? null : fromRegistryName(item.getRegistryName(), nbt); - } - - @Nullable - private static ModLockKey fromFluid(@Nonnull Fluid fluid, @Nullable CompoundNBT nbt) { - return fluid == Fluids.EMPTY ? null : fromRegistryName(fluid.getRegistryName(), nbt); - } - - @Nullable - private static ModLockKey fromRegistryName(@Nullable ResourceLocation registryName, @Nullable CompoundNBT nbt) { + private static ModLockKey fromRegistryEntry(@Nonnull IForgeRegistryEntry registryEntry, @Nullable CompoundNBT nbt) { //If the registry name is somehow null we can't instantiate a new mod lock // Should never happen but gets rid of the null pointer warning + ResourceLocation registryName = registryEntry.getRegistryName(); return registryName == null ? null : new ModLockKey(registryName.getNamespace(), nbt); } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java index 5cd0c64..0db2f8e 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java @@ -19,8 +19,7 @@ public class SaturationLockKey implements IFuzzyLockKey { public SaturationLockKey(float saturation) { if (saturation < 0) { - //TODO: Add whatever information is needed here for a better error message - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Saturation value must be greater than or equal to zero. Received: '" + saturation + "'."); } this.saturation = saturation; } @@ -48,10 +47,7 @@ private static SaturationLockKey fromItem(@Nonnull Item item) { @Nullable private static SaturationLockKey fromFood(@Nullable Food food) { - //TODO: Check if the saturation is accurate or if it is what used to be saturation modifier - // If it is old equiv then it should be - // saturation = food.getHealing() * food.getSaturation() * 2f; - return food == null ? null : new SaturationLockKey(food.getSaturation()); + return food == null ? null : new SaturationLockKey(food.getHealing() * food.getSaturation() * 2F); } @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java index 0e2d244..6fc6a04 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java @@ -8,8 +8,7 @@ public abstract class HarvestLockKey implements IFuzzyLockKey { protected HarvestLockKey(int harvestLevel) { if (harvestLevel < 0) { - //TODO: Add whatever information is needed here for a better error message - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Harvest level must be greater than or equal to zero. Received: '" + harvestLevel + "'."); } this.harvestLevel = harvestLevel; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java index 6f832b3..3077fc2 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java @@ -18,7 +18,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; -//TODO: Javadoc, this is basically a wrapper for TagLockKey to be able to get the requirements of all the different tags on an item/block/etc public class ParentTagLockKey implements IParentLockKey { @Nonnull @@ -26,10 +25,6 @@ public class ParentTagLockKey implements IParentLockKey { @Nullable private final CompoundNBT nbt; - public ParentTagLockKey(@Nonnull Collection tags) { - this(tags, null); - } - public ParentTagLockKey(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { this.tags = tags; this.nbt = nbt == null || nbt.isEmpty() ? null : nbt; @@ -42,15 +37,16 @@ public static ParentTagLockKey fromObject(@Nonnull Object object) { if (stack.isEmpty()) { return null; } - return fromItem(stack.getItem(), stack.getTag()); + return fromTags(stack.getItem().getTags(), stack.getTag()); } else if (object instanceof Item) { - return fromItem((Item) object, null); + return fromTags(((Item) object).getTags()); } else if (object instanceof BlockState) { return fromTags(((BlockState) object).getBlock().getTags()); } else if (object instanceof Block) { return fromTags(((Block) object).getTags()); } else if (object instanceof FluidStack) { - return fromTags((((FluidStack) object).getFluid()).getTags()); + FluidStack stack = (FluidStack) object; + return fromTags(stack.getFluid().getTags(), stack.getTag()); } else if (object instanceof Fluid) { return fromTags(((Fluid) object).getTags()); } else if (object instanceof FluidState) { @@ -60,14 +56,13 @@ public static ParentTagLockKey fromObject(@Nonnull Object object) { } @Nullable - private static ParentTagLockKey fromItem(@Nonnull Item item, @Nullable CompoundNBT nbt) { - Collection tags = item.getTags(); - return tags.isEmpty() ? null : new ParentTagLockKey(tags, nbt); + private static ParentTagLockKey fromTags(@Nonnull Collection tags) { + return fromTags(tags, null); } @Nullable - private static ParentTagLockKey fromTags(@Nonnull Collection tags) { - return tags.isEmpty() ? null : new ParentTagLockKey(tags); + private static ParentTagLockKey fromTags(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { + return tags.isEmpty() ? null : new ParentTagLockKey(tags, nbt); } @Nonnull diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java index 30848fb..f094c76 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java @@ -9,6 +9,7 @@ import com.teamacronymcoders.epos.api.requirements.SimpleRequirement; import java.util.ArrayList; import java.util.List; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -25,6 +26,14 @@ static void registerLockTypes() { EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof String ? new StringLockKey((String) object) : null); } + /** + * Ensure that the lock registry has no lock keys in it so that we don't leak keys into the next test. + */ + @AfterEach + void resetLocks() { + EposAPI.LOCK_REGISTRY.clearLocks(); + } + @Test @DisplayName("Test adding, and then retrieving by a simple lock key") void simpleAddRetrieve() { @@ -40,4 +49,22 @@ void simpleAddRetrieve() { Assertions.assertTrue(requirement instanceof SimpleRequirement); Assertions.assertEquals(name, ((SimpleRequirement) requirement).getName()); } + + @Test + @DisplayName("Test retrieval via ParentLockKey") + void fromParentLock() { + + } + + @Test + @DisplayName("Test retrieval via FuzzyLockKey") + void fromFuzzyLock() { + + } + + @Test + @DisplayName("Test retrieval across multiple lock types.") + void multiRetrieval() { + + } } \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java index dd2ff69..c90096b 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/LocksTest.java @@ -5,5 +5,5 @@ @DisplayName("Test Lock Implementation.") class LocksTest { - //TODO: Add a test for NBT comparision, but mainly this is waiting for the MC JUnit support stuff + //TODO: Add a test for the various locks implemented in Epos. This is mainly waiting for the MC JUnit support stuff } \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java new file mode 100644 index 0000000..2d7766c --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java @@ -0,0 +1,34 @@ +package com.teamacronymcoders.epos.api.locks; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Test NBTLockKey NBT comparision") +class NBTLockKeyTest { + + //TODO: Write a bunch of tests for various NBT partial comparisons + + @Test + @DisplayName("Test NBTLockKey nbt contains string check.") + void containsString() { + + } + + @Test + @DisplayName("Test NBTLockKey nbt contains partial int list.") + void containsPartialIntList() { + + } + + @Test + @DisplayName("Test NBTLockKey nbt contains partial int list, with repeated elements.") + void containsPartialIntListRepeats() { + + } + + @Test + @DisplayName("Test NBTLockKey nbt containing partial match nbt compound.") + void containsPartialCompound() { + + } +} \ No newline at end of file From 08d41ff6e61a231158b02c27704cd17c1799c5d1 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Wed, 4 Sep 2019 15:47:20 -0400 Subject: [PATCH 04/14] Implement tests for NBT comparison, and deduplicate some of the compare code for arrays --- .../epos/api/locks/keys/NBTLockKey.java | 76 ++++++------------- .../epos/api/locks/NBTLockKeyTest.java | 55 ++++++++++++-- .../epos/api/locks/NBTLockKeyTestHelper.java | 19 +++++ 3 files changed, 93 insertions(+), 57 deletions(-) create mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTestHelper.java diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java index 74b4a26..e21d2a6 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/NBTLockKey.java @@ -12,6 +12,7 @@ import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.LongArrayNBT; import net.minecraftforge.common.util.Constants; +import org.apache.commons.lang3.ArrayUtils; public abstract class NBTLockKey implements IFuzzyLockKey { @@ -22,7 +23,6 @@ protected NBTLockKey(@Nullable CompoundNBT nbt) { this.nbt = nbt == null || nbt.isEmpty() ? null : nbt; } - //TODO: Re-evaluate this and try to deduplicate the code and make sure tag list isn't checking duplicates protected static boolean similarNBT(@Nullable INBT full, @Nullable INBT partial) { if (full == null) { return partial == null; @@ -54,6 +54,8 @@ protected static boolean similarNBT(@Nullable INBT full, @Nullable INBT partial) if (fTagList.isEmpty() && !pTagList.isEmpty() || fTagList.getTagType() != pTagList.getTagType()) { return false; } + //TODO: Add similar support to this for making sure repeats get counted based on how many times they appear in partial + // This is an edge case so isn't super important for now but is something to keep in mind for (int i = 0; i < pTagList.size(); i++) { INBT pTag = pTagList.get(i); boolean hasTag = false; @@ -69,64 +71,34 @@ protected static boolean similarNBT(@Nullable INBT full, @Nullable INBT partial) } return true; case Constants.NBT.TAG_BYTE_ARRAY: - byte[] fByteArray = ((ByteArrayNBT) full).getByteArray(); - byte[] pByteArray = ((ByteArrayNBT) partial).getByteArray(); - List hits = new ArrayList<>(); - for (byte pByte : pByteArray) { - boolean hasMatch = false; - for (int i = 0; i < fByteArray.length; i++) { - if (!hits.contains(i) && pByte == fByteArray[i]) { - hits.add(i); - hasMatch = true; - break; - } - } - if (!hasMatch) { - return false; - } - } - return true; + return compareArrays(ArrayUtils.toObject(((ByteArrayNBT) full).getByteArray()), ArrayUtils.toObject(((ByteArrayNBT) partial).getByteArray())); case Constants.NBT.TAG_INT_ARRAY: - int[] fIntArray = ((IntArrayNBT) full).getIntArray(); - int[] pIntArray = ((IntArrayNBT) partial).getIntArray(); - hits = new ArrayList<>(); - for (int pInt : pIntArray) { - boolean hasMatch = false; - for (int i = 0; i < fIntArray.length; i++) { - if (!hits.contains(i) && pInt == fIntArray[i]) { - hits.add(i); - hasMatch = true; - break; - } - } - if (!hasMatch) { - return false; - } - } - return true; + return compareArrays(ArrayUtils.toObject(((IntArrayNBT) full).getIntArray()), ArrayUtils.toObject(((IntArrayNBT) partial).getIntArray())); case Constants.NBT.TAG_LONG_ARRAY: - long[] fLongArray = ((LongArrayNBT) full).getAsLongArray(); - long[] pLongArray = ((LongArrayNBT) partial).getAsLongArray(); - hits = new ArrayList<>(); - for (long pLong : pLongArray) { - boolean hasMatch = false; - for (int i = 0; i < fLongArray.length; i++) { - if (!hits.contains(i) && pLong == fLongArray[i]) { - hits.add(i); - hasMatch = true; - break; - } - } - if (!hasMatch) { - return false; - } - } - return true; + return compareArrays(ArrayUtils.toObject(((LongArrayNBT) full).getAsLongArray()), ArrayUtils.toObject(((LongArrayNBT) partial).getAsLongArray())); default: return false; } } + private static > boolean compareArrays(T[] fullArray, T[] partialArray) { + List hits = new ArrayList<>(); + for (T partial : partialArray) { + boolean hasMatch = false; + for (int i = 0; i < fullArray.length; i++) { + if (!hits.contains(i) && partial.compareTo(fullArray[i]) == 0) { + hits.add(i); + hasMatch = true; + break; + } + } + if (!hasMatch) { + return false; + } + } + return true; + } + @Nullable public CompoundNBT getNBT() { return this.nbt; diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java index 2d7766c..8bf4a49 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTest.java @@ -1,34 +1,79 @@ package com.teamacronymcoders.epos.api.locks; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import javax.annotation.Nullable; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.nbt.IntArrayNBT; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.StringNBT; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("Test NBTLockKey NBT comparision") class NBTLockKeyTest { - //TODO: Write a bunch of tests for various NBT partial comparisons + @Nullable + private CompoundNBT getTagFromJson(String json) { + try { + return JsonToNBT.getTagFromJson(json); + } catch (CommandSyntaxException ignored) { + } + return null; + } @Test - @DisplayName("Test NBTLockKey nbt contains string check.") - void containsString() { + @DisplayName("Test NBTLockKey when given the same compound, simple.") + void matchesSimple() { + INBT tag = getTagFromJson("{test: \"value\"}"); + Assertions.assertTrue(NBTLockKeyTestHelper.isNBTSimilar(tag, tag)); + } + @Test + @DisplayName("Test NBTLockKey nbt compare check using something other than compounds.") + void compareString() { + INBT tag = new StringNBT("test"); + Assertions.assertTrue(NBTLockKeyTestHelper.isNBTSimilar(tag, tag)); } @Test @DisplayName("Test NBTLockKey nbt contains partial int list.") void containsPartialIntList() { - + INBT full = new IntArrayNBT(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}); + INBT partial = new IntArrayNBT(new int[]{1, 3, 5, 8, 9}); + Assertions.assertTrue(NBTLockKeyTestHelper.isNBTSimilar(full, partial)); } @Test @DisplayName("Test NBTLockKey nbt contains partial int list, with repeated elements.") void containsPartialIntListRepeats() { - + INBT full = new IntArrayNBT(new int[]{1, 1, 1, 2, 3}); + INBT partial = new IntArrayNBT(new int[]{1, 2, 1}); + Assertions.assertTrue(NBTLockKeyTestHelper.isNBTSimilar(full, partial)); + INBT random = new IntArrayNBT(new int[]{1, 2, 3, 4, 5}); + Assertions.assertFalse(NBTLockKeyTestHelper.isNBTSimilar(full, random)); } @Test @DisplayName("Test NBTLockKey nbt containing partial match nbt compound.") void containsPartialCompound() { + INBT full = getTagFromJson("{Random: \"test\", Special: {Categories: [\"aoe\", \"harvest\", \"tool\"]}}"); + INBT partial = getTagFromJson("{Special: {Categories: [\"tool\"]}}"); + Assertions.assertTrue(NBTLockKeyTestHelper.isNBTSimilar(full, partial)); + } + @Test + @DisplayName("Test NBTLockKey when given the same complex compound.") + void matchesComplex() { + //Tag taken from a random 1.12 tinker's construct pickaxe. + INBT tag = getTagFromJson("{StatsOriginal: {AttackSpeedMultiplier: 1.0f, MiningSpeed: 3.5f, FreeModifiers: 3, Durability: 1122, HarvestLevel: 4, " + + "Attack: 3.6f}, Stats: {AttackSpeedMultiplier: 1.0f, MiningSpeed: 3.5f, FreeModifiers: 3, Durability: 1122, " + + "HarvestLevel: 4, Attack: 3.6f}, Special: {Categories: [\"aoe\", \"harvest\", \"tool\"]}, TinkerData: " + + "{Materials: [\"dark_steel\", \"ardite\", \"obsidian\"], Modifiers: [\"toolleveling\"]}, Modifiers: " + + "[{identifier: \"unnatural\", color: -9671572, level: 1}, {identifier: \"stonebound\", color: -3063280, level: 1}, " + + "{identifier: \"duritos\", color: -10478396, level: 1}, {identifier: \"toolleveling\", color: 16777215, level: 1}], " + + "Traits: [\"unnatural\", \"stonebound\", \"duritos\", \"toolleveling\"]}"); + Assertions.assertTrue(NBTLockKeyTestHelper.isNBTSimilar(tag, tag)); } } \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTestHelper.java b/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTestHelper.java new file mode 100644 index 0000000..d3e330e --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/NBTLockKeyTestHelper.java @@ -0,0 +1,19 @@ +package com.teamacronymcoders.epos.api.locks; + +import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; +import javax.annotation.Nullable; +import net.minecraft.nbt.INBT; + +/** + * This class is used to expose {@link NBTLockKey#similarNBT(INBT, INBT)} to the Test package + */ +abstract class NBTLockKeyTestHelper extends NBTLockKey { + + private NBTLockKeyTestHelper() { + super(null); + } + + static boolean isNBTSimilar(@Nullable INBT full, @Nullable INBT partial) { + return NBTLockKey.similarNBT(full, partial); + } +} \ No newline at end of file From 5b75ed709db85ed064b88beccad4cbfca2fc8df5 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Wed, 4 Sep 2019 16:12:31 -0400 Subject: [PATCH 05/14] Implement remaining tests --- .../epos/api/locks/LockAPITest.java | 36 ++++++++++++------- .../epos/api/locks/keys/ListLockKey.java | 3 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java index f094c76..b04f5e0 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java @@ -7,7 +7,7 @@ import com.teamacronymcoders.epos.api.locks.keys.StringLockKey; import com.teamacronymcoders.epos.api.requirements.IRequirement; import com.teamacronymcoders.epos.api.requirements.SimpleRequirement; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -38,33 +38,45 @@ void resetLocks() { @DisplayName("Test adding, and then retrieving by a simple lock key") void simpleAddRetrieve() { StringLockKey lockKey = new StringLockKey("Key"); - List requirements = new ArrayList<>(); - String name = "Requirement"; - requirements.add(new SimpleRequirement(name)); - EposAPI.LOCK_REGISTRY.addLockByKey(lockKey, requirements); + IRequirement requirement = new SimpleRequirement("Requirement"); + EposAPI.LOCK_REGISTRY.addLockByKey(lockKey, Collections.singletonList(requirement)); List fromKey = EposAPI.LOCK_REGISTRY.getRequirementsByKey(lockKey); - Assertions.assertEquals(requirements.size(), fromKey.size()); + Assertions.assertEquals(fromKey.size(), 1); //It is not empty as we know it is the same size as our initial - IRequirement requirement = fromKey.get(0); - Assertions.assertTrue(requirement instanceof SimpleRequirement); - Assertions.assertEquals(name, ((SimpleRequirement) requirement).getName()); + Assertions.assertTrue(fromKey.contains(requirement)); } @Test @DisplayName("Test retrieval via ParentLockKey") void fromParentLock() { - + //ListLockKey + EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("1"), Collections.singletonList(new SimpleRequirement("1"))); + EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("2"), Collections.singletonList(new SimpleRequirement("2"))); + EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("3"), Collections.singletonList(new SimpleRequirement("3"))); + List fromKey = EposAPI.LOCK_REGISTRY.getLocks("1,2,3"); + Assertions.assertEquals(fromKey.size(), 3); } @Test @DisplayName("Test retrieval via FuzzyLockKey") void fromFuzzyLock() { - + IRequirement bigRequirement = new SimpleRequirement("Requirement Big"); + IRequirement smallRequirement = new SimpleRequirement("Requirement Small"); + EposAPI.LOCK_REGISTRY.addLockByKey(new IntegerLockKey(5), Collections.singletonList(bigRequirement)); + EposAPI.LOCK_REGISTRY.addLockByKey(new IntegerLockKey(3), Collections.singletonList(smallRequirement)); + List fromKey = EposAPI.LOCK_REGISTRY.getRequirementsByKey(new IntegerLockKey(7)); + Assertions.assertEquals(fromKey.size(), 2); + //It is not empty as we know it is the same size as our initial + Assertions.assertTrue(fromKey.contains(bigRequirement) && fromKey.contains(smallRequirement)); } @Test @DisplayName("Test retrieval across multiple lock types.") void multiRetrieval() { - + EposAPI.LOCK_REGISTRY.addLockByKey(new IntegerLockKey(1), Collections.singletonList(new SimpleRequirement("1"))); + EposAPI.LOCK_REGISTRY.addLockByKey(new DoubleLockKey(3), Collections.singletonList(new SimpleRequirement("2"))); + EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("3"), Collections.singletonList(new SimpleRequirement("3"))); + List fromKey = EposAPI.LOCK_REGISTRY.getLocks("3"); + Assertions.assertEquals(fromKey.size(), 3); } } \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java index cf959d7..af598c1 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java @@ -21,7 +21,8 @@ public static ListLockKey fromObject(@Nonnull Object object) { if (object instanceof List) { return new ListLockKey<>((List) object); } else if (object instanceof String) { - return new ListLockKey<>(Arrays.asList(((String) object).split("\\s*,\\s*"))); + String string = (String) object; + return string.contains(",") ? new ListLockKey<>(Arrays.asList(string.split("\\s*,\\s*"))) : null; } return null; } From 3bcfde8c89e094d659f6eb0f43365a831c31fd09 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Sat, 7 Sep 2019 17:23:31 -0400 Subject: [PATCH 06/14] Make a lot of the requested changes. Some more still need to be made. --- .../epos/api/locks/LockRegistry.java | 32 +++++++++-------- .../epos/locks/DefaultLocks.java | 18 +--------- .../epos/locks/keys/ArmorLockKey.java | 19 +++++------ .../locks/keys/ArmorToughnessLockKey.java | 19 +++++------ .../epos/locks/keys/AttackDamageLockKey.java | 13 +++---- .../epos/locks/keys/GenericNBTLockKey.java | 14 ++++++-- .../epos/locks/keys/HungerLockKey.java | 13 ++++--- .../epos/locks/keys/ItemLockKey.java | 10 ++++-- .../epos/locks/keys/SaturationLockKey.java | 13 ++++--- .../keys/harvest/BlockHarvestLockKey.java | 3 ++ .../locks/keys/harvest/HarvestLockKey.java | 6 ++-- .../keys/harvest/ToolHarvestLockKey.java | 8 ++++- .../epos/locks/keys/tag/ParentTagLockKey.java | 8 ++++- .../epos/utils/AttributeUtils.java | 34 +++++++++++++++++++ 14 files changed, 135 insertions(+), 75 deletions(-) create mode 100644 src/main/java/com/teamacronymcoders/epos/utils/AttributeUtils.java diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java index 77818fa..6f63e48 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java @@ -15,6 +15,7 @@ import java.util.Set; import javax.annotation.Nonnull; +//TODO: JavaDoc all methods once the RequirementCombiner system is developed, as some of the methods here may change slightly public class LockRegistry { private static final List EMPTY_REQUIREMENTS = Collections.emptyList(); @@ -23,11 +24,16 @@ public class LockRegistry { private final Map> locks = new HashMap<>(); private final Map> fuzzyLockInfo = new HashMap<>(); + /** + * Unlike the 1.12 system this has it so that each lock key has one registration for each type it can be created from Each one has to be checked when getting by type + * rather than knowing it "should" be good for that type already + * + * @param creator A Lock Key Creator that creates keys of type KEY given an object. + * @param The type of key the given lock creator is for. + */ + //TODO: Evaluate if there is any performance impact of checking against all compared to directly getting the subset that works public void registerLockType(@Nonnull ILockKeyCreator creator) { keyCreators.add(creator); - //Unlike the 1.12 system this has it so that each lock key has one registration for each type it can be created from - //Each one has to be checked when getting by type rather than knowing it "should" be good for that type already - //Does this have any negative performance impact } /** @@ -39,17 +45,15 @@ public void clearLocks() { } public void addLockByKey(@Nonnull ILockKey key, @Nonnull List requirements) { - if (key instanceof GenericLockKey || requirements.isEmpty()) { - //Don't allow having locks on the generic key that is just for when there isn't enough information about a fuzzy lock key - return; - } - locks.put(key, requirements); - - if (key instanceof IFuzzyLockKey) { - IFuzzyLockKey fuzzy = (IFuzzyLockKey) key; - if (!fuzzy.isNotFuzzy()) { - //Store the fuzzy instance in a list for the specific item - fuzzyLockInfo.computeIfAbsent(fuzzy.getNotFuzzy(), k -> new HashSet<>()).add(fuzzy); + //Don't allow having locks on the generic key that is just for when there isn't enough information about a fuzzy lock key + if (!(key instanceof GenericLockKey) && !requirements.isEmpty()) { + locks.put(key, requirements); + if (key instanceof IFuzzyLockKey) { + IFuzzyLockKey fuzzy = (IFuzzyLockKey) key; + if (!fuzzy.isNotFuzzy()) { + //Store the fuzzy instance in a list for the specific item + fuzzyLockInfo.computeIfAbsent(fuzzy.getNotFuzzy(), k -> new HashSet<>()).add(fuzzy); + } } } } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java index 0c22393..b632733 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java @@ -21,38 +21,22 @@ public class DefaultLocks { public static void registerKeyLookups() { - //ItemLockKey - EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ItemLockKey.fromItemStack((ItemStack) object) : null); - //ModLockKey + EposAPI.LOCK_REGISTRY.registerLockType(ItemLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(ModLockKey::fromObject); - //Generic lock based entirely on NBT EposAPI.LOCK_REGISTRY.registerLockType(GenericNBTLockKey::fromObject); //Ones that probably will be in an addon but for now are from CompatSkills for more test cases of seeing how the system works - - //DimensionTypeLockKey EposAPI.LOCK_REGISTRY.registerLockType(DimensionTypeLockKey::fromObject); - //EntityDamageKey EposAPI.LOCK_REGISTRY.registerLockType(EntityDamageKey::fromObject); - //EntityMountKey EposAPI.LOCK_REGISTRY.registerLockType(EntityMountKey::fromObject); - //EntityTameKey EposAPI.LOCK_REGISTRY.registerLockType(EntityTameKey::fromObject); - //ArmorLockKey EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ArmorLockKey.fromItemStack((ItemStack) object) : null); - //ArmorToughnessKey EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ArmorToughnessLockKey.fromItemStack((ItemStack) object) : null); - //AttackDamageLockKey EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? AttackDamageLockKey.fromItemStack((ItemStack) object) : null); - //HungerLockKey EposAPI.LOCK_REGISTRY.registerLockType(HungerLockKey::fromObject); - //SaturationLockKey EposAPI.LOCK_REGISTRY.registerLockType(SaturationLockKey::fromObject); - //BlockHarvestLockKey EposAPI.LOCK_REGISTRY.registerLockType(BlockHarvestLockKey::fromObject); - //ToolHarvestLockKey EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ToolHarvestLockKey.fromItemStack((ItemStack) object) : null); - //ParentTagLockKey EposAPI.LOCK_REGISTRY.registerLockType(ParentTagLockKey::fromObject); } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java index ab7e878..c3f5dd0 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java @@ -1,10 +1,11 @@ package com.teamacronymcoders.epos.locks.keys; +import com.google.common.collect.Multimap; import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; -import java.util.Collection; +import com.teamacronymcoders.epos.utils.AttributeUtils; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -20,10 +21,10 @@ public class ArmorLockKey implements IFuzzyLockKey { private final double armor; + /** + * @apiNote Ensure that the given armor value is positive. + */ public ArmorLockKey(double armor) { - if (armor < 0) { - throw new IllegalArgumentException("Armor value must be greater than or equal to zero. Received: '" + armor + "'."); - } this.armor = armor; } @@ -35,12 +36,10 @@ public static ArmorLockKey fromItemStack(@Nonnull ItemStack stack) { Item item = stack.getItem(); if (item instanceof ArmorItem) { ArmorItem armorItem = (ArmorItem) item; - double armor = armorItem.getDamageReduceAmount(); - Collection protection = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack).get(SharedMonsterAttributes.ARMOR.getName()); - if (!protection.isEmpty()) { - armor += protection.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D); - } - return new ArmorLockKey(armor); + Multimap attributeModifiers = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack); + double armor = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ARMOR, armorItem.getDamageReduceAmount()); + //Ensure that the value is actually positive + return armor < 0 ? null : new ArmorLockKey(armor); } return null; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java index b2ce91a..7352299 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java @@ -1,10 +1,11 @@ package com.teamacronymcoders.epos.locks.keys; +import com.google.common.collect.Multimap; import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; -import java.util.Collection; +import com.teamacronymcoders.epos.utils.AttributeUtils; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -20,10 +21,10 @@ public class ArmorToughnessLockKey implements IFuzzyLockKey { private final double toughness; + /** + * @apiNote Ensure that the given armor toughness value is positive. + */ public ArmorToughnessLockKey(double toughness) { - if (toughness < 0) { - throw new IllegalArgumentException("Armor toughness must be greater than or equal to zero. Received: '" + toughness + "'."); - } this.toughness = toughness; } @@ -35,12 +36,10 @@ public static ArmorToughnessLockKey fromItemStack(@Nonnull ItemStack stack) { Item item = stack.getItem(); if (item instanceof ArmorItem) { ArmorItem armorItem = (ArmorItem) item; - double toughness = armorItem.getToughness(); - Collection protection = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack).get(SharedMonsterAttributes.ARMOR_TOUGHNESS.getName()); - if (!protection.isEmpty()) { - toughness += protection.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D); - } - return new ArmorToughnessLockKey(toughness); + Multimap attributeModifiers = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack); + double toughness = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ARMOR_TOUGHNESS, armorItem.getToughness()); + //Ensure that the value is actually positive + return toughness < 0 ? null : new ArmorToughnessLockKey(toughness); } return null; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java index 466fb75..573bd65 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java @@ -5,7 +5,7 @@ import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; -import java.util.Collection; +import com.teamacronymcoders.epos.utils.AttributeUtils; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -21,10 +21,10 @@ public class AttackDamageLockKey implements IFuzzyLockKey { private final double attackDamage; + /** + * @apiNote Ensure that the given damage value is positive. + */ public AttackDamageLockKey(double attackDamage) { - if (attackDamage < 0) { - throw new IllegalArgumentException("Damage value must be greater than or equal to zero. Received: '" + attackDamage + "'."); - } this.attackDamage = attackDamage; } @@ -35,8 +35,9 @@ public static AttackDamageLockKey fromItemStack(@Nonnull ItemStack stack) { } Item item = stack.getItem(); Multimap attributeModifiers = item.getAttributeModifiers(EquipmentSlotType.MAINHAND, stack); - Collection damage = attributeModifiers.get(SharedMonsterAttributes.ATTACK_DAMAGE.getName()); - return damage.isEmpty() ? null : new AttackDamageLockKey(damage.stream().findFirst().map(AttributeModifier::getAmount).orElse(0D)); + double damage = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ATTACK_DAMAGE); + //Ensure that the value is actually positive + return damage < 0 ? null : new AttackDamageLockKey(damage); } @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java index ec85e4c..b1c455b 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java @@ -14,7 +14,10 @@ public class GenericNBTLockKey extends NBTLockKey { private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.GENERIC_NBT); - public GenericNBTLockKey(@Nullable CompoundNBT nbt) { + /** + * @apiNote Ensure that the given Compound is not empty. + */ + public GenericNBTLockKey(@Nonnull CompoundNBT nbt) { super(nbt); } @@ -22,13 +25,18 @@ public GenericNBTLockKey(@Nullable CompoundNBT nbt) { public static GenericNBTLockKey fromObject(@Nonnull Object object) { if (object instanceof ItemStack) { ItemStack stack = (ItemStack) object; - return stack.isEmpty() ? null : new GenericNBTLockKey(((ItemStack) object).getTag()); + return stack.hasTag() ? fromCompound(stack.getTag()) : null; } else if (object instanceof CompoundNBT) { - return new GenericNBTLockKey((CompoundNBT) object); + return fromCompound((CompoundNBT) object); } return null; } + @Nullable + private static GenericNBTLockKey fromCompound(@Nonnull CompoundNBT nbt) { + return nbt.isEmpty() ? null : new GenericNBTLockKey(nbt); + } + @Override @Nonnull public ILockKey getNotFuzzy() { diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java index 99cd612..2b47c10 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java @@ -17,10 +17,10 @@ public class HungerLockKey implements IFuzzyLockKey { private final int hunger; + /** + * @apiNote Ensure that the given hunger value is positive. + */ public HungerLockKey(int hunger) { - if (hunger < 0) { - throw new IllegalArgumentException("Hunger value must be greater than or equal to zero. Received: '" + hunger + "'."); - } this.hunger = hunger; } @@ -47,7 +47,12 @@ private static HungerLockKey fromItem(@Nonnull Item item) { @Nullable private static HungerLockKey fromFood(@Nullable Food food) { - return food == null ? null : new HungerLockKey(food.getHealing()); + if (food == null) { + return null; + } + int healing = food.getHealing(); + //Ensure that the value is actually positive + return healing < 0 ? null : new HungerLockKey(healing); } @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java index 6b4a416..fe659b0 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java @@ -24,9 +24,15 @@ public ItemLockKey(@Nonnull Item item, @Nullable CompoundNBT nbt) { } @Nullable - public static ItemLockKey fromItemStack(@Nonnull ItemStack stack) { - return stack.isEmpty() ? null : new ItemLockKey(stack.getItem(), stack.getTag()); + public static ItemLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + return stack.isEmpty() ? null : new ItemLockKey(stack.getItem(), stack.getTag()); + } else if (object instanceof Item) { + return new ItemLockKey((Item) object); + } //TODO: Add case for block and for blockstate (or maybe just add a BlockStateLockKey) + return null; } @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java index 0db2f8e..b7ee257 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java @@ -17,10 +17,10 @@ public class SaturationLockKey implements IFuzzyLockKey { private final float saturation; + /** + * @apiNote Ensure that the given saturation value is positive. + */ public SaturationLockKey(float saturation) { - if (saturation < 0) { - throw new IllegalArgumentException("Saturation value must be greater than or equal to zero. Received: '" + saturation + "'."); - } this.saturation = saturation; } @@ -47,7 +47,12 @@ private static SaturationLockKey fromItem(@Nonnull Item item) { @Nullable private static SaturationLockKey fromFood(@Nullable Food food) { - return food == null ? null : new SaturationLockKey(food.getHealing() * food.getSaturation() * 2F); + if (food == null) { + return null; + } + float saturation = food.getHealing() * food.getSaturation() * 2F; + //Ensure that the value is actually positive + return saturation < 0 ? null : new SaturationLockKey(saturation); } @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java index f035f01..1dc2da8 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java @@ -16,6 +16,9 @@ public class BlockHarvestLockKey extends HarvestLockKey { private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.BLOCK_HARVEST); + /** + * @apiNote Ensure that the given harvest level is positive. + */ public BlockHarvestLockKey(int harvestLevel) { super(harvestLevel); } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java index 6fc6a04..91738e2 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/HarvestLockKey.java @@ -6,10 +6,10 @@ public abstract class HarvestLockKey implements IFuzzyLockKey { protected final int harvestLevel; + /** + * @apiNote Ensure that the given harvest level is positive. + */ protected HarvestLockKey(int harvestLevel) { - if (harvestLevel < 0) { - throw new IllegalArgumentException("Harvest level must be greater than or equal to zero. Received: '" + harvestLevel + "'."); - } this.harvestLevel = harvestLevel; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java index 43d87fd..875016c 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java @@ -24,12 +24,18 @@ public class ToolHarvestLockKey extends HarvestLockKey { @Nullable private final ToolType toolType; + /** + * @apiNote Ensure that the given harvest level is positive. + */ public ToolHarvestLockKey(@Nullable ToolType toolType, int harvestLevel) { super(harvestLevel); this.toolType = toolType; this.typeLevels = new HashMap<>(); } + /** + * @apiNote Ensure that the given harvest level is positive. + */ private ToolHarvestLockKey(@Nonnull Map typeLevels, int harvestLevel) { super(harvestLevel); this.toolType = null; @@ -56,7 +62,7 @@ public static ToolHarvestLockKey fromItemStack(@Nonnull ItemStack stack) { } //TODO: Decide if it matches only one tool type if it should just be that type instead of it as a map // Note: Would have to rewrite fuzzyEquals implementation - return highestLevel == -1 ? null : new ToolHarvestLockKey(typeLevels, highestLevel); + return highestLevel < 0 || typeLevels.isEmpty() ? null : new ToolHarvestLockKey(typeLevels, highestLevel); } @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java index 3077fc2..7fd8348 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java @@ -10,6 +10,8 @@ import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.FluidState; import net.minecraft.item.Item; @@ -25,7 +27,7 @@ public class ParentTagLockKey implements IParentLockKey { @Nullable private final CompoundNBT nbt; - public ParentTagLockKey(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { + private ParentTagLockKey(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { this.tags = tags; this.nbt = nbt == null || nbt.isEmpty() ? null : nbt; } @@ -51,6 +53,10 @@ public static ParentTagLockKey fromObject(@Nonnull Object object) { return fromTags(((Fluid) object).getTags()); } else if (object instanceof FluidState) { return fromTags(((FluidState) object).getFluid().getTags()); + } else if (object instanceof Entity) { + return fromTags(((Entity) object).getType().getTags()); + } else if (object instanceof EntityType) { + return fromTags(((EntityType) object).getTags()); } return null; } diff --git a/src/main/java/com/teamacronymcoders/epos/utils/AttributeUtils.java b/src/main/java/com/teamacronymcoders/epos/utils/AttributeUtils.java new file mode 100644 index 0000000..39ee976 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/utils/AttributeUtils.java @@ -0,0 +1,34 @@ +package com.teamacronymcoders.epos.utils; + +import com.google.common.collect.Multimap; +import java.util.Collection; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.ai.attributes.AttributeModifier.Operation; +import net.minecraft.entity.ai.attributes.IAttribute; + +public class AttributeUtils { + + public static double calculateValueFromModifiers(Multimap attributeModifiers, IAttribute attribute) { + return calculateValueFromModifiers(attributeModifiers, attribute, 0); + } + + public static double calculateValueFromModifiers(Multimap attributeModifiers, IAttribute attribute, double initialValue) { + Collection modifiers = attributeModifiers.get(attribute.getName()); + for (AttributeModifier modifier : modifiers) { + Operation operation = modifier.getOperation(); + switch (operation) { + case ADDITION: + initialValue += modifier.getAmount(); + break; + case MULTIPLY_BASE: + //TODO: Figure out how we should handle MULTIPLY_BASE so that we have the correct value + //attribute.getDefaultValue() * modifier.getAmount(); + break; + case MULTIPLY_TOTAL: + initialValue *= modifier.getAmount(); + break; + } + } + return initialValue; + } +} \ No newline at end of file From 2fdeeb3d07c6facc37fce28f1843cf5d48b8caf8 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Thu, 3 Oct 2019 12:22:14 -0400 Subject: [PATCH 07/14] Prep work on creating a BlockStateLockKey, currently does not work at all --- build.gradle | 2 +- gradle.properties | 8 +- .../epos/feats/LuckyAnglerFeat.java | 4 +- .../epos/locks/DefaultLocks.java | 2 + .../epos/locks/keys/BlockStateLockKey.java | 73 +++++++++++++++++++ .../epos/locks/keys/ItemLockKey.java | 1 - .../epos/locks/keys/tag/ParentTagLockKey.java | 3 + .../item/ItemRewardEventHandler.java | 6 +- .../pathfeature/item/ItemRewardFeature.java | 4 +- 9 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java diff --git a/build.gradle b/build.gradle index 67016b7..017c91c 100644 --- a/build.gradle +++ b/build.gradle @@ -103,7 +103,7 @@ dependencies { testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junit_version}" minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - compile fg.deobf("com.hrznstudio:titanium:${titanium_version}") + compile fg.deobf("com.hrznstudio:titanium:${minecraft_version}-${titanium_version}") } task srcJar(type: Jar) { diff --git a/gradle.properties b/gradle.properties index d0f3b2b..5e23eff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,10 @@ minecraft_version=1.14.4 -forge_version=28.0.91 -mappings_version=20190904-1.14.3 +forge_version=28.1.31 +mappings_version=20191003-1.14.3 base_version=4.0.0 -junit_version=5.5.1 -titanium_version=2.1.+ +junit_version=5.5.2 +titanium_version=2.2.+ team=Team Acronym Coders group=com.teamacronymcoders diff --git a/src/main/java/com/teamacronymcoders/epos/feats/LuckyAnglerFeat.java b/src/main/java/com/teamacronymcoders/epos/feats/LuckyAnglerFeat.java index f977a52..280d5e8 100644 --- a/src/main/java/com/teamacronymcoders/epos/feats/LuckyAnglerFeat.java +++ b/src/main/java/com/teamacronymcoders/epos/feats/LuckyAnglerFeat.java @@ -27,13 +27,13 @@ public class LuckyAnglerFeat { if (entityJoinWorldEvent.getEntity() instanceof FishingBobberEntity) { SkillInfo skill = iCharacterStats.getSkills().get(NAME.toString()); FishingBobberEntity oldEntity = (FishingBobberEntity) entityJoinWorldEvent.getEntity(); - if (!oldEntity.getEntityData().contains("replaced") && oldEntity.getAngler() != null && skill != null) { + if (!oldEntity.getPersistentData().contains("replaced") && oldEntity.getAngler() != null && skill != null) { ItemStack stack = oldEntity.getAngler().getActiveItemStack(); FishingBobberEntity newEntity = new FishingBobberEntity(oldEntity.getAngler(), oldEntity.world, EnchantmentHelper.getFishingLuckBonus(stack) + skill.getLevel(), Math.max(5, EnchantmentHelper.getFishingSpeedBonus(stack) + skill.getLevel())); - newEntity.getEntityData().putBoolean("replaced", true); + newEntity.getPersistentData().putBoolean("replaced", true); entityJoinWorldEvent.getWorld().addEntity(newEntity); entityJoinWorldEvent.setCanceled(true); } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java index b632733..8f33c52 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java @@ -4,6 +4,7 @@ import com.teamacronymcoders.epos.locks.keys.ArmorLockKey; import com.teamacronymcoders.epos.locks.keys.ArmorToughnessLockKey; import com.teamacronymcoders.epos.locks.keys.AttackDamageLockKey; +import com.teamacronymcoders.epos.locks.keys.BlockStateLockKey; import com.teamacronymcoders.epos.locks.keys.DimensionTypeLockKey; import com.teamacronymcoders.epos.locks.keys.GenericNBTLockKey; import com.teamacronymcoders.epos.locks.keys.HungerLockKey; @@ -22,6 +23,7 @@ public class DefaultLocks { public static void registerKeyLookups() { EposAPI.LOCK_REGISTRY.registerLockType(ItemLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerLockType(BlockStateLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(ModLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(GenericNBTLockKey::fromObject); diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java new file mode 100644 index 0000000..b75a6be --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java @@ -0,0 +1,73 @@ +package com.teamacronymcoders.epos.locks.keys; + +import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.pattern.BlockStateMatcher; + +//TODO: Figure out the fuzzy and non fuzzy state of this. Use BlockStateMatcher to match blockstates +public class BlockStateLockKey implements IFuzzyLockKey { + + @Nonnull + private BlockState state; + + public BlockStateLockKey(@Nonnull BlockState state) { + this.state = state; + } + + @Nullable + public static BlockStateLockKey fromObject(@Nonnull Object object) { + if (object instanceof BlockState) { + return new BlockStateLockKey((BlockState) object); + } else if (object instanceof Block) { + return new BlockStateLockKey(((Block) object).getDefaultState()); + } + return null; + } + + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + if (o == this) { + return true; + } + if (o instanceof BlockStateLockKey) { + BlockStateLockKey other = (BlockStateLockKey) o; + //TODO + } + return false; + } + + @Override + public boolean isNotFuzzy() { + //TODO + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return isNotFuzzy() ? this : new BlockStateLockKey(state); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof BlockStateLockKey)) { + return false; + } + BlockStateLockKey other = (BlockStateLockKey) o; + //TODO + return false;//item == other.item && Objects.equals(nbt, other.nbt); + } + + @Override + public int hashCode() { + return Objects.hash(state); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java index fe659b0..3e1735c 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java @@ -31,7 +31,6 @@ public static ItemLockKey fromObject(@Nonnull Object object) { } else if (object instanceof Item) { return new ItemLockKey((Item) object); } - //TODO: Add case for block and for blockstate (or maybe just add a BlockStateLockKey) return null; } diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java index 7fd8348..726dfcb 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java @@ -34,6 +34,9 @@ private ParentTagLockKey(@Nonnull Collection tags, @Nullable C @Nullable public static ParentTagLockKey fromObject(@Nonnull Object object) { + //TODO: Make an easier way for third party mods to add an object -> tag list/tags system + // At that point it may make more sense for this to not exist and just directly interact with TagLockKey, + // and keep track of Tag if (object instanceof ItemStack) { ItemStack stack = (ItemStack) object; if (stack.isEmpty()) { diff --git a/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardEventHandler.java b/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardEventHandler.java index 622be8b..8929a9f 100644 --- a/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardEventHandler.java +++ b/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardEventHandler.java @@ -9,9 +9,9 @@ @Mod.EventBusSubscriber(modid = EposAPI.ID, bus = Mod.EventBusSubscriber.Bus.MOD) public class ItemRewardEventHandler { public static void onDeath(PlayerEvent.Clone event) { - if (event.getOriginal().getEntityData().contains("item_rewards")) { - CompoundNBT nbt = event.getOriginal().getEntityData().getCompound("item_rewards"); - event.getPlayer().getEntityData().put("item_rewards", nbt); + if (event.getOriginal().getPersistentData().contains("item_rewards")) { + CompoundNBT nbt = event.getOriginal().getPersistentData().getCompound("item_rewards"); + event.getPlayer().getPersistentData().put("item_rewards", nbt); } } } diff --git a/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeature.java b/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeature.java index 0b9977d..f3b732a 100644 --- a/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeature.java +++ b/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeature.java @@ -24,10 +24,10 @@ public ItemRewardFeature(String identifier, ItemStack stack) { @Override public void applyTo(LivingEntity character, ICharacterStats characterStats) { World world = character.world; - CompoundNBT entityNBT = character.getEntityData(); + CompoundNBT entityNBT = character.getPersistentData(); if (!entityNBT.contains("item_rewards")) { CompoundNBT newNBT = new CompoundNBT(); - character.getEntityData().put("item_rewards", newNBT); + character.getPersistentData().put("item_rewards", newNBT); } CompoundNBT itemRewards = entityNBT.getCompound("item_rewards"); if (itemRewards.contains(identifier)) { From c3713a5cb4b177c5be2c50a9ec0d28511c106014 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Thu, 3 Oct 2019 12:29:33 -0400 Subject: [PATCH 08/14] Run optimize imports to remove all the unused imports --- .../teamacronymcoders/epos/api/feat/Feat.java | 6 +----- .../epos/api/feat/FeatBuilder.java | 7 +++---- .../epos/api/feat/FeatEventHandler.java | 3 +-- .../epos/api/feat/Feats.java | 11 +++++----- .../epos/api/json/JsonUtils.java | 5 ++--- .../api/pathfeature/PathFeatureProvider.java | 1 - .../epos/api/pathfeature/PathFeatures.java | 2 -- .../epos/api/registry/IRegistryEntry.java | 3 +-- .../api/registry/MissingRegistryEntry.java | 3 +-- .../epos/api/registry/RegistrationEvent.java | 3 +-- .../epos/api/registry/Registry.java | 9 ++++----- .../epos/api/skill/MissingSkill.java | 3 +-- .../epos/api/skill/SkillInfo.java | 3 +-- .../epos/api/skill/Skills.java | 10 ++++------ .../java/com/teamacronymcoders/epos/Epos.java | 11 +++++----- .../epos/capability/NBTCapabilityStorage.java | 3 +-- .../PosInvHandlerCapabilityProvider.java | 5 ++--- .../epos/client/gui/GuiQuiverAddonScreen.java | 7 +++---- .../epos/configs/EposClientConfig.java | 3 +-- .../epos/container/QuiverContainer.java | 3 +-- .../ForgeRegistryEventHandler.java | 20 ++++++++++++++++--- .../epos/feats/GravelExcavatorFeat.java | 5 ++--- .../epos/feats/ImprovisedCombatFeat.java | 3 +-- .../epos/feature/quiver/QuiverItem.java | 3 +-- .../epos/json/JsonLoader.java | 7 +++---- .../json/jsonprovider/PathJsonProvider.java | 3 +-- .../epos/locks/keys/BlockStateLockKey.java | 1 - .../com/teamacronymcoders/epos/path/Path.java | 3 +-- .../item/ItemRewardFeatureProvider.java | 3 --- .../LevelUpSkillFeatureProvider.java | 3 --- .../skillxp/SkillXPFeatureProvider.java | 3 --- .../teamacronymcoders/epos/skill/Skill.java | 3 +-- .../epos/utils/BlockBreakHelper.java | 7 +++---- 33 files changed, 68 insertions(+), 97 deletions(-) diff --git a/src/api/java/com/teamacronymcoders/epos/api/feat/Feat.java b/src/api/java/com/teamacronymcoders/epos/api/feat/Feat.java index 6b340d8..3468ea9 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/feat/Feat.java +++ b/src/api/java/com/teamacronymcoders/epos/api/feat/Feat.java @@ -1,12 +1,8 @@ package com.teamacronymcoders.epos.api.feat; -import net.minecraft.util.ResourceLocation; +import java.util.List; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.registries.ForgeRegistryEntry; -import net.minecraftforge.registries.IForgeRegistry; - -import javax.annotation.Nonnull; -import java.util.List; public class Feat extends ForgeRegistryEntry { private final List> eventHandlers; diff --git a/src/api/java/com/teamacronymcoders/epos/api/feat/FeatBuilder.java b/src/api/java/com/teamacronymcoders/epos/api/feat/FeatBuilder.java index c5a1c2b..2bf5a8d 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/feat/FeatBuilder.java +++ b/src/api/java/com/teamacronymcoders/epos/api/feat/FeatBuilder.java @@ -2,6 +2,9 @@ import com.google.common.collect.Lists; import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.ParametersAreNonnullByDefault; import net.minecraft.entity.LivingEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; @@ -9,10 +12,6 @@ import net.minecraftforge.eventbus.api.Event; import org.apache.logging.log4j.util.TriConsumer; -import javax.annotation.Nonnull; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.List; - @ParametersAreNonnullByDefault public class FeatBuilder { private final ResourceLocation registryName; diff --git a/src/api/java/com/teamacronymcoders/epos/api/feat/FeatEventHandler.java b/src/api/java/com/teamacronymcoders/epos/api/feat/FeatEventHandler.java index f371550..b667583 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/feat/FeatEventHandler.java +++ b/src/api/java/com/teamacronymcoders/epos/api/feat/FeatEventHandler.java @@ -1,13 +1,12 @@ package com.teamacronymcoders.epos.api.feat; import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import java.util.Objects; import net.minecraft.entity.LivingEntity; import net.minecraft.util.ResourceLocation; import net.minecraftforge.eventbus.api.Event; import org.apache.logging.log4j.util.TriConsumer; -import java.util.Objects; - public class FeatEventHandler { public final ResourceLocation featId; public final TriConsumer eventHandler; diff --git a/src/api/java/com/teamacronymcoders/epos/api/feat/Feats.java b/src/api/java/com/teamacronymcoders/epos/api/feat/Feats.java index ea3707b..c8e056d 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/feat/Feats.java +++ b/src/api/java/com/teamacronymcoders/epos/api/feat/Feats.java @@ -5,17 +5,16 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.Maps; import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; -import net.minecraft.entity.LivingEntity; -import net.minecraft.nbt.CompoundNBT; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.eventbus.api.Event; - -import javax.annotation.Nonnull; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.eventbus.api.Event; public class Feats implements INBTSerializable { private final Map feats; diff --git a/src/api/java/com/teamacronymcoders/epos/api/json/JsonUtils.java b/src/api/java/com/teamacronymcoders/epos/api/json/JsonUtils.java index 1a2a4c1..4083ad5 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/json/JsonUtils.java +++ b/src/api/java/com/teamacronymcoders/epos/api/json/JsonUtils.java @@ -4,14 +4,13 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponent; import net.minecraft.util.text.TranslationTextComponent; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - public class JsonUtils { @Nonnull public static String getString(JsonObject jsonObject, String fieldName) throws JsonParseException { diff --git a/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatureProvider.java b/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatureProvider.java index 8655cc1..49e33c5 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatureProvider.java +++ b/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatureProvider.java @@ -2,7 +2,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.teamacronymcoders.epos.api.registry.IRegistryEntry; import net.minecraftforge.registries.ForgeRegistryEntry; public abstract class PathFeatureProvider extends ForgeRegistryEntry { diff --git a/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatures.java b/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatures.java index 9921dc5..aebfde2 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatures.java +++ b/src/api/java/com/teamacronymcoders/epos/api/pathfeature/PathFeatures.java @@ -2,8 +2,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; -import net.minecraft.network.PacketBuffer; - import java.util.List; public class PathFeatures { diff --git a/src/api/java/com/teamacronymcoders/epos/api/registry/IRegistryEntry.java b/src/api/java/com/teamacronymcoders/epos/api/registry/IRegistryEntry.java index c86b634..6d8c2f5 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/registry/IRegistryEntry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/registry/IRegistryEntry.java @@ -1,8 +1,7 @@ package com.teamacronymcoders.epos.api.registry; -import net.minecraft.util.ResourceLocation; - import javax.annotation.Nonnull; +import net.minecraft.util.ResourceLocation; public interface IRegistryEntry { @Nonnull diff --git a/src/api/java/com/teamacronymcoders/epos/api/registry/MissingRegistryEntry.java b/src/api/java/com/teamacronymcoders/epos/api/registry/MissingRegistryEntry.java index 5813c3e..9c24453 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/registry/MissingRegistryEntry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/registry/MissingRegistryEntry.java @@ -1,11 +1,10 @@ package com.teamacronymcoders.epos.api.registry; +import javax.annotation.Nonnull; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; -import javax.annotation.Nonnull; - public class MissingRegistryEntry> implements INamedRegistryEntry { private final ResourceLocation registryName; private final ITextComponent name; diff --git a/src/api/java/com/teamacronymcoders/epos/api/registry/RegistrationEvent.java b/src/api/java/com/teamacronymcoders/epos/api/registry/RegistrationEvent.java index 85a7d08..dc0d856 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/registry/RegistrationEvent.java +++ b/src/api/java/com/teamacronymcoders/epos/api/registry/RegistrationEvent.java @@ -1,8 +1,7 @@ package com.teamacronymcoders.epos.api.registry; -import net.minecraftforge.eventbus.api.GenericEvent; - import java.util.List; +import net.minecraftforge.eventbus.api.GenericEvent; public class RegistrationEvent extends GenericEvent { private final Registry registry; diff --git a/src/api/java/com/teamacronymcoders/epos/api/registry/Registry.java b/src/api/java/com/teamacronymcoders/epos/api/registry/Registry.java index 32dd7ac..33975f5 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/registry/Registry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/registry/Registry.java @@ -1,14 +1,13 @@ package com.teamacronymcoders.epos.api.registry; import com.google.common.collect.Maps; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; import java.util.Map; import java.util.Objects; import java.util.function.Function; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.util.ResourceLocation; @ParametersAreNonnullByDefault public class Registry { diff --git a/src/api/java/com/teamacronymcoders/epos/api/skill/MissingSkill.java b/src/api/java/com/teamacronymcoders/epos/api/skill/MissingSkill.java index d898227..3163734 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/skill/MissingSkill.java +++ b/src/api/java/com/teamacronymcoders/epos/api/skill/MissingSkill.java @@ -1,10 +1,9 @@ package com.teamacronymcoders.epos.api.skill; +import javax.annotation.Nonnull; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; -import javax.annotation.Nonnull; - public class MissingSkill implements ISkill { private final ResourceLocation registryName; diff --git a/src/api/java/com/teamacronymcoders/epos/api/skill/SkillInfo.java b/src/api/java/com/teamacronymcoders/epos/api/skill/SkillInfo.java index de6e0bc..0dff732 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/skill/SkillInfo.java +++ b/src/api/java/com/teamacronymcoders/epos/api/skill/SkillInfo.java @@ -1,10 +1,9 @@ package com.teamacronymcoders.epos.api.skill; +import javax.annotation.Nonnull; import net.minecraft.nbt.CompoundNBT; import net.minecraftforge.common.util.INBTSerializable; -import javax.annotation.Nonnull; - public class SkillInfo implements INBTSerializable, Comparable { private final String registryName; private final ISkill skill; diff --git a/src/api/java/com/teamacronymcoders/epos/api/skill/Skills.java b/src/api/java/com/teamacronymcoders/epos/api/skill/Skills.java index 503423d..301c383 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/skill/Skills.java +++ b/src/api/java/com/teamacronymcoders/epos/api/skill/Skills.java @@ -1,17 +1,15 @@ package com.teamacronymcoders.epos.api.skill; import com.teamacronymcoders.epos.api.EposAPI; -import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.INBTSerializable; import org.apache.commons.lang3.tuple.Pair; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; - public class Skills implements INBTSerializable { private final Map skillInfoMap; diff --git a/src/main/java/com/teamacronymcoders/epos/Epos.java b/src/main/java/com/teamacronymcoders/epos/Epos.java index 1a9d14a..ab57cf4 100644 --- a/src/main/java/com/teamacronymcoders/epos/Epos.java +++ b/src/main/java/com/teamacronymcoders/epos/Epos.java @@ -1,19 +1,21 @@ package com.teamacronymcoders.epos; +import static com.teamacronymcoders.epos.api.EposAPI.ID; +import static com.teamacronymcoders.epos.api.EposAPI.PATH_REGISTRY; +import static com.teamacronymcoders.epos.api.EposAPI.SKILL_REGISTRY; + import com.hrznstudio.titanium.module.ModuleController; import com.hrznstudio.titanium.tab.AdvancedTitaniumTab; import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; -import com.teamacronymcoders.epos.api.path.IPath; -import com.teamacronymcoders.epos.api.skill.ISkill; import com.teamacronymcoders.epos.capability.NBTCapabilityStorage; import com.teamacronymcoders.epos.characterstats.CharacterStats; import com.teamacronymcoders.epos.configs.EposClientConfig; import com.teamacronymcoders.epos.feature.EposModules; -import com.teamacronymcoders.epos.locks.DefaultLocks; import com.teamacronymcoders.epos.json.JsonLoader; import com.teamacronymcoders.epos.json.jsondirector.RegistryJsonDirector; import com.teamacronymcoders.epos.json.jsonprovider.PathJsonProvider; import com.teamacronymcoders.epos.json.jsonprovider.SkillJsonProvider; +import com.teamacronymcoders.epos.locks.DefaultLocks; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.fml.ModLoadingContext; @@ -21,13 +23,10 @@ import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; -import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import static com.teamacronymcoders.epos.api.EposAPI.*; - @Mod(ID) @Mod.EventBusSubscriber public class Epos extends ModuleController { diff --git a/src/main/java/com/teamacronymcoders/epos/capability/NBTCapabilityStorage.java b/src/main/java/com/teamacronymcoders/epos/capability/NBTCapabilityStorage.java index ef4b01a..1b954ea 100644 --- a/src/main/java/com/teamacronymcoders/epos/capability/NBTCapabilityStorage.java +++ b/src/main/java/com/teamacronymcoders/epos/capability/NBTCapabilityStorage.java @@ -1,13 +1,12 @@ package com.teamacronymcoders.epos.capability; +import javax.annotation.Nullable; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.INBTSerializable; -import javax.annotation.Nullable; - public class NBTCapabilityStorage> implements Capability.IStorage { private final Class nbtClass; diff --git a/src/main/java/com/teamacronymcoders/epos/capability/PosInvHandlerCapabilityProvider.java b/src/main/java/com/teamacronymcoders/epos/capability/PosInvHandlerCapabilityProvider.java index d074167..e500ce3 100644 --- a/src/main/java/com/teamacronymcoders/epos/capability/PosInvHandlerCapabilityProvider.java +++ b/src/main/java/com/teamacronymcoders/epos/capability/PosInvHandlerCapabilityProvider.java @@ -1,6 +1,8 @@ package com.teamacronymcoders.epos.capability; import com.hrznstudio.titanium.block.tile.inventory.PosInvHandler; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; @@ -8,9 +10,6 @@ import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - public class PosInvHandlerCapabilityProvider implements ICapabilityProvider { private final LazyOptional optional; diff --git a/src/main/java/com/teamacronymcoders/epos/client/gui/GuiQuiverAddonScreen.java b/src/main/java/com/teamacronymcoders/epos/client/gui/GuiQuiverAddonScreen.java index 1d8d2f5..de47ce8 100644 --- a/src/main/java/com/teamacronymcoders/epos/client/gui/GuiQuiverAddonScreen.java +++ b/src/main/java/com/teamacronymcoders/epos/client/gui/GuiQuiverAddonScreen.java @@ -7,6 +7,9 @@ import com.hrznstudio.titanium.client.gui.addon.SlotsGuiAddon; import com.hrznstudio.titanium.client.gui.asset.IAssetProvider; import com.teamacronymcoders.epos.container.QuiverContainer; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; @@ -14,10 +17,6 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - public class GuiQuiverAddonScreen extends GuiAddonScreen implements INamedContainerProvider { private final PosInvHandler handler; diff --git a/src/main/java/com/teamacronymcoders/epos/configs/EposClientConfig.java b/src/main/java/com/teamacronymcoders/epos/configs/EposClientConfig.java index 212f60f..496cb38 100644 --- a/src/main/java/com/teamacronymcoders/epos/configs/EposClientConfig.java +++ b/src/main/java/com/teamacronymcoders/epos/configs/EposClientConfig.java @@ -1,8 +1,7 @@ package com.teamacronymcoders.epos.configs; -import net.minecraftforge.common.ForgeConfigSpec; - import java.util.Objects; +import net.minecraftforge.common.ForgeConfigSpec; public class EposClientConfig { private static EposClientConfig instance; diff --git a/src/main/java/com/teamacronymcoders/epos/container/QuiverContainer.java b/src/main/java/com/teamacronymcoders/epos/container/QuiverContainer.java index 1d167ff..7a496ef 100644 --- a/src/main/java/com/teamacronymcoders/epos/container/QuiverContainer.java +++ b/src/main/java/com/teamacronymcoders/epos/container/QuiverContainer.java @@ -4,6 +4,7 @@ import com.hrznstudio.titanium.block.tile.inventory.PosInvHandler; import com.hrznstudio.titanium.client.gui.asset.IAssetProvider; import com.teamacronymcoders.epos.feature.quiver.QuiverItem; +import java.awt.Point; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; @@ -14,8 +15,6 @@ import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.registries.ObjectHolder; -import java.awt.*; - public class QuiverContainer extends Container { @ObjectHolder("epos:quiver_container") public static final ContainerType TYPE = null; diff --git a/src/main/java/com/teamacronymcoders/epos/eventhandler/ForgeRegistryEventHandler.java b/src/main/java/com/teamacronymcoders/epos/eventhandler/ForgeRegistryEventHandler.java index 058be90..291bd52 100644 --- a/src/main/java/com/teamacronymcoders/epos/eventhandler/ForgeRegistryEventHandler.java +++ b/src/main/java/com/teamacronymcoders/epos/eventhandler/ForgeRegistryEventHandler.java @@ -1,10 +1,26 @@ package com.teamacronymcoders.epos.eventhandler; +import static com.teamacronymcoders.epos.api.EposAPI.ID; + import com.teamacronymcoders.epos.api.EposAPI; import com.teamacronymcoders.epos.api.feat.Feat; import com.teamacronymcoders.epos.api.pathfeature.PathFeatureProvider; import com.teamacronymcoders.epos.container.QuiverContainer; -import com.teamacronymcoders.epos.feats.*; +import com.teamacronymcoders.epos.feats.EfficiencyFeats; +import com.teamacronymcoders.epos.feats.EnderResistanceFeat; +import com.teamacronymcoders.epos.feats.GluttonousHungerFeat; +import com.teamacronymcoders.epos.feats.GravelExcavatorFeat; +import com.teamacronymcoders.epos.feats.HarvestAreaFeat; +import com.teamacronymcoders.epos.feats.ImprovisedCombatFeat; +import com.teamacronymcoders.epos.feats.LuckyAnglerFeat; +import com.teamacronymcoders.epos.feats.ObsidianSmasherFeat; +import com.teamacronymcoders.epos.feats.OreExtractionFeat; +import com.teamacronymcoders.epos.feats.PalmOfExcavationFeat; +import com.teamacronymcoders.epos.feats.PurityFeats; +import com.teamacronymcoders.epos.feats.SpiritOfBattleFeat; +import com.teamacronymcoders.epos.feats.TimberFeat; +import com.teamacronymcoders.epos.feats.UnarmedStrikeFeat; +import com.teamacronymcoders.epos.feats.WayOfTheBladeFeat; import com.teamacronymcoders.epos.pathfeature.feat.FeatFeatureProvider; import com.teamacronymcoders.epos.pathfeature.item.ItemRewardFeatureProvider; import com.teamacronymcoders.epos.pathfeature.levelupskill.LevelUpSkillFeatureProvider; @@ -19,8 +35,6 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.registries.RegistryBuilder; -import static com.teamacronymcoders.epos.api.EposAPI.ID; - @EventBusSubscriber(modid = EposAPI.ID, bus = EventBusSubscriber.Bus.MOD) public class ForgeRegistryEventHandler { @SubscribeEvent diff --git a/src/main/java/com/teamacronymcoders/epos/feats/GravelExcavatorFeat.java b/src/main/java/com/teamacronymcoders/epos/feats/GravelExcavatorFeat.java index 92d6dc4..0f01d7d 100644 --- a/src/main/java/com/teamacronymcoders/epos/feats/GravelExcavatorFeat.java +++ b/src/main/java/com/teamacronymcoders/epos/feats/GravelExcavatorFeat.java @@ -4,6 +4,8 @@ import com.teamacronymcoders.epos.api.feat.Feat; import com.teamacronymcoders.epos.api.feat.FeatBuilder; import com.teamacronymcoders.epos.utils.BlockBreakHelper; +import java.util.ArrayDeque; +import java.util.Deque; import net.minecraft.block.GravelBlock; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.ResourceLocation; @@ -12,9 +14,6 @@ import net.minecraftforge.common.ToolType; import net.minecraftforge.event.world.BlockEvent; -import java.util.ArrayDeque; -import java.util.Deque; - public class GravelExcavatorFeat { private static final ResourceLocation NAME = new ResourceLocation(EposAPI.ID, "gravel_excavator"); public static final Feat FEAT = diff --git a/src/main/java/com/teamacronymcoders/epos/feats/ImprovisedCombatFeat.java b/src/main/java/com/teamacronymcoders/epos/feats/ImprovisedCombatFeat.java index 693d8c3..3335020 100644 --- a/src/main/java/com/teamacronymcoders/epos/feats/ImprovisedCombatFeat.java +++ b/src/main/java/com/teamacronymcoders/epos/feats/ImprovisedCombatFeat.java @@ -5,11 +5,10 @@ import com.teamacronymcoders.epos.api.feat.Feat; import com.teamacronymcoders.epos.api.feat.FeatAcquiredEvent; import com.teamacronymcoders.epos.api.feat.FeatBuilder; +import java.util.Set; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.ToolType; -import java.util.Set; - public class ImprovisedCombatFeat { private static final ResourceLocation NAME = new ResourceLocation(EposAPI.ID, "improvised_combat"); public static final Feat FEAT = diff --git a/src/main/java/com/teamacronymcoders/epos/feature/quiver/QuiverItem.java b/src/main/java/com/teamacronymcoders/epos/feature/quiver/QuiverItem.java index a9c6d85..b83bef9 100644 --- a/src/main/java/com/teamacronymcoders/epos/feature/quiver/QuiverItem.java +++ b/src/main/java/com/teamacronymcoders/epos/feature/quiver/QuiverItem.java @@ -4,6 +4,7 @@ import com.teamacronymcoders.epos.Epos; import com.teamacronymcoders.epos.capability.PosInvHandlerCapabilityProvider; import com.teamacronymcoders.epos.client.gui.GuiQuiverAddonScreen; +import javax.annotation.Nullable; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.Item; @@ -19,8 +20,6 @@ import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.items.CapabilityItemHandler; -import javax.annotation.Nullable; - public class QuiverItem extends Item { public QuiverItem() { super(new Item.Properties().group(Epos.EPOS_TAB).maxStackSize(1).rarity(Rarity.EPIC)); diff --git a/src/main/java/com/teamacronymcoders/epos/json/JsonLoader.java b/src/main/java/com/teamacronymcoders/epos/json/JsonLoader.java index bbcb3e2..30fcf24 100644 --- a/src/main/java/com/teamacronymcoders/epos/json/JsonLoader.java +++ b/src/main/java/com/teamacronymcoders/epos/json/JsonLoader.java @@ -5,6 +5,9 @@ import com.google.gson.JsonParseException; import com.teamacronymcoders.epos.json.jsondirector.IJsonDirector; import com.teamacronymcoders.epos.json.jsonprovider.IJsonProvider; +import java.util.Map; +import java.util.Objects; +import javax.annotation.ParametersAreNonnullByDefault; import net.minecraft.client.resources.JsonReloadListener; import net.minecraft.profiler.IProfiler; import net.minecraft.resources.IResourceManager; @@ -12,10 +15,6 @@ import net.minecraft.util.Tuple; import org.apache.logging.log4j.Logger; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Map; -import java.util.Objects; - @ParametersAreNonnullByDefault public class JsonLoader extends JsonReloadListener { private final IJsonDirector director; diff --git a/src/main/java/com/teamacronymcoders/epos/json/jsonprovider/PathJsonProvider.java b/src/main/java/com/teamacronymcoders/epos/json/jsonprovider/PathJsonProvider.java index 7815e69..c492d8e 100644 --- a/src/main/java/com/teamacronymcoders/epos/json/jsonprovider/PathJsonProvider.java +++ b/src/main/java/com/teamacronymcoders/epos/json/jsonprovider/PathJsonProvider.java @@ -13,10 +13,9 @@ import com.teamacronymcoders.epos.path.Path; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.minecraft.util.ResourceLocation; - import java.util.List; import java.util.Map; +import net.minecraft.util.ResourceLocation; public class PathJsonProvider implements IJsonProvider { @Override diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java index b75a6be..1ddd493 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java @@ -7,7 +7,6 @@ import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.pattern.BlockStateMatcher; //TODO: Figure out the fuzzy and non fuzzy state of this. Use BlockStateMatcher to match blockstates public class BlockStateLockKey implements IFuzzyLockKey { diff --git a/src/main/java/com/teamacronymcoders/epos/path/Path.java b/src/main/java/com/teamacronymcoders/epos/path/Path.java index bd5118f..9785caa 100644 --- a/src/main/java/com/teamacronymcoders/epos/path/Path.java +++ b/src/main/java/com/teamacronymcoders/epos/path/Path.java @@ -3,12 +3,11 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.path.IPath; import com.teamacronymcoders.epos.api.pathfeature.PathFeatures; +import javax.annotation.Nonnull; import net.minecraft.entity.LivingEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; -import javax.annotation.Nonnull; - public class Path implements IPath { private final ResourceLocation registryName; private final ITextComponent name; diff --git a/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeatureProvider.java b/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeatureProvider.java index e4ac217..da12c2f 100644 --- a/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeatureProvider.java +++ b/src/main/java/com/teamacronymcoders/epos/pathfeature/item/ItemRewardFeatureProvider.java @@ -2,7 +2,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import com.teamacronymcoders.epos.api.EposAPI; import com.teamacronymcoders.epos.api.json.JsonUtils; import com.teamacronymcoders.epos.api.pathfeature.IPathFeature; import com.teamacronymcoders.epos.api.pathfeature.PathFeatureProvider; @@ -12,8 +11,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.registries.ForgeRegistries; -import javax.annotation.Nonnull; - // TODO: Import NBT-Code from BASE to not use MC's Horrid NBT Code public class ItemRewardFeatureProvider extends PathFeatureProvider { @Override diff --git a/src/main/java/com/teamacronymcoders/epos/pathfeature/levelupskill/LevelUpSkillFeatureProvider.java b/src/main/java/com/teamacronymcoders/epos/pathfeature/levelupskill/LevelUpSkillFeatureProvider.java index 5947f12..fed2bc1 100644 --- a/src/main/java/com/teamacronymcoders/epos/pathfeature/levelupskill/LevelUpSkillFeatureProvider.java +++ b/src/main/java/com/teamacronymcoders/epos/pathfeature/levelupskill/LevelUpSkillFeatureProvider.java @@ -7,9 +7,6 @@ import com.teamacronymcoders.epos.api.pathfeature.IPathFeature; import com.teamacronymcoders.epos.api.pathfeature.PathFeatureProvider; import com.teamacronymcoders.epos.api.skill.ISkill; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Nonnull; public class LevelUpSkillFeatureProvider extends PathFeatureProvider { @Override diff --git a/src/main/java/com/teamacronymcoders/epos/pathfeature/skillxp/SkillXPFeatureProvider.java b/src/main/java/com/teamacronymcoders/epos/pathfeature/skillxp/SkillXPFeatureProvider.java index bda8747..3a31905 100644 --- a/src/main/java/com/teamacronymcoders/epos/pathfeature/skillxp/SkillXPFeatureProvider.java +++ b/src/main/java/com/teamacronymcoders/epos/pathfeature/skillxp/SkillXPFeatureProvider.java @@ -7,9 +7,6 @@ import com.teamacronymcoders.epos.api.pathfeature.IPathFeature; import com.teamacronymcoders.epos.api.pathfeature.PathFeatureProvider; import com.teamacronymcoders.epos.api.skill.ISkill; -import net.minecraft.util.ResourceLocation; - -import javax.annotation.Nonnull; public class SkillXPFeatureProvider extends PathFeatureProvider { @Override diff --git a/src/main/java/com/teamacronymcoders/epos/skill/Skill.java b/src/main/java/com/teamacronymcoders/epos/skill/Skill.java index 2dcf1ae..6f5e7ce 100644 --- a/src/main/java/com/teamacronymcoders/epos/skill/Skill.java +++ b/src/main/java/com/teamacronymcoders/epos/skill/Skill.java @@ -2,11 +2,10 @@ import com.teamacronymcoders.epos.api.skill.ISkill; import com.teamacronymcoders.epos.api.skill.SkillInfo; +import javax.annotation.Nonnull; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; -import javax.annotation.Nonnull; - public class Skill implements ISkill { private final ResourceLocation registryName; private final ITextComponent name; diff --git a/src/main/java/com/teamacronymcoders/epos/utils/BlockBreakHelper.java b/src/main/java/com/teamacronymcoders/epos/utils/BlockBreakHelper.java index f39079f..5b8835f 100644 --- a/src/main/java/com/teamacronymcoders/epos/utils/BlockBreakHelper.java +++ b/src/main/java/com/teamacronymcoders/epos/utils/BlockBreakHelper.java @@ -1,5 +1,8 @@ package com.teamacronymcoders.epos.utils; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -9,10 +12,6 @@ import net.minecraftforge.event.world.BlockEvent; import org.antlr.v4.runtime.misc.Array2DHashSet; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - public class BlockBreakHelper { public static void handleBreakBlock(Iterable iterable, World world, PlayerEntity player) { iterable.forEach(blockPos -> handleBreakBlock(world, blockPos, world.getBlockState(blockPos), player)); From d1f97f681148bf1379e01723ef5fe46a2cf31aad Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Thu, 3 Oct 2019 12:58:35 -0400 Subject: [PATCH 09/14] Implement BlockStateLockKey --- .../epos/locks/keys/BlockStateLockKey.java | 54 +++++++++++++++---- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java index 1ddd493..57c1450 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java @@ -2,20 +2,36 @@ import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import java.util.Collections; +import java.util.Map; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.state.IProperty; -//TODO: Figure out the fuzzy and non fuzzy state of this. Use BlockStateMatcher to match blockstates public class BlockStateLockKey implements IFuzzyLockKey { + private static Map, Comparable> EMPTY_PROPERTIES = Collections.emptyMap(); + + @Nonnull + private final Block block; + //Can be empty if we only care about the block type and not its state @Nonnull - private BlockState state; + private final Map, Comparable> properties; public BlockStateLockKey(@Nonnull BlockState state) { - this.state = state; + this(state.getBlock(), state.getValues()); + } + + public BlockStateLockKey(@Nonnull Block block) { + this(block, EMPTY_PROPERTIES); + } + + private BlockStateLockKey(@Nonnull Block block, @Nonnull Map, Comparable> properties) { + this.block = block; + this.properties = properties; } @Nullable @@ -23,7 +39,7 @@ public static BlockStateLockKey fromObject(@Nonnull Object object) { if (object instanceof BlockState) { return new BlockStateLockKey((BlockState) object); } else if (object instanceof Block) { - return new BlockStateLockKey(((Block) object).getDefaultState()); + return new BlockStateLockKey(((Block) object)); } return null; } @@ -35,21 +51,36 @@ public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { } if (o instanceof BlockStateLockKey) { BlockStateLockKey other = (BlockStateLockKey) o; - //TODO + if (block == other.block) { + //Compare the properties making sure that they match + return properties.entrySet().stream().allMatch(entry -> compareProperty(entry.getKey(), other)); + } } return false; } + private > boolean compareProperty(IProperty property, BlockStateLockKey other) { + if (other.properties.containsKey(property)) { + //TODO: If we find a use case where it makes sense to use the compareTo as >= 0 + // so that it is fuzzy in that regard, potentially change this to >= from == + return getValue(property).compareTo(other.getValue(property)) == 0; + } + return false; + } + + private > T getValue(IProperty property) { + return (T) properties.get(property); + } + @Override public boolean isNotFuzzy() { - //TODO - return false; + return properties.isEmpty(); } @Override @Nonnull public ILockKey getNotFuzzy() { - return isNotFuzzy() ? this : new BlockStateLockKey(state); + return isNotFuzzy() ? this : new BlockStateLockKey(block); } @Override @@ -61,12 +92,13 @@ public boolean equals(Object o) { return false; } BlockStateLockKey other = (BlockStateLockKey) o; - //TODO - return false;//item == other.item && Objects.equals(nbt, other.nbt); + //Note: Map#equals is declared to ensure they are both maps and that the keys and values are equal. + // The type of the map does not matter + return block == other.block && properties.equals(other.properties); } @Override public int hashCode() { - return Objects.hash(state); + return Objects.hash(block, properties); } } \ No newline at end of file From d312d0b4ff1a9a0793721976530bd907b340b71e Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Thu, 3 Oct 2019 14:07:29 -0400 Subject: [PATCH 10/14] Create a multi lock key creator system --- .../epos/api/locks/LockRegistry.java | 98 ++++++++++++++----- .../{ => keys/creator}/ILockKeyCreator.java | 2 +- .../keys/creator/IMultiLockKeyCreator.java | 23 +++++ .../epos/locks/DefaultLocks.java | 2 +- .../keys/harvest/ToolHarvestLockKey.java | 60 ++++-------- .../epos/locks/keys/tag/ParentTagLockKey.java | 1 + 6 files changed, 119 insertions(+), 67 deletions(-) rename src/api/java/com/teamacronymcoders/epos/api/locks/{ => keys/creator}/ILockKeyCreator.java (88%) create mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java index 6f63e48..6810ee3 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java @@ -4,6 +4,8 @@ import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import com.teamacronymcoders.epos.api.locks.keys.IParentLockKey; +import com.teamacronymcoders.epos.api.locks.keys.creator.ILockKeyCreator; +import com.teamacronymcoders.epos.api.locks.keys.creator.IMultiLockKeyCreator; import com.teamacronymcoders.epos.api.requirements.IRequirement; import java.util.ArrayList; import java.util.Collection; @@ -15,18 +17,21 @@ import java.util.Set; import javax.annotation.Nonnull; -//TODO: JavaDoc all methods once the RequirementCombiner system is developed, as some of the methods here may change slightly +//TODO: JavaDoc remaining methods once the RequirementCombiner system is developed, +// as the description for them may change some public class LockRegistry { private static final List EMPTY_REQUIREMENTS = Collections.emptyList(); private final List> keyCreators = new ArrayList<>(); + private final List> multiKeyCreators = new ArrayList<>(); private final Map> locks = new HashMap<>(); private final Map> fuzzyLockInfo = new HashMap<>(); /** - * Unlike the 1.12 system this has it so that each lock key has one registration for each type it can be created from Each one has to be checked when getting by type - * rather than knowing it "should" be good for that type already + * Unlike the 1.12 system this has it so that each lock key has one registration for each type + * it can be created from Each one has to be checked when getting by type rather than knowing + * it "should" be good for that type already * * @param creator A Lock Key Creator that creates keys of type KEY given an object. * @param The type of key the given lock creator is for. @@ -36,6 +41,14 @@ public void registerLockType(@Nonnull ILockKeyCreator The type of key the given lock creator is for. + */ + public void registerMultiLockType(@Nonnull IMultiLockKeyCreator creator) { + multiKeyCreators.add(creator); + } + /** * For use in reloading, and unit tests */ @@ -58,6 +71,14 @@ public void addLockByKey(@Nonnull ILockKey key, @Nonnull List requ } } + /** + * Gets the requirements by the the given {@link ILockKey}. If the give key is an {@link IFuzzyLockKey}, + * retrieves all requirements that match; similar to {@link #getFuzzyRequirements(IFuzzyLockKey)}. + * @param key The {@link ILockKey} to retrieve the requirements of. + * @return A {@link List} of requirements for the given {@link ILockKey} + * @apiNote This method does not have special handling for {@link IParentLockKey} as parent lock keys + * should not be directly initialized, and are for internal use via the lock key creators. + */ @Nonnull public List getRequirementsByKey(@Nonnull ILockKey key) { if (key instanceof IFuzzyLockKey) { @@ -66,6 +87,13 @@ public List getRequirementsByKey(@Nonnull ILockKey key) { return locks.getOrDefault(key, EMPTY_REQUIREMENTS); } + /** + * Gets the requirements by the given {@link IFuzzyLockKey}. This includes the base "non fuzzy" + * lock key variant and any requirements that are {@link IFuzzyLockKey#fuzzyEquals(IFuzzyLockKey)} + * to the given key. + * @param key The {@link IFuzzyLockKey} to retrieve the requirements of. + * @return A {@link List} of requirements for the given {@link IFuzzyLockKey} + */ @Nonnull public List getFuzzyRequirements(@Nonnull IFuzzyLockKey key) { List requirements = new ArrayList<>(); @@ -88,15 +116,6 @@ public List getFuzzyRequirements(@Nonnull IFuzzyLockKey key) { return requirements; } - //Helper method to add a lock's requirements to the requirement list if it has them - private void addRequirementsFromLock(@Nonnull List requirements, @Nonnull ILockKey key) { - List reqs = locks.get(key); - if (reqs != null) { - //If there are locks for the key add them - requirements.addAll(reqs); - } - } - @Nonnull public List getLocks(@Nonnull Collection objects) { //TODO: Helper method for combining the locks of multiple same type objects (Maybe even allow of different type objects) @@ -113,21 +132,52 @@ public List getLocks(@Nonnull Object object) { List requirements = new ArrayList<>(); for (ILockKeyCreator keyCreator : keyCreators) { ILockKey lockKey = keyCreator.createFrom(object); - if (lockKey == null) { - //We failed to create a lock key with our object, continue to next type of lock key - continue; + if (lockKey != null) { + //We didn't fail to create a lock key with our object, + // so we can add any requirements we find to our list of requirements. + addRequirementsFromCreatedKey(requirements, lockKey); } - if (lockKey instanceof IFuzzyLockKey) { - requirements.addAll(getFuzzyRequirements((IFuzzyLockKey) lockKey)); - } else { - addRequirementsFromLock(requirements, lockKey); - } - if (lockKey instanceof IParentLockKey) { - //Add all the sub requirements the lock key may have - // (if there is one that matches the key itself it will have been caught above) - requirements.addAll(((IParentLockKey) lockKey).getSubRequirements()); + } + //Handle any multi keys + for (IMultiLockKeyCreator keyCreator : multiKeyCreators) { + Collection lockKeys = keyCreator.createFrom(object); + for (ILockKey lockKey : lockKeys) { + addRequirementsFromCreatedKey(requirements, lockKey); } } return requirements; } + + /** + * Figures out what kind of key the given key is, and retrieves the proper set of requirements + * for it and adds them to the given requirement list. + * @param requirements List of requirements to add to + * @param key The lock key to get the requirements of. + */ + private void addRequirementsFromCreatedKey(@Nonnull List requirements, @Nonnull ILockKey key) { + if (key instanceof IFuzzyLockKey) { + requirements.addAll(getFuzzyRequirements((IFuzzyLockKey) key)); + } else { + addRequirementsFromLock(requirements, key); + } + if (key instanceof IParentLockKey) { + //Add all the sub requirements the lock key may have + // (if there is one that matches the key itself it will have been caught above) + requirements.addAll(((IParentLockKey) key).getSubRequirements()); + } + } + + /** + * Helper method to add a lock's requirements to the requirement list. + * If there are no requirements for the given key, do nothing. + * @param requirements List of requirements to add to + * @param key The lock key to get the requirements of. + */ + private void addRequirementsFromLock(@Nonnull List requirements, @Nonnull ILockKey key) { + List reqs = locks.get(key); + if (reqs != null) { + //If there are locks for the key add them + requirements.addAll(reqs); + } + } } \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/ILockKeyCreator.java similarity index 88% rename from src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java rename to src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/ILockKeyCreator.java index a9d9dc7..1d7e188 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/ILockKeyCreator.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/ILockKeyCreator.java @@ -1,4 +1,4 @@ -package com.teamacronymcoders.epos.api.locks; +package com.teamacronymcoders.epos.api.locks.keys.creator; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import javax.annotation.Nonnull; diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java new file mode 100644 index 0000000..d36501a --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java @@ -0,0 +1,23 @@ +package com.teamacronymcoders.epos.api.locks.keys.creator; + +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import java.util.Collection; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Like {@link ILockKeyCreator} except is used if multiple instances of our key can + * be created at once from the given object. + * @param + */ +@FunctionalInterface +public interface IMultiLockKeyCreator { + + /** + * @return empty if it cannot be used to create a type. + * + * @implNote IMPORTANT: fail fast where possible, and ensure it is actually the type going to be used + */ + @Nonnull + Collection createFrom(@Nonnull Object o); +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java index 8f33c52..6ea43e3 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java @@ -38,7 +38,7 @@ public static void registerKeyLookups() { EposAPI.LOCK_REGISTRY.registerLockType(HungerLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(SaturationLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(BlockHarvestLockKey::fromObject); - EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ToolHarvestLockKey.fromItemStack((ItemStack) object) : null); + EposAPI.LOCK_REGISTRY.registerMultiLockType(ToolHarvestLockKey::getKeysFromObject); EposAPI.LOCK_REGISTRY.registerLockType(ParentTagLockKey::fromObject); } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java index 875016c..3f68e22 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java @@ -4,65 +4,51 @@ import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import com.teamacronymcoders.epos.locks.FuzzyLockKeyTypes; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Objects; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.common.ToolType; -//TODO: Add back in some form of support based on tool type -// Or should that be part of the logic handler abilities that merges this with another for handling specific tool types public class ToolHarvestLockKey extends HarvestLockKey { + private static final List EMPTY = Collections.emptyList(); private static final GenericLockKey NOT_FUZZY = new GenericLockKey(FuzzyLockKeyTypes.TOOL_HARVEST); @Nonnull - private final Map typeLevels; - @Nullable private final ToolType toolType; /** * @apiNote Ensure that the given harvest level is positive. */ - public ToolHarvestLockKey(@Nullable ToolType toolType, int harvestLevel) { + public ToolHarvestLockKey(@Nonnull ToolType toolType, int harvestLevel) { super(harvestLevel); this.toolType = toolType; - this.typeLevels = new HashMap<>(); } - /** - * @apiNote Ensure that the given harvest level is positive. - */ - private ToolHarvestLockKey(@Nonnull Map typeLevels, int harvestLevel) { - super(harvestLevel); - this.toolType = null; - this.typeLevels = typeLevels; - } - - @Nullable - public static ToolHarvestLockKey fromItemStack(@Nonnull ItemStack stack) { + @Nonnull + public static List getKeysFromObject(@Nonnull Object object) { + if (!(object instanceof ItemStack)) { + //If we are not an ItemStack fail + return EMPTY; + } + ItemStack stack = (ItemStack) object; if (stack.isEmpty()) { - return null; + //Fail if our stack is empty + return EMPTY; } - int highestLevel = -1; + List keys = new ArrayList<>(); Item item = stack.getItem(); - Map typeLevels = new HashMap<>(); for (ToolType type : item.getToolTypes(stack)) { int level = item.getHarvestLevel(stack, type, null, null); - if (level < 0) { - continue; - } - typeLevels.put(type, level); - if (level > highestLevel) { - highestLevel = level; + if (level >= 0) { + keys.add(new ToolHarvestLockKey(type, level)); } } - //TODO: Decide if it matches only one tool type if it should just be that type instead of it as a map - // Note: Would have to rewrite fuzzyEquals implementation - return highestLevel < 0 || typeLevels.isEmpty() ? null : new ToolHarvestLockKey(typeLevels, highestLevel); + return keys; } @Override @@ -72,12 +58,7 @@ public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { } if (o instanceof ToolHarvestLockKey) { ToolHarvestLockKey toolLock = (ToolHarvestLockKey) o; - if (harvestLevel >= toolLock.harvestLevel) { - if (toolLock.toolType == null) { - return toolType == null; - } - return toolLock.typeLevels.keySet().stream().noneMatch(s -> !typeLevels.containsKey(s) || typeLevels.get(s) < toolLock.typeLevels.get(s)); - } + return harvestLevel >= toolLock.harvestLevel && toolType.equals(toolLock.toolType); } return false; } @@ -95,9 +76,6 @@ public boolean equals(Object o) { } if (o instanceof ToolHarvestLockKey) { ToolHarvestLockKey toolLock = (ToolHarvestLockKey) o; - if (toolType == null) { - return toolLock.toolType == null && harvestLevel == toolLock.harvestLevel; - } return harvestLevel == toolLock.harvestLevel && toolType.equals(toolLock.toolType); } return false; diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java index 726dfcb..7eef156 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java @@ -20,6 +20,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; +//TODO: Instead of this being a ParentLockKey, this could be done via the MultiLockKeyCreator system public class ParentTagLockKey implements IParentLockKey { @Nonnull From 18e964c9ca029ca1cf68f309782ea4d585e0edf4 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Thu, 3 Oct 2019 14:34:27 -0400 Subject: [PATCH 11/14] Remove ParentLockKey as it can be done via the new MultiLockKeyCreator system --- .../epos/api/locks/LockRegistry.java | 26 +----- .../epos/api/locks/keys/IParentLockKey.java | 18 ---- .../keys/creator/IMultiLockKeyCreator.java | 1 - .../epos/locks/DefaultLocks.java | 11 ++- .../epos/locks/keys/ArmorLockKey.java | 37 +++++---- .../locks/keys/ArmorToughnessLockKey.java | 37 +++++---- .../epos/locks/keys/AttackDamageLockKey.java | 30 ++++--- .../epos/locks/keys/BlockStateLockKey.java | 20 ++--- .../epos/locks/keys/DimensionTypeLockKey.java | 20 ++--- .../epos/locks/keys/GenericNBTLockKey.java | 32 ++++---- .../epos/locks/keys/HungerLockKey.java | 52 ++++++------ .../epos/locks/keys/ItemLockKey.java | 22 ++--- .../epos/locks/keys/ModLockKey.java | 46 +++++------ .../epos/locks/keys/SaturationLockKey.java | 52 ++++++------ .../ParentTagLockKey.java => TagLockKey.java} | 82 +++++++++++-------- .../locks/keys/entity/EntityDamageKey.java | 10 +-- .../locks/keys/entity/EntityMountKey.java | 10 +-- .../epos/locks/keys/entity/EntityTameKey.java | 10 +-- .../keys/harvest/BlockHarvestLockKey.java | 36 ++++---- .../keys/harvest/ToolHarvestLockKey.java | 42 +++++----- .../epos/locks/keys/tag/TagLockKey.java | 46 ----------- .../epos/api/locks/LockAPITest.java | 9 +- .../epos/api/locks/keys/ListLockKey.java | 39 --------- .../epos/api/locks/keys/StringLockKey.java | 28 +++++++ 24 files changed, 324 insertions(+), 392 deletions(-) delete mode 100644 src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java rename src/main/java/com/teamacronymcoders/epos/locks/keys/{tag/ParentTagLockKey.java => TagLockKey.java} (50%) delete mode 100644 src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java delete mode 100644 src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java index 6810ee3..6fff4e6 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/LockRegistry.java @@ -3,7 +3,6 @@ import com.teamacronymcoders.epos.api.locks.keys.GenericLockKey; import com.teamacronymcoders.epos.api.locks.keys.IFuzzyLockKey; import com.teamacronymcoders.epos.api.locks.keys.ILockKey; -import com.teamacronymcoders.epos.api.locks.keys.IParentLockKey; import com.teamacronymcoders.epos.api.locks.keys.creator.ILockKeyCreator; import com.teamacronymcoders.epos.api.locks.keys.creator.IMultiLockKeyCreator; import com.teamacronymcoders.epos.api.requirements.IRequirement; @@ -76,8 +75,6 @@ public void addLockByKey(@Nonnull ILockKey key, @Nonnull List requ * retrieves all requirements that match; similar to {@link #getFuzzyRequirements(IFuzzyLockKey)}. * @param key The {@link ILockKey} to retrieve the requirements of. * @return A {@link List} of requirements for the given {@link ILockKey} - * @apiNote This method does not have special handling for {@link IParentLockKey} as parent lock keys - * should not be directly initialized, and are for internal use via the lock key creators. */ @Nonnull public List getRequirementsByKey(@Nonnull ILockKey key) { @@ -135,38 +132,19 @@ public List getLocks(@Nonnull Object object) { if (lockKey != null) { //We didn't fail to create a lock key with our object, // so we can add any requirements we find to our list of requirements. - addRequirementsFromCreatedKey(requirements, lockKey); + requirements.addAll(getRequirementsByKey(lockKey)); } } //Handle any multi keys for (IMultiLockKeyCreator keyCreator : multiKeyCreators) { Collection lockKeys = keyCreator.createFrom(object); for (ILockKey lockKey : lockKeys) { - addRequirementsFromCreatedKey(requirements, lockKey); + requirements.addAll(getRequirementsByKey(lockKey)); } } return requirements; } - /** - * Figures out what kind of key the given key is, and retrieves the proper set of requirements - * for it and adds them to the given requirement list. - * @param requirements List of requirements to add to - * @param key The lock key to get the requirements of. - */ - private void addRequirementsFromCreatedKey(@Nonnull List requirements, @Nonnull ILockKey key) { - if (key instanceof IFuzzyLockKey) { - requirements.addAll(getFuzzyRequirements((IFuzzyLockKey) key)); - } else { - addRequirementsFromLock(requirements, key); - } - if (key instanceof IParentLockKey) { - //Add all the sub requirements the lock key may have - // (if there is one that matches the key itself it will have been caught above) - requirements.addAll(((IParentLockKey) key).getSubRequirements()); - } - } - /** * Helper method to add a lock's requirements to the requirement list. * If there are no requirements for the given key, do nothing. diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java deleted file mode 100644 index 53ca9c0..0000000 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/IParentLockKey.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.teamacronymcoders.epos.api.locks.keys; - -import com.teamacronymcoders.epos.api.locks.LockRegistry; -import com.teamacronymcoders.epos.api.requirements.IRequirement; -import java.util.Collection; -import java.util.List; -import javax.annotation.Nonnull; - -public interface IParentLockKey extends ILockKey { - - /** - * Retrieves any sub requirements this key may have. This usually can be implemented by calling {@link LockRegistry#getLocks(Collection)}}. - * - * @return A List of all the sub requirements. - */ - @Nonnull - List getSubRequirements(); -} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java index d36501a..fd74e66 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java +++ b/src/api/java/com/teamacronymcoders/epos/api/locks/keys/creator/IMultiLockKeyCreator.java @@ -3,7 +3,6 @@ import com.teamacronymcoders.epos.api.locks.keys.ILockKey; import java.util.Collection; import javax.annotation.Nonnull; -import javax.annotation.Nullable; /** * Like {@link ILockKeyCreator} except is used if multiple instances of our key can diff --git a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java index 6ea43e3..8c0e97c 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/DefaultLocks.java @@ -11,13 +11,12 @@ import com.teamacronymcoders.epos.locks.keys.ItemLockKey; import com.teamacronymcoders.epos.locks.keys.ModLockKey; import com.teamacronymcoders.epos.locks.keys.SaturationLockKey; +import com.teamacronymcoders.epos.locks.keys.TagLockKey; import com.teamacronymcoders.epos.locks.keys.entity.EntityDamageKey; import com.teamacronymcoders.epos.locks.keys.entity.EntityMountKey; import com.teamacronymcoders.epos.locks.keys.entity.EntityTameKey; import com.teamacronymcoders.epos.locks.keys.harvest.BlockHarvestLockKey; import com.teamacronymcoders.epos.locks.keys.harvest.ToolHarvestLockKey; -import com.teamacronymcoders.epos.locks.keys.tag.ParentTagLockKey; -import net.minecraft.item.ItemStack; public class DefaultLocks { @@ -32,13 +31,13 @@ public static void registerKeyLookups() { EposAPI.LOCK_REGISTRY.registerLockType(EntityDamageKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(EntityMountKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(EntityTameKey::fromObject); - EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ArmorLockKey.fromItemStack((ItemStack) object) : null); - EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? ArmorToughnessLockKey.fromItemStack((ItemStack) object) : null); - EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof ItemStack ? AttackDamageLockKey.fromItemStack((ItemStack) object) : null); + EposAPI.LOCK_REGISTRY.registerLockType(ArmorLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerLockType(ArmorToughnessLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerLockType(AttackDamageLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(HungerLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(SaturationLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(BlockHarvestLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerMultiLockType(ToolHarvestLockKey::getKeysFromObject); - EposAPI.LOCK_REGISTRY.registerLockType(ParentTagLockKey::fromObject); + EposAPI.LOCK_REGISTRY.registerMultiLockType(TagLockKey::getKeysFromObject); } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java index c3f5dd0..fa27b3c 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorLockKey.java @@ -28,22 +28,6 @@ public ArmorLockKey(double armor) { this.armor = armor; } - @Nullable - public static ArmorLockKey fromItemStack(@Nonnull ItemStack stack) { - if (stack.isEmpty()) { - return null; - } - Item item = stack.getItem(); - if (item instanceof ArmorItem) { - ArmorItem armorItem = (ArmorItem) item; - Multimap attributeModifiers = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack); - double armor = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ARMOR, armorItem.getDamageReduceAmount()); - //Ensure that the value is actually positive - return armor < 0 ? null : new ArmorLockKey(armor); - } - return null; - } - @Override public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { return o == this || o instanceof ArmorLockKey && armor >= ((ArmorLockKey) o).armor; @@ -69,4 +53,25 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(armor); } + + @Nullable + public static ArmorLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + Item item = stack.getItem(); + if (item instanceof ArmorItem) { + ArmorItem armorItem = (ArmorItem) item; + Multimap attributeModifiers = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack); + double armor = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ARMOR, armorItem.getDamageReduceAmount()); + //Ensure that the value is actually positive + if (armor >= 0) { + return new ArmorLockKey(armor); + } + } + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java index 7352299..6a34454 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ArmorToughnessLockKey.java @@ -28,22 +28,6 @@ public ArmorToughnessLockKey(double toughness) { this.toughness = toughness; } - @Nullable - public static ArmorToughnessLockKey fromItemStack(@Nonnull ItemStack stack) { - if (stack.isEmpty()) { - return null; - } - Item item = stack.getItem(); - if (item instanceof ArmorItem) { - ArmorItem armorItem = (ArmorItem) item; - Multimap attributeModifiers = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack); - double toughness = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ARMOR_TOUGHNESS, armorItem.getToughness()); - //Ensure that the value is actually positive - return toughness < 0 ? null : new ArmorToughnessLockKey(toughness); - } - return null; - } - @Override public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { return o == this || o instanceof ArmorToughnessLockKey && toughness >= ((ArmorToughnessLockKey) o).toughness; @@ -69,4 +53,25 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(toughness); } + + @Nullable + public static ArmorToughnessLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + Item item = stack.getItem(); + if (item instanceof ArmorItem) { + ArmorItem armorItem = (ArmorItem) item; + Multimap attributeModifiers = armorItem.getAttributeModifiers(armorItem.getEquipmentSlot(), stack); + double toughness = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ARMOR_TOUGHNESS, armorItem.getToughness()); + //Ensure that the value is actually positive + if (toughness >= 0) { + return new ArmorToughnessLockKey(toughness); + } + } + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java index 573bd65..aff2be2 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/AttackDamageLockKey.java @@ -28,18 +28,6 @@ public AttackDamageLockKey(double attackDamage) { this.attackDamage = attackDamage; } - @Nullable - public static AttackDamageLockKey fromItemStack(@Nonnull ItemStack stack) { - if (stack.isEmpty()) { - return null; - } - Item item = stack.getItem(); - Multimap attributeModifiers = item.getAttributeModifiers(EquipmentSlotType.MAINHAND, stack); - double damage = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ATTACK_DAMAGE); - //Ensure that the value is actually positive - return damage < 0 ? null : new AttackDamageLockKey(damage); - } - @Override public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { return o == this || o instanceof AttackDamageLockKey && attackDamage >= ((AttackDamageLockKey) o).attackDamage; @@ -65,4 +53,22 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(attackDamage); } + + @Nullable + public static AttackDamageLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + Item item = stack.getItem(); + Multimap attributeModifiers = item.getAttributeModifiers(EquipmentSlotType.MAINHAND, stack); + double damage = AttributeUtils.calculateValueFromModifiers(attributeModifiers, SharedMonsterAttributes.ATTACK_DAMAGE); + //Ensure that the value is actually positive + if (damage >= 0) { + return new AttackDamageLockKey(damage); + } + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java index 57c1450..4928864 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/BlockStateLockKey.java @@ -34,16 +34,6 @@ private BlockStateLockKey(@Nonnull Block block, @Nonnull Map, Compa this.properties = properties; } - @Nullable - public static BlockStateLockKey fromObject(@Nonnull Object object) { - if (object instanceof BlockState) { - return new BlockStateLockKey((BlockState) object); - } else if (object instanceof Block) { - return new BlockStateLockKey(((Block) object)); - } - return null; - } - @Override public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { if (o == this) { @@ -101,4 +91,14 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(block, properties); } + + @Nullable + public static BlockStateLockKey fromObject(@Nonnull Object object) { + if (object instanceof BlockState) { + return new BlockStateLockKey((BlockState) object); + } else if (object instanceof Block) { + return new BlockStateLockKey(((Block) object)); + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java index 90d08ec..cf79b3d 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/DimensionTypeLockKey.java @@ -16,6 +16,16 @@ public DimensionTypeLockKey(@Nonnull DimensionType dimension) { this.dimension = dimension; } + @Override + public boolean equals(Object obj) { + return obj == this || obj instanceof DimensionTypeLockKey && dimension.equals(((DimensionTypeLockKey) obj).dimension); + } + + @Override + public int hashCode() { + return dimension.hashCode(); + } + @Nullable public static DimensionTypeLockKey fromObject(@Nonnull Object object) { if (object instanceof DimensionType) { @@ -27,14 +37,4 @@ public static DimensionTypeLockKey fromObject(@Nonnull Object object) { } return null; } - - @Override - public boolean equals(Object obj) { - return obj == this || obj instanceof DimensionTypeLockKey && dimension.equals(((DimensionTypeLockKey) obj).dimension); - } - - @Override - public int hashCode() { - return dimension.hashCode(); - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java index b1c455b..cf953e2 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/GenericNBTLockKey.java @@ -21,22 +21,6 @@ public GenericNBTLockKey(@Nonnull CompoundNBT nbt) { super(nbt); } - @Nullable - public static GenericNBTLockKey fromObject(@Nonnull Object object) { - if (object instanceof ItemStack) { - ItemStack stack = (ItemStack) object; - return stack.hasTag() ? fromCompound(stack.getTag()) : null; - } else if (object instanceof CompoundNBT) { - return fromCompound((CompoundNBT) object); - } - return null; - } - - @Nullable - private static GenericNBTLockKey fromCompound(@Nonnull CompoundNBT nbt) { - return nbt.isEmpty() ? null : new GenericNBTLockKey(nbt); - } - @Override @Nonnull public ILockKey getNotFuzzy() { @@ -52,4 +36,20 @@ public boolean equals(Object o) { public int hashCode() { return nbt == null ? super.hashCode() : nbt.hashCode(); } + + @Nullable + public static GenericNBTLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + return stack.hasTag() ? fromCompound(stack.getTag()) : null; + } else if (object instanceof CompoundNBT) { + return fromCompound((CompoundNBT) object); + } + return null; + } + + @Nullable + private static GenericNBTLockKey fromCompound(@Nonnull CompoundNBT nbt) { + return nbt.isEmpty() ? null : new GenericNBTLockKey(nbt); + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java index 2b47c10..b5a04b5 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/HungerLockKey.java @@ -24,6 +24,32 @@ public HungerLockKey(int hunger) { this.hunger = hunger; } + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof HungerLockKey && hunger >= ((HungerLockKey) o).hunger; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public int hashCode() { + return Objects.hash(hunger); + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof HungerLockKey && hunger == ((HungerLockKey) o).hunger; + } + @Nullable public static HungerLockKey fromObject(@Nonnull Object object) { if (object instanceof ItemStack) { @@ -54,30 +80,4 @@ private static HungerLockKey fromFood(@Nullable Food food) { //Ensure that the value is actually positive return healing < 0 ? null : new HungerLockKey(healing); } - - @Override - public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { - return o == this || o instanceof HungerLockKey && hunger >= ((HungerLockKey) o).hunger; - } - - @Override - public boolean isNotFuzzy() { - return false; - } - - @Override - @Nonnull - public ILockKey getNotFuzzy() { - return NOT_FUZZY; - } - - @Override - public int hashCode() { - return Objects.hash(hunger); - } - - @Override - public boolean equals(Object o) { - return o == this || o instanceof HungerLockKey && hunger == ((HungerLockKey) o).hunger; - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java index 3e1735c..68f52d3 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ItemLockKey.java @@ -23,17 +23,6 @@ public ItemLockKey(@Nonnull Item item, @Nullable CompoundNBT nbt) { this.item = item; } - @Nullable - public static ItemLockKey fromObject(@Nonnull Object object) { - if (object instanceof ItemStack) { - ItemStack stack = (ItemStack) object; - return stack.isEmpty() ? null : new ItemLockKey(stack.getItem(), stack.getTag()); - } else if (object instanceof Item) { - return new ItemLockKey((Item) object); - } - return null; - } - @Override @Nonnull public ILockKey getNotFuzzy() { @@ -56,4 +45,15 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(item, nbt); } + + @Nullable + public static ItemLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + return stack.isEmpty() ? null : new ItemLockKey(stack.getItem(), stack.getTag()); + } else if (object instanceof Item) { + return new ItemLockKey((Item) object); + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java index cd9a6b0..f198ca9 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/ModLockKey.java @@ -27,6 +27,29 @@ public ModLockKey(@Nonnull String modName, @Nullable CompoundNBT nbt) { this.modName = modName.toLowerCase(); } + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return isNotFuzzy() ? this : new ModLockKey(modName); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof ModLockKey) { + ModLockKey other = (ModLockKey) o; + return modName.equals(other.modName) && Objects.equals(nbt, other.nbt); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(modName, nbt); + } + @Nullable public static ModLockKey fromObject(@Nonnull Object object) { if (object instanceof IForgeRegistryEntry) { @@ -58,27 +81,4 @@ private static ModLockKey fromRegistryEntry(@Nonnull IForgeRegistryEntry ResourceLocation registryName = registryEntry.getRegistryName(); return registryName == null ? null : new ModLockKey(registryName.getNamespace(), nbt); } - - @Override - @Nonnull - public ILockKey getNotFuzzy() { - return isNotFuzzy() ? this : new ModLockKey(modName); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof ModLockKey) { - ModLockKey other = (ModLockKey) o; - return modName.equals(other.modName) && Objects.equals(nbt, other.nbt); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(modName, nbt); - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java index b7ee257..0a17ee5 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/SaturationLockKey.java @@ -24,6 +24,32 @@ public SaturationLockKey(float saturation) { this.saturation = saturation; } + @Override + public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { + return o == this || o instanceof SaturationLockKey && saturation >= ((SaturationLockKey) o).saturation; + } + + @Override + public boolean isNotFuzzy() { + return false; + } + + @Override + @Nonnull + public ILockKey getNotFuzzy() { + return NOT_FUZZY; + } + + @Override + public int hashCode() { + return Objects.hash(saturation); + } + + @Override + public boolean equals(Object o) { + return o == this || o instanceof SaturationLockKey && saturation == ((SaturationLockKey) o).saturation; + } + @Nullable public static SaturationLockKey fromObject(@Nonnull Object object) { if (object instanceof ItemStack) { @@ -54,30 +80,4 @@ private static SaturationLockKey fromFood(@Nullable Food food) { //Ensure that the value is actually positive return saturation < 0 ? null : new SaturationLockKey(saturation); } - - @Override - public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { - return o == this || o instanceof SaturationLockKey && saturation >= ((SaturationLockKey) o).saturation; - } - - @Override - public boolean isNotFuzzy() { - return false; - } - - @Override - @Nonnull - public ILockKey getNotFuzzy() { - return NOT_FUZZY; - } - - @Override - public int hashCode() { - return Objects.hash(saturation); - } - - @Override - public boolean equals(Object o) { - return o == this || o instanceof SaturationLockKey && saturation == ((SaturationLockKey) o).saturation; - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/TagLockKey.java similarity index 50% rename from src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java rename to src/main/java/com/teamacronymcoders/epos/locks/keys/TagLockKey.java index 7eef156..f621df6 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/ParentTagLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/TagLockKey.java @@ -1,11 +1,12 @@ -package com.teamacronymcoders.epos.locks.keys.tag; +package com.teamacronymcoders.epos.locks.keys; -import com.teamacronymcoders.epos.api.EposAPI; -import com.teamacronymcoders.epos.api.locks.keys.IParentLockKey; -import com.teamacronymcoders.epos.api.requirements.IRequirement; -import java.util.ArrayList; +import com.teamacronymcoders.epos.api.locks.keys.ILockKey; +import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.block.Block; @@ -20,28 +21,52 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; -//TODO: Instead of this being a ParentLockKey, this could be done via the MultiLockKeyCreator system -public class ParentTagLockKey implements IParentLockKey { +//TODO: Do we want a param that says "what type" the tag is for (would it even make sense to have one like that) +public class TagLockKey extends NBTLockKey { + private static final List EMPTY = Collections.emptyList(); + + private final ResourceLocation tag; + + public TagLockKey(ResourceLocation tag) { + this(tag, null); + } + + public TagLockKey(@Nonnull ResourceLocation tag, @Nullable CompoundNBT nbt) { + super(nbt); + this.tag = tag; + } + + @Override @Nonnull - private final Collection tags; - @Nullable - private final CompoundNBT nbt; + public ILockKey getNotFuzzy() { + return isNotFuzzy() ? this : new TagLockKey(tag); + } - private ParentTagLockKey(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { - this.tags = tags; - this.nbt = nbt == null || nbt.isEmpty() ? null : nbt; + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (o instanceof TagLockKey && tag.equals(((TagLockKey) o).tag)) { + return getNBT() == null ? ((TagLockKey) o).getNBT() == null : getNBT().equals(((TagLockKey) o).getNBT()); + } + return false; } - @Nullable - public static ParentTagLockKey fromObject(@Nonnull Object object) { + @Override + public int hashCode() { + return Objects.hash(tag, nbt); + } + + @Nonnull + public static List getKeysFromObject(@Nonnull Object object) { //TODO: Make an easier way for third party mods to add an object -> tag list/tags system - // At that point it may make more sense for this to not exist and just directly interact with TagLockKey, - // and keep track of Tag + // At that point it may make more sense for TagLockKey to just directly keep track of Tag if (object instanceof ItemStack) { ItemStack stack = (ItemStack) object; if (stack.isEmpty()) { - return null; + return EMPTY; } return fromTags(stack.getItem().getTags(), stack.getTag()); } else if (object instanceof Item) { @@ -62,26 +87,19 @@ public static ParentTagLockKey fromObject(@Nonnull Object object) { } else if (object instanceof EntityType) { return fromTags(((EntityType) object).getTags()); } - return null; + return EMPTY; } - @Nullable - private static ParentTagLockKey fromTags(@Nonnull Collection tags) { + @Nonnull + public static List fromTags(@Nonnull Collection tags) { return fromTags(tags, null); } - @Nullable - private static ParentTagLockKey fromTags(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { - return tags.isEmpty() ? null : new ParentTagLockKey(tags, nbt); - } - @Nonnull - @Override - public List getSubRequirements() { - List requirements = new ArrayList<>(); - for (ResourceLocation location : tags) { - requirements.addAll(EposAPI.LOCK_REGISTRY.getFuzzyRequirements(new TagLockKey(location, nbt))); + public static List fromTags(@Nonnull Collection tags, @Nullable CompoundNBT nbt) { + if (tags.isEmpty()) { + return EMPTY; } - return requirements; + return tags.stream().map(tag -> new TagLockKey(tag, nbt)).collect(Collectors.toList()); } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java index 9b40b23..c5d3629 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityDamageKey.java @@ -11,14 +11,14 @@ public EntityDamageKey(EntityType entityType) { super(entityType); } + @Override + public boolean equals(Object obj) { + return obj instanceof EntityDamageKey && super.equals(obj); + } + @Nullable public static EntityDamageKey fromObject(@Nonnull Object object) { EntityType type = getEntityType(object); return type == null ? null : new EntityDamageKey<>(type); } - - @Override - public boolean equals(Object obj) { - return obj instanceof EntityDamageKey && super.equals(obj); - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java index 1385000..2f31904 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityMountKey.java @@ -11,14 +11,14 @@ public EntityMountKey(EntityType entityType) { super(entityType); } + @Override + public boolean equals(Object obj) { + return obj instanceof EntityMountKey && super.equals(obj); + } + @Nullable public static EntityMountKey fromObject(@Nonnull Object object) { EntityType type = getEntityType(object); return type == null ? null : new EntityMountKey<>(type); } - - @Override - public boolean equals(Object obj) { - return obj instanceof EntityMountKey && super.equals(obj); - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java index 2e8911d..9ee7cc3 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/entity/EntityTameKey.java @@ -11,14 +11,14 @@ public EntityTameKey(EntityType entityType) { super(entityType); } + @Override + public boolean equals(Object obj) { + return obj instanceof EntityTameKey && super.equals(obj); + } + @Nullable public static EntityTameKey fromObject(@Nonnull Object object) { EntityType type = getEntityType(object); return type == null ? null : new EntityTameKey<>(type); } - - @Override - public boolean equals(Object obj) { - return obj instanceof EntityTameKey && super.equals(obj); - } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java index 1dc2da8..785e7bb 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/BlockHarvestLockKey.java @@ -23,24 +23,6 @@ public BlockHarvestLockKey(int harvestLevel) { super(harvestLevel); } - @Nullable - public static BlockHarvestLockKey fromObject(@Nonnull Object object) { - if (object instanceof ItemStack) { - ItemStack stack = (ItemStack) object; - if (stack.isEmpty()) { - return null; - } - Block block = Block.getBlockFromItem(stack.getItem()); - return block == Blocks.AIR ? null : new BlockHarvestLockKey(block.getHarvestLevel(block.getDefaultState())); - } else if (object instanceof BlockState) { - return new BlockHarvestLockKey(((BlockState) object).getHarvestLevel()); - } else if (object instanceof Block) { - Block block = (Block) object; - return new BlockHarvestLockKey(block.getHarvestLevel(block.getDefaultState())); - } - return null; - } - @Override public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { return o == this || o instanceof BlockHarvestLockKey && harvestLevel >= ((BlockHarvestLockKey) o).harvestLevel; @@ -61,4 +43,22 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(harvestLevel); } + + @Nullable + public static BlockHarvestLockKey fromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return null; + } + Block block = Block.getBlockFromItem(stack.getItem()); + return block == Blocks.AIR ? null : new BlockHarvestLockKey(block.getHarvestLevel(block.getDefaultState())); + } else if (object instanceof BlockState) { + return new BlockHarvestLockKey(((BlockState) object).getHarvestLevel()); + } else if (object instanceof Block) { + Block block = (Block) object; + return new BlockHarvestLockKey(block.getHarvestLevel(block.getDefaultState())); + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java index 3f68e22..5eb634e 100644 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java +++ b/src/main/java/com/teamacronymcoders/epos/locks/keys/harvest/ToolHarvestLockKey.java @@ -29,28 +29,6 @@ public ToolHarvestLockKey(@Nonnull ToolType toolType, int harvestLevel) { this.toolType = toolType; } - @Nonnull - public static List getKeysFromObject(@Nonnull Object object) { - if (!(object instanceof ItemStack)) { - //If we are not an ItemStack fail - return EMPTY; - } - ItemStack stack = (ItemStack) object; - if (stack.isEmpty()) { - //Fail if our stack is empty - return EMPTY; - } - List keys = new ArrayList<>(); - Item item = stack.getItem(); - for (ToolType type : item.getToolTypes(stack)) { - int level = item.getHarvestLevel(stack, type, null, null); - if (level >= 0) { - keys.add(new ToolHarvestLockKey(type, level)); - } - } - return keys; - } - @Override public boolean fuzzyEquals(@Nonnull IFuzzyLockKey o) { if (o == this) { @@ -85,4 +63,24 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(toolType, harvestLevel); } + + @Nonnull + public static List getKeysFromObject(@Nonnull Object object) { + if (object instanceof ItemStack) { + ItemStack stack = (ItemStack) object; + if (stack.isEmpty()) { + return EMPTY; + } + List keys = new ArrayList<>(); + Item item = stack.getItem(); + for (ToolType type : item.getToolTypes(stack)) { + int level = item.getHarvestLevel(stack, type, null, null); + if (level >= 0) { + keys.add(new ToolHarvestLockKey(type, level)); + } + } + return keys; + } + return EMPTY; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java b/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java deleted file mode 100644 index 43e5e14..0000000 --- a/src/main/java/com/teamacronymcoders/epos/locks/keys/tag/TagLockKey.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.teamacronymcoders.epos.locks.keys.tag; - -import com.teamacronymcoders.epos.api.locks.keys.ILockKey; -import com.teamacronymcoders.epos.api.locks.keys.NBTLockKey; -import java.util.Objects; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.ResourceLocation; - -//TODO: Do we want a param that says "what type" the tag is for (would it even make sense to have one like that) -public class TagLockKey extends NBTLockKey { - - private final ResourceLocation tag; - - public TagLockKey(ResourceLocation tag) { - this(tag, null); - } - - public TagLockKey(@Nonnull ResourceLocation tag, @Nullable CompoundNBT nbt) { - super(nbt); - this.tag = tag; - } - - @Override - @Nonnull - public ILockKey getNotFuzzy() { - return isNotFuzzy() ? this : new TagLockKey(tag); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof TagLockKey && tag.equals(((TagLockKey) o).tag)) { - return getNBT() == null ? ((TagLockKey) o).getNBT() == null : getNBT().equals(((TagLockKey) o).getNBT()); - } - return false; - } - - @Override - public int hashCode() { - return Objects.hash(tag, nbt); - } -} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java index b04f5e0..ce42063 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/LockAPITest.java @@ -3,7 +3,6 @@ import com.teamacronymcoders.epos.api.EposAPI; import com.teamacronymcoders.epos.api.locks.keys.DoubleLockKey; import com.teamacronymcoders.epos.api.locks.keys.IntegerLockKey; -import com.teamacronymcoders.epos.api.locks.keys.ListLockKey; import com.teamacronymcoders.epos.api.locks.keys.StringLockKey; import com.teamacronymcoders.epos.api.requirements.IRequirement; import com.teamacronymcoders.epos.api.requirements.SimpleRequirement; @@ -22,8 +21,9 @@ class LockAPITest { static void registerLockTypes() { EposAPI.LOCK_REGISTRY.registerLockType(DoubleLockKey::fromObject); EposAPI.LOCK_REGISTRY.registerLockType(IntegerLockKey::fromObject); - EposAPI.LOCK_REGISTRY.registerLockType(ListLockKey::fromObject); - EposAPI.LOCK_REGISTRY.registerLockType(object -> object instanceof String ? new StringLockKey((String) object) : null); + EposAPI.LOCK_REGISTRY.registerLockType(StringLockKey::fromObject); + + EposAPI.LOCK_REGISTRY.registerMultiLockType(StringLockKey::getKeysFromObject); } /** @@ -47,9 +47,8 @@ void simpleAddRetrieve() { } @Test - @DisplayName("Test retrieval via ParentLockKey") + @DisplayName("Test retrieval via multi lock creator system") void fromParentLock() { - //ListLockKey EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("1"), Collections.singletonList(new SimpleRequirement("1"))); EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("2"), Collections.singletonList(new SimpleRequirement("2"))); EposAPI.LOCK_REGISTRY.addLockByKey(new StringLockKey("3"), Collections.singletonList(new SimpleRequirement("3"))); diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java deleted file mode 100644 index af598c1..0000000 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/ListLockKey.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.teamacronymcoders.epos.api.locks.keys; - -import com.teamacronymcoders.epos.api.EposAPI; -import com.teamacronymcoders.epos.api.requirements.IRequirement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class ListLockKey implements IParentLockKey { - - private final List values; - - private ListLockKey(List values) { - this.values = values; - } - - @Nullable - public static ListLockKey fromObject(@Nonnull Object object) { - if (object instanceof List) { - return new ListLockKey<>((List) object); - } else if (object instanceof String) { - String string = (String) object; - return string.contains(",") ? new ListLockKey<>(Arrays.asList(string.split("\\s*,\\s*"))) : null; - } - return null; - } - - @Nonnull - @Override - public List getSubRequirements() { - List requirements = new ArrayList<>(); - for (TYPE value : values) { - requirements.addAll(EposAPI.LOCK_REGISTRY.getLocks(value)); - } - return requirements; - } -} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java index 9e65f6a..d4a5b17 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java +++ b/src/test/java/com/teamacronymcoders/epos/api/locks/keys/StringLockKey.java @@ -1,9 +1,15 @@ package com.teamacronymcoders.epos.api.locks.keys; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class StringLockKey implements ILockKey { + private static final List EMPTY = Collections.emptyList(); + @Nonnull private final String value; @@ -20,4 +26,26 @@ public boolean equals(Object obj) { public int hashCode() { return value.hashCode(); } + + @Nullable + public static StringLockKey fromObject(@Nonnull Object object) { + return object instanceof String ? new StringLockKey((String) object) : null; + } + + @Nonnull + public static List getKeysFromObject(@Nonnull Object object) { + if (object instanceof String) { + String string = (String) object; + if (!string.contains(",")) { + return EMPTY; + } + List keys = new ArrayList<>(); + String[] strings = string.split("\\s*,\\s*"); + for (String s : strings) { + keys.add(new StringLockKey(s)); + } + return keys; + } + return EMPTY; + } } \ No newline at end of file From 2e0af32b509f1ba757a532f2ca506c0ee11cd537 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Fri, 4 Oct 2019 12:32:49 -0400 Subject: [PATCH 12/14] First pass outlining some of the things that will be needed for/by requirements --- gradle.properties | 4 +-- .../epos/api/requirements/IRequirement.java | 33 +++++++++++++++++-- .../requirements/IRequirementCombiner.java | 4 +++ .../api/requirements/RequirementCombiner.java | 14 ++++++++ .../api/requirements/RequirementRegistry.java | 14 ++++++++ .../epos/requirements/SkillRequirement.java | 21 ++++++++++++ .../requirements/logic/ANDRequirement.java | 27 +++++++++++++++ .../requirements/logic/DoubleRequirement.java | 27 +++++++++++++++ .../requirements/logic/NANDRequirement.java | 27 +++++++++++++++ .../requirements/logic/NORRequirement.java | 27 +++++++++++++++ .../requirements/logic/NOTRequirement.java | 28 ++++++++++++++++ .../requirements/logic/ORRequirement.java | 27 +++++++++++++++ .../requirements/logic/XNORRequirement.java | 27 +++++++++++++++ .../requirements/logic/XORRequirement.java | 27 +++++++++++++++ .../api/requirements/SimpleRequirement.java | 17 ++++++++++ 15 files changed, 320 insertions(+), 4 deletions(-) create mode 100644 src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirementCombiner.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementCombiner.java create mode 100644 src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java create mode 100644 src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java diff --git a/gradle.properties b/gradle.properties index 5e23eff..19fcf1a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ minecraft_version=1.14.4 -forge_version=28.1.31 -mappings_version=20191003-1.14.3 +forge_version=28.1.34 +mappings_version=20191004-1.14.3 base_version=4.0.0 junit_version=5.5.2 diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java index 7b63ea1..42a9d39 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java @@ -1,6 +1,35 @@ package com.teamacronymcoders.epos.api.requirements; -//TODO: Actually implement this and other stuff, this package and this interface are currently -// Just placeholders so that the lock logic has something to reference +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; + public interface IRequirement { + + /** + * Gets the tooltip for this requirement to show in various places like GUIs. + * @param matches True if the requirement is met or false if it is not met. + * @return An {@link ITextComponent} to display for this requirement. + * @implNote It is expected to support both values of matches so that it is + * easy for players to determine if they meet a requirement or not. + * @apiNote This method will also be used by things like "not" requirements. + */ + @Nonnull + ITextComponent getToolTip(boolean matches); + + /** + * Checks if this requirement is met by the given {@link LivingEntity} who has the + * given {@link ICharacterStats} + * @param entity The entity to check. + * @param stats The {@link ICharacterStats} of the entity. + * @return True if the entity meets this requirement, false otherwise. + */ + boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats); + + //TODO: Requirement comparision, Allow for "extended" data so that things like + // skills|level in reskillable would then say "same type", and then give the number + // Maybe have it be another interface that is for supporting extended compare + + //TODO: Add support for requirement caching. } \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirementCombiner.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirementCombiner.java new file mode 100644 index 0000000..e8d4548 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirementCombiner.java @@ -0,0 +1,4 @@ +package com.teamacronymcoders.epos.api.requirements; + +public interface IRequirementCombiner { +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementCombiner.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementCombiner.java new file mode 100644 index 0000000..640cff8 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementCombiner.java @@ -0,0 +1,14 @@ +package com.teamacronymcoders.epos.api.requirements; + +//TODO: Rename this so it is clearer that this is just a "Default" simple implementation +public class RequirementCombiner implements IRequirementCombiner { + + //TODO: Theoretically we could and *should* flatten the requirements so that + // if we have an outermost "and" requirement in the list of requirements + // we should split it so that it is no longer an "and" requirement. + // Could this maybe be used as a sort of proof of concept of the system for + // making it so that it can "apply" multiple combiner types, as strictly speaking + // the API should have no concept of an "and" requirement. + // An alternate option would be to put the default requirement combiner implementation + // inside of Epos instead of the API. (This may make more sense). +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java new file mode 100644 index 0000000..eda899e --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java @@ -0,0 +1,14 @@ +package com.teamacronymcoders.epos.api.requirements; + +//TODO: Look into if this can/should use an existing system. +// Requirements could just be a forge registry, and then we have a class +// that helps manage them and interact with them. +public class RequirementRegistry { + + //TODO: We will need serializers to get requirements from JSON and also for sending + // over the network + // NOTE: We want to make sure that the impl for the serializers of logic requirements + // do a few checks to try and simplify things similar to the LogicParser class in + // Reskillable. We should also make sure that if it gets simplified it prints out + // a message to the log to inform the pack dev that they can simplify their requirement +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java new file mode 100644 index 0000000..f7e5089 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java @@ -0,0 +1,21 @@ +package com.teamacronymcoders.epos.requirements; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; + +public class SkillRequirement implements IRequirement { + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + return null; + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java new file mode 100644 index 0000000..647886b --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +public class ANDRequirement extends DoubleRequirement { + + public ANDRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + super(leftRequirement, rightRequirement); + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + //TODO: Add the lang key to the lang file with the proper format + return new TranslationTextComponent("requirement.epos.tooltip.and", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return leftRequirement.isMet(entity, stats) && rightRequirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java new file mode 100644 index 0000000..f13056c --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; + +public abstract class DoubleRequirement implements IRequirement { + + @Nonnull + protected final IRequirement leftRequirement; + @Nonnull + protected final IRequirement rightRequirement; + + protected DoubleRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + this.leftRequirement = leftRequirement; + this.rightRequirement = rightRequirement; + } + + @Nonnull + public IRequirement getLeftRequirement() { + return leftRequirement; + } + + @Nonnull + public IRequirement getRightRequirement() { + return rightRequirement; + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java new file mode 100644 index 0000000..6d9b8b7 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +public class NANDRequirement extends DoubleRequirement { + + public NANDRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + super(leftRequirement, rightRequirement); + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + //TODO: Add the lang key to the lang file with the proper format + return new TranslationTextComponent("requirement.epos.tooltip.nand", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return !leftRequirement.isMet(entity, stats) || !rightRequirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java new file mode 100644 index 0000000..d66bf12 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +public class NORRequirement extends DoubleRequirement { + + public NORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + super(leftRequirement, rightRequirement); + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + //TODO: Add the lang key to the lang file with the proper format + return new TranslationTextComponent("requirement.epos.tooltip.nor", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return !leftRequirement.isMet(entity, stats) && !rightRequirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java new file mode 100644 index 0000000..908c0be --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java @@ -0,0 +1,28 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; + +public class NOTRequirement implements IRequirement { + + @Nonnull + private final IRequirement requirement; + + public NOTRequirement(@Nonnull IRequirement requirement) { + this.requirement = requirement; + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + return requirement.getToolTip(!matches); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return !requirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java new file mode 100644 index 0000000..eda1a88 --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +public class ORRequirement extends DoubleRequirement { + + public ORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + super(leftRequirement, rightRequirement); + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + //TODO: Add the lang key to the lang file with the proper format + return new TranslationTextComponent("requirement.epos.tooltip.or", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return leftRequirement.isMet(entity, stats) || rightRequirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java new file mode 100644 index 0000000..3246cfd --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +public class XNORRequirement extends DoubleRequirement { + + public XNORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + super(leftRequirement, rightRequirement); + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + //TODO: Add the lang key to the lang file with the proper format + return new TranslationTextComponent("requirement.epos.tooltip.xnor", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return leftRequirement.isMet(entity, stats) == rightRequirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java new file mode 100644 index 0000000..40d711a --- /dev/null +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.requirements.logic; + +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import com.teamacronymcoders.epos.api.requirements.IRequirement; +import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +public class XORRequirement extends DoubleRequirement { + + public XORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirement rightRequirement) { + super(leftRequirement, rightRequirement); + } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + //TODO: Add the lang key to the lang file with the proper format + return new TranslationTextComponent("requirement.epos.tooltip.xor", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return leftRequirement.isMet(entity, stats) != rightRequirement.isMet(entity, stats); + } +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java index 38efc8e..990238d 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java +++ b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java @@ -1,6 +1,10 @@ package com.teamacronymcoders.epos.api.requirements; +import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import javax.annotation.Nonnull; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; /** * Simple implementation of IRequirement that can be compared by the name it got passed. @@ -11,9 +15,11 @@ public class SimpleRequirement implements IRequirement { @Nonnull private final String name; + private final ITextComponent tooltip; public SimpleRequirement(@Nonnull String name) { this.name = name; + this.tooltip = new StringTextComponent(name); } @Nonnull @@ -30,4 +36,15 @@ public boolean equals(Object obj) { public int hashCode() { return name.hashCode(); } + + @Nonnull + @Override + public ITextComponent getToolTip(boolean matches) { + return tooltip; + } + + @Override + public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + return false; + } } \ No newline at end of file From 9f27d6494c0d704deff1046aff0618adac7389c4 Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Tue, 19 Nov 2019 12:17:50 -0500 Subject: [PATCH 13/14] Commit various parts of my work on requirement comparision so that I can access it easier from another machine if I don't work on it more before then. --- gradle.properties | 4 +- .../epos/api/requirements/IRequirement.java | 39 ++++++++++++++----- .../requirements/RequirementComparision.java | 27 +++++++++++++ .../api/requirements/RequirementRegistry.java | 2 + .../epos/requirements/SkillRequirement.java | 15 +++++++ .../requirements/logic/ANDRequirement.java | 29 ++++++++++++++ .../requirements/logic/DoubleRequirement.java | 29 ++++++++++++++ .../requirements/logic/NANDRequirement.java | 17 ++++++++ .../requirements/logic/NORRequirement.java | 17 ++++++++ .../requirements/logic/NOTRequirement.java | 21 ++++++++++ .../requirements/logic/ORRequirement.java | 33 ++++++++++++++++ .../requirements/logic/XNORRequirement.java | 17 ++++++++ .../requirements/logic/XORRequirement.java | 17 ++++++++ .../requirements/LogicRequirementTest.java | 9 +++++ .../api/requirements/SimpleRequirement.java | 14 +++++++ 15 files changed, 279 insertions(+), 11 deletions(-) create mode 100644 src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementComparision.java create mode 100644 src/test/java/com/teamacronymcoders/epos/api/requirements/LogicRequirementTest.java diff --git a/gradle.properties b/gradle.properties index 19fcf1a..6ecb618 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ minecraft_version=1.14.4 -forge_version=28.1.34 -mappings_version=20191004-1.14.3 +forge_version=28.1.90 +mappings_version=20191119-1.14.3 base_version=4.0.0 junit_version=5.5.2 diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java index 42a9d39..d8f1856 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java @@ -1,35 +1,56 @@ package com.teamacronymcoders.epos.api.requirements; import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; +import java.util.function.BiPredicate; import javax.annotation.Nonnull; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; -public interface IRequirement { +public interface IRequirement extends BiPredicate { /** * Gets the tooltip for this requirement to show in various places like GUIs. + * * @param matches True if the requirement is met or false if it is not met. + * * @return An {@link ITextComponent} to display for this requirement. - * @implNote It is expected to support both values of matches so that it is - * easy for players to determine if they meet a requirement or not. + * + * @implNote It is expected to support both values of matches so that it is easy for players to determine if they meet a requirement or not. * @apiNote This method will also be used by things like "not" requirements. */ @Nonnull ITextComponent getToolTip(boolean matches); /** - * Checks if this requirement is met by the given {@link LivingEntity} who has the - * given {@link ICharacterStats} + * Checks if this requirement is met by the given {@link LivingEntity} who has the given {@link ICharacterStats} + * * @param entity The entity to check. - * @param stats The {@link ICharacterStats} of the entity. + * @param stats The {@link ICharacterStats} of the entity. + * * @return True if the entity meets this requirement, false otherwise. */ boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats); - //TODO: Requirement comparision, Allow for "extended" data so that things like - // skills|level in reskillable would then say "same type", and then give the number - // Maybe have it be another interface that is for supporting extended compare + default boolean test(LivingEntity entity, ICharacterStats stats) { + if (entity == null || stats == null) { + return false; + } + return isMet(entity, stats); + } + + /** + * Compares a given {@link IRequirement} against this one and returns a {@link RequirementComparision} of the two requirements. + * + * @param other The {@link IRequirement} to compare. + * + * @return The {@link RequirementComparision} of the given {@link IRequirement} and this one. + */ + @Nonnull + RequirementComparision compare(IRequirement other); + //TODO: Should we have them override hashCode/equals for if the two requirements are identical? + + //TODO: Maybe make an interface for ICombinableRequirement: + // combine(ICombinableRequirement other, Type type), and require that they support "adding" and then optionally multiplying??? //TODO: Add support for requirement caching. } \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementComparision.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementComparision.java new file mode 100644 index 0000000..f7f3735 --- /dev/null +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementComparision.java @@ -0,0 +1,27 @@ +package com.teamacronymcoders.epos.api.requirements; + +//TODO: Maybe come up with a better name for this, also maybe order the enum? +public enum RequirementComparision { + /** + * For use in requirement comparision when the requirement being tested is incompatible with the requirement doing the testing. + */ + INCOMPATIBLE, + /** + * For use in requirement comparision when the requirement being tested is of the same overall type as the requirement doing the testing but has a differing subtype. + * + * For example: if both requirements are skill requirements, but they are for different skills, then this would be returned. + */ + TYPE_MATCHES, + /** + * For use in requirement comparision when the requirement being tested is identical to the requirement doing the testing. + */ + IDENTICAL, + /** + * For use in requirement comparision when the requirement being tested is more restrictive than the requirement doing the testing. + */ + MORE_RESTRICTIVE_THAN, + /** + * For use in requirement comparision when the requirement being tested is less restrictive than the requirement doing the testing. + */ + LESS_RESTRICTIVE_THAN +} \ No newline at end of file diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java index eda899e..c9e74c1 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/RequirementRegistry.java @@ -3,6 +3,8 @@ //TODO: Look into if this can/should use an existing system. // Requirements could just be a forge registry, and then we have a class // that helps manage them and interact with them. +//TODO: Evaluate doing it similar to vanilla and have a RequirementType registry +// and a RequirementSerializer recipe public class RequirementRegistry { //TODO: We will need serializers to get requirements from JSON and also for sending diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java index f7e5089..63e624e 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java @@ -2,6 +2,7 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; @@ -11,11 +12,25 @@ public class SkillRequirement implements IRequirement { @Nonnull @Override public ITextComponent getToolTip(boolean matches) { + //TODO: Implement return null; } @Override public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { + //TODO: Implement return false; } + + @Nonnull + @Override + public RequirementComparision compare(IRequirement other) { + if (other == this) { + return RequirementComparision.IDENTICAL; + } else if (other instanceof SkillRequirement) { + //TODO: Check the skill information of the two requirements to try and give a better comparision + return RequirementComparision.TYPE_MATCHES; + } + return RequirementComparision.INCOMPATIBLE; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java index 647886b..a081808 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java @@ -2,7 +2,9 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -24,4 +26,31 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return leftRequirement.isMet(entity, stats) && rightRequirement.isMet(entity, stats); } + + @Override + protected boolean isInstance(DoubleRequirement requirement) { + return requirement instanceof ANDRequirement; + } + + @Nullable + @Override + protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + //TODO: Should this upper logic be moved to DoubleRequiremet? + boolean leftIdentical = leftComparision == RequirementComparision.IDENTICAL; + boolean rightIdentical = rightComparision == RequirementComparision.IDENTICAL; + if (leftIdentical && (rightIdentical || rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN)) { + //If one of the requirements are identical then we can take the value of the other one + return rightComparision; + } else if (rightIdentical && (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN)) { + //If one of the requirements are identical then we can take the value of the other one + return leftComparision; + } + //AND specific logic + else if (leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN && rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + return RequirementComparision.MORE_RESTRICTIVE_THAN; + } else if (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN && rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + return RequirementComparision.LESS_RESTRICTIVE_THAN; + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java index f13056c..7bccd45 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java @@ -1,8 +1,12 @@ package com.teamacronymcoders.epos.requirements.logic; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +//TODO: Do we want to add a "simplify" method that returns a list of IRequirement, for use in our combiner +// This would be specifically for our double requirement stuff public abstract class DoubleRequirement implements IRequirement { @Nonnull @@ -24,4 +28,29 @@ public IRequirement getLeftRequirement() { public IRequirement getRightRequirement() { return rightRequirement; } + + @Nonnull + @Override + public RequirementComparision compare(IRequirement other) { + if (other == this) { + return RequirementComparision.IDENTICAL; + } else if (other instanceof DoubleRequirement && isInstance((DoubleRequirement) other)) { + DoubleRequirement otherRequirement = (DoubleRequirement) other; + RequirementComparision comparision = getComparision(getLeftRequirement().compare(otherRequirement.getLeftRequirement()), + getRightRequirement().compare(otherRequirement.getRightRequirement())); + if (comparision != null) { + return comparision; + } + //Check to see if they were just written in the opposite order + comparision = getComparision(getLeftRequirement().compare(otherRequirement.getRightRequirement()), + getRightRequirement().compare(otherRequirement.getLeftRequirement())); + return comparision != null ? comparision : RequirementComparision.TYPE_MATCHES; + } + return RequirementComparision.INCOMPATIBLE; + } + + protected abstract boolean isInstance(DoubleRequirement requirement); + + @Nullable + protected abstract RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision); } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java index 6d9b8b7..a2c6af7 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java @@ -2,7 +2,9 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -24,4 +26,19 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return !leftRequirement.isMet(entity, stats) || !rightRequirement.isMet(entity, stats); } + + @Override + protected boolean isInstance(DoubleRequirement requirement) { + return requirement instanceof NANDRequirement; + } + + @Nullable + @Override + protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.IDENTICAL) { + return RequirementComparision.IDENTICAL; + } + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java index d66bf12..1008380 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java @@ -2,7 +2,9 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -24,4 +26,19 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return !leftRequirement.isMet(entity, stats) && !rightRequirement.isMet(entity, stats); } + + @Override + protected boolean isInstance(DoubleRequirement requirement) { + return requirement instanceof NORRequirement; + } + + @Nullable + @Override + protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.IDENTICAL) { + return RequirementComparision.IDENTICAL; + } + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java index 908c0be..ff41cd0 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java @@ -2,6 +2,7 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; @@ -25,4 +26,24 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return !requirement.isMet(entity, stats); } + + @Nonnull + @Override + public RequirementComparision compare(IRequirement other) { + if (other == this) { + return RequirementComparision.IDENTICAL; + } else if (other instanceof NOTRequirement) { + RequirementComparision innerComparision = requirement.compare(((NOTRequirement) other).requirement); + if (innerComparision == RequirementComparision.IDENTICAL) { + return RequirementComparision.IDENTICAL; + } else if (innerComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + return RequirementComparision.LESS_RESTRICTIVE_THAN; + } else if (innerComparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + return RequirementComparision.MORE_RESTRICTIVE_THAN; + } + //TODO: Evaluate if we should return incompatible if the sub types are incompatible but they are both NOT requirements + return RequirementComparision.TYPE_MATCHES; + } + return RequirementComparision.INCOMPATIBLE; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java index eda1a88..b2fc721 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java @@ -2,7 +2,9 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -24,4 +26,35 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return leftRequirement.isMet(entity, stats) || rightRequirement.isMet(entity, stats); } + + @Override + protected boolean isInstance(DoubleRequirement requirement) { + return requirement instanceof ORRequirement; + } + + @Nullable + @Override + protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + boolean leftIdentical = leftComparision == RequirementComparision.IDENTICAL; + boolean rightIdentical = rightComparision == RequirementComparision.IDENTICAL; + if (leftIdentical && (rightIdentical || rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN)) { + //If one of the requirements are identical then we can take the value of the other one + return rightComparision; + } else if (rightIdentical && (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN)) { + //If one of the requirements are identical then we can take the value of the other one + return leftComparision; + } + //Or specific logic + //TODO: Implement + else if (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN && rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + + } else if (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN && rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + + } else if (leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN && rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + + } else if (leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN && rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java index 3246cfd..03f9123 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java @@ -2,7 +2,9 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -24,4 +26,19 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return leftRequirement.isMet(entity, stats) == rightRequirement.isMet(entity, stats); } + + @Override + protected boolean isInstance(DoubleRequirement requirement) { + return requirement instanceof XNORRequirement; + } + + @Nullable + @Override + protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.IDENTICAL) { + return RequirementComparision.IDENTICAL; + } + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java index 40d711a..36c16f6 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java @@ -2,7 +2,9 @@ import com.teamacronymcoders.epos.api.characterstats.ICharacterStats; import com.teamacronymcoders.epos.api.requirements.IRequirement; +import com.teamacronymcoders.epos.api.requirements.RequirementComparision; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.entity.LivingEntity; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -24,4 +26,19 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return leftRequirement.isMet(entity, stats) != rightRequirement.isMet(entity, stats); } + + @Override + protected boolean isInstance(DoubleRequirement requirement) { + return requirement instanceof XORRequirement; + } + + @Nullable + @Override + protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.IDENTICAL) { + return RequirementComparision.IDENTICAL; + } + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/requirements/LogicRequirementTest.java b/src/test/java/com/teamacronymcoders/epos/api/requirements/LogicRequirementTest.java new file mode 100644 index 0000000..1daac23 --- /dev/null +++ b/src/test/java/com/teamacronymcoders/epos/api/requirements/LogicRequirementTest.java @@ -0,0 +1,9 @@ +package com.teamacronymcoders.epos.api.requirements; + +import org.junit.jupiter.api.DisplayName; + +@DisplayName("Test the requirement comparision implementations of logic requirements") +class LogicRequirementTest { + + //TODO: Implement tests here, we can just have the logic requirements be wrappers around our test impl of a requirement SimpleRequirement +} \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java index 990238d..ca68792 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java +++ b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java @@ -47,4 +47,18 @@ public ITextComponent getToolTip(boolean matches) { public boolean isMet(@Nonnull LivingEntity entity, @Nonnull ICharacterStats stats) { return false; } + + @Nonnull + @Override + public RequirementComparision compare(IRequirement other) { + if (other == this) { + return RequirementComparision.IDENTICAL; + } else if (other instanceof SimpleRequirement) { + if (name.equals(((SimpleRequirement) other).name)) { + return RequirementComparision.IDENTICAL; + } + return RequirementComparision.TYPE_MATCHES; + } + return RequirementComparision.INCOMPATIBLE; + } } \ No newline at end of file From 266f6b4d63daf2a111d6a5c28f16cfc3496d0def Mon Sep 17 00:00:00 2001 From: pupnewfster Date: Wed, 29 Apr 2020 10:39:49 -0400 Subject: [PATCH 14/14] More docs and various other stuff I don't remember what it is --- .../epos/api/requirements/IRequirement.java | 19 ++++++++ .../epos/requirements/SkillRequirement.java | 5 +++ .../requirements/logic/ANDRequirement.java | 31 +++++++++++-- .../requirements/logic/DoubleRequirement.java | 45 ++++++++++++++++++- .../requirements/logic/NANDRequirement.java | 11 ++++- .../requirements/logic/NORRequirement.java | 11 ++++- .../requirements/logic/NOTRequirement.java | 5 +++ .../requirements/logic/ORRequirement.java | 25 ++++++++++- .../requirements/logic/XNORRequirement.java | 11 ++++- .../requirements/logic/XORRequirement.java | 11 ++++- .../api/requirements/SimpleRequirement.java | 5 +++ 11 files changed, 164 insertions(+), 15 deletions(-) diff --git a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java index d8f1856..a3958fc 100644 --- a/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java +++ b/src/api/java/com/teamacronymcoders/epos/api/requirements/IRequirement.java @@ -8,6 +8,8 @@ public interface IRequirement extends BiPredicate { + //TODO: Do we need some other form of check, because for logic requirements if we want to show individual branches as + // being "met" we do not have enough information from a boolean of if it is met overall /** * Gets the tooltip for this requirement to show in various places like GUIs. * @@ -44,9 +46,26 @@ default boolean test(LivingEntity entity, ICharacterStats stats) { * @param other The {@link IRequirement} to compare. * * @return The {@link RequirementComparision} of the given {@link IRequirement} and this one. + * + * @implNote While the default implementations do check {@link #canCompareWith(IRequirement)}, it still makes sense to verify that the type is proper when + * implementing this method, as the spec does not require checking {@link #canCompareWith(IRequirement)} given that is mainly a helper method to allow quick failing + * if neither {@link IRequirement} knows how to compare to the other. */ @Nonnull RequirementComparision compare(IRequirement other); + + /** + * A helper method to allow quickly checking if this {@link IRequirement} is comparable with another {@link IRequirement}. This is mainly used so that in cases where + * there may be multiple requirements stored in a single requirement, such as with logic requirements, so then while this {@link IRequirement} may not know how to + * compare itself to the logic requirement, we can quickly check the other direction and see that the logic requirement knows how to compare itself against us. + * + * @param other The {@link IRequirement} to check if we know how to compare to. + * + * @return True if we can compare ourselves with the given {@link IRequirement}, false otherwise. + * + * @apiNote It is not required to check this method before calling {@link #compare(IRequirement)} but it is recommended. + */ + boolean canCompareWith(IRequirement other); //TODO: Should we have them override hashCode/equals for if the two requirements are identical? //TODO: Maybe make an interface for ICombinableRequirement: diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java index 63e624e..36f4768 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/SkillRequirement.java @@ -33,4 +33,9 @@ public RequirementComparision compare(IRequirement other) { } return RequirementComparision.INCOMPATIBLE; } + + @Override + public boolean canCompareWith(IRequirement other) { + return other instanceof SkillRequirement; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java index a081808..a3e9808 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ANDRequirement.java @@ -18,8 +18,8 @@ public ANDRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequireme @Nonnull @Override public ITextComponent getToolTip(boolean matches) { - //TODO: Add the lang key to the lang file with the proper format - return new TranslationTextComponent("requirement.epos.tooltip.and", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + //TODO: Add the lang key to the lang file with the proper format, and matching values, as one may match and the other may not + return new TranslationTextComponent("requirement.epos.tooltip.and", leftRequirement.getToolTip(matches), rightRequirement.getToolTip(matches)); } @Override @@ -35,7 +35,7 @@ protected boolean isInstance(DoubleRequirement requirement) { @Nullable @Override protected RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { - //TODO: Should this upper logic be moved to DoubleRequiremet? + //TODO: Should this upper logic be moved to DoubleRequirement? boolean leftIdentical = leftComparision == RequirementComparision.IDENTICAL; boolean rightIdentical = rightComparision == RequirementComparision.IDENTICAL; if (leftIdentical && (rightIdentical || rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN)) { @@ -53,4 +53,29 @@ else if (leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN && righ } return null; } + + @Nullable + @Override + protected RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + if (leftComparision == rightComparision) { + //If they both agree on the comparision type, then we go with that type + return leftComparision; + } else if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN || + rightComparision == RequirementComparision.IDENTICAL && leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + //If one is identical, but the other is more restrictive, then we are more restrictive overall + return RequirementComparision.MORE_RESTRICTIVE_THAN; + } else if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || + rightComparision == RequirementComparision.IDENTICAL && leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + //If one is identical, but the other is less restrictive, then the most restrictive comparision is identical + return RequirementComparision.IDENTICAL; + } else if (leftComparision == RequirementComparision.IDENTICAL || rightComparision == RequirementComparision.IDENTICAL) { + //If only one of them is identical, we have extra restrictions being the second requirement so we are more restrictive + return RequirementComparision.MORE_RESTRICTIVE_THAN; + } else if (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN && rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN || + rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN && leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + //If one is more restrictive, but the other is less restrictive, then they are incompatible + return RequirementComparision.INCOMPATIBLE; + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java index 7bccd45..6396063 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/DoubleRequirement.java @@ -29,14 +29,25 @@ public IRequirement getRightRequirement() { return rightRequirement; } + @Override + public boolean canCompareWith(IRequirement other) { + return true; + } + @Nonnull @Override public RequirementComparision compare(IRequirement other) { if (other == this) { return RequirementComparision.IDENTICAL; - } else if (other instanceof DoubleRequirement && isInstance((DoubleRequirement) other)) { + } + RequirementComparision comparision = getSingleComparision(getSingleComparision(leftRequirement, other), getSingleComparision(rightRequirement, other)); + //TODO: FIXME: So that this merges with the other comparision properly + if (comparision != null) { + return comparision; + } + if (other instanceof DoubleRequirement && isInstance((DoubleRequirement) other)) { DoubleRequirement otherRequirement = (DoubleRequirement) other; - RequirementComparision comparision = getComparision(getLeftRequirement().compare(otherRequirement.getLeftRequirement()), + comparision = getComparision(getLeftRequirement().compare(otherRequirement.getLeftRequirement()), getRightRequirement().compare(otherRequirement.getRightRequirement())); if (comparision != null) { return comparision; @@ -53,4 +64,34 @@ public RequirementComparision compare(IRequirement other) { @Nullable protected abstract RequirementComparision getComparision(RequirementComparision leftComparision, RequirementComparision rightComparision); + + //TODO: Docs, basically is a method that figures out what the overall comparision is based on the pieces + //TODO: Add support for checking partial matches, which is why canCompareWith always returns true + // For example if one requirement in an AND requirement is identical to other, then we can have this be MORE_RESTRICTIVE + @Nullable + protected abstract RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision); + + //TODO: Do we want this to be able to have TYPE_MATCHES? + @Nonnull + private RequirementComparision getSingleComparision(IRequirement inner, IRequirement other) { + if (inner.canCompareWith(other)) { + RequirementComparision comparision = inner.compare(other); + if (comparision == RequirementComparision.IDENTICAL || comparision == RequirementComparision.LESS_RESTRICTIVE_THAN || + comparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + return comparision; + } + } + if (other.canCompareWith(inner)) { + RequirementComparision comparision = inner.compare(other); + if (comparision == RequirementComparision.IDENTICAL) { + return comparision; + } else if (comparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + return RequirementComparision.LESS_RESTRICTIVE_THAN; + } else if (comparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + return RequirementComparision.MORE_RESTRICTIVE_THAN; + } + return RequirementComparision.INCOMPATIBLE; + } + return RequirementComparision.INCOMPATIBLE; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java index a2c6af7..9f1c389 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NANDRequirement.java @@ -18,8 +18,8 @@ public NANDRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirem @Nonnull @Override public ITextComponent getToolTip(boolean matches) { - //TODO: Add the lang key to the lang file with the proper format - return new TranslationTextComponent("requirement.epos.tooltip.nand", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + //TODO: Add the lang key to the lang file with the proper format, and matching values, as one may match and the other may not + return new TranslationTextComponent("requirement.epos.tooltip.nand", leftRequirement.getToolTip(matches), rightRequirement.getToolTip(matches)); } @Override @@ -41,4 +41,11 @@ protected RequirementComparision getComparision(RequirementComparision leftCompa //TODO: Implement return null; } + + @Nullable + @Override + protected RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java index 1008380..4c6ed51 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NORRequirement.java @@ -18,8 +18,8 @@ public NORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequireme @Nonnull @Override public ITextComponent getToolTip(boolean matches) { - //TODO: Add the lang key to the lang file with the proper format - return new TranslationTextComponent("requirement.epos.tooltip.nor", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + //TODO: Add the lang key to the lang file with the proper format, and matching values, as one may match and the other may not + return new TranslationTextComponent("requirement.epos.tooltip.nor", leftRequirement.getToolTip(matches), rightRequirement.getToolTip(matches)); } @Override @@ -41,4 +41,11 @@ protected RequirementComparision getComparision(RequirementComparision leftCompa //TODO: Implement return null; } + + @Nullable + @Override + protected RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java index ff41cd0..6839ee1 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/NOTRequirement.java @@ -46,4 +46,9 @@ public RequirementComparision compare(IRequirement other) { } return RequirementComparision.INCOMPATIBLE; } + + @Override + public boolean canCompareWith(IRequirement other) { + return other instanceof NOTRequirement; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java index b2fc721..70b1b9d 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/ORRequirement.java @@ -18,8 +18,8 @@ public ORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequiremen @Nonnull @Override public ITextComponent getToolTip(boolean matches) { - //TODO: Add the lang key to the lang file with the proper format - return new TranslationTextComponent("requirement.epos.tooltip.or", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + //TODO: Add the lang key to the lang file with the proper format, and matching values, as one may match and the other may not + return new TranslationTextComponent("requirement.epos.tooltip.or", leftRequirement.getToolTip(matches), rightRequirement.getToolTip(matches)); } @Override @@ -57,4 +57,25 @@ else if (leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN && righ } return null; } + + @Nullable + @Override + protected RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + if (leftComparision == rightComparision) { + //If they both agree on the comparision type, then we go with that type + return leftComparision; + } else if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.MORE_RESTRICTIVE_THAN || + rightComparision == RequirementComparision.IDENTICAL && leftComparision == RequirementComparision.MORE_RESTRICTIVE_THAN) { + //If one is identical, but the other is more restrictive, then the more restrictive compare is identical + return RequirementComparision.IDENTICAL; + } else if (leftComparision == RequirementComparision.IDENTICAL && rightComparision == RequirementComparision.LESS_RESTRICTIVE_THAN || + rightComparision == RequirementComparision.IDENTICAL && leftComparision == RequirementComparision.LESS_RESTRICTIVE_THAN) { + //If one is identical, but the other is less restrictive, then we are less restrictive overall + return RequirementComparision.LESS_RESTRICTIVE_THAN; + } else if (leftComparision == RequirementComparision.IDENTICAL || rightComparision == RequirementComparision.IDENTICAL) { + //If only one of them is identical, we have extra options being the second requirement so we are less restrictive + return RequirementComparision.LESS_RESTRICTIVE_THAN; + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java index 03f9123..6cdc922 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XNORRequirement.java @@ -18,8 +18,8 @@ public XNORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequirem @Nonnull @Override public ITextComponent getToolTip(boolean matches) { - //TODO: Add the lang key to the lang file with the proper format - return new TranslationTextComponent("requirement.epos.tooltip.xnor", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + //TODO: Add the lang key to the lang file with the proper format, and matching values, as one may match and the other may not + return new TranslationTextComponent("requirement.epos.tooltip.xnor", leftRequirement.getToolTip(matches), rightRequirement.getToolTip(matches)); } @Override @@ -41,4 +41,11 @@ protected RequirementComparision getComparision(RequirementComparision leftCompa //TODO: Implement return null; } + + @Nullable + @Override + protected RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java index 36c16f6..43d4bc1 100644 --- a/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java +++ b/src/main/java/com/teamacronymcoders/epos/requirements/logic/XORRequirement.java @@ -18,8 +18,8 @@ public XORRequirement(@Nonnull IRequirement leftRequirement, @Nonnull IRequireme @Nonnull @Override public ITextComponent getToolTip(boolean matches) { - //TODO: Add the lang key to the lang file with the proper format - return new TranslationTextComponent("requirement.epos.tooltip.xor", leftRequirement.getToolTip(!matches), rightRequirement.getToolTip(!matches)); + //TODO: Add the lang key to the lang file with the proper format, and matching values, as one may match and the other may not + return new TranslationTextComponent("requirement.epos.tooltip.xor", leftRequirement.getToolTip(matches), rightRequirement.getToolTip(matches)); } @Override @@ -41,4 +41,11 @@ protected RequirementComparision getComparision(RequirementComparision leftCompa //TODO: Implement return null; } + + @Nullable + @Override + protected RequirementComparision getSingleComparision(RequirementComparision leftComparision, RequirementComparision rightComparision) { + //TODO: Implement + return null; + } } \ No newline at end of file diff --git a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java index ca68792..5eb8d8f 100644 --- a/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java +++ b/src/test/java/com/teamacronymcoders/epos/api/requirements/SimpleRequirement.java @@ -61,4 +61,9 @@ public RequirementComparision compare(IRequirement other) { } return RequirementComparision.INCOMPATIBLE; } + + @Override + public boolean canCompareWith(IRequirement other) { + return other instanceof SimpleRequirement; + } } \ No newline at end of file