diff --git a/paper-api/src/main/java/org/bukkit/Registry.java b/paper-api/src/main/java/org/bukkit/Registry.java index 1941df36c..9d0d0d745 100644 --- a/paper-api/src/main/java/org/bukkit/Registry.java +++ b/paper-api/src/main/java/org/bukkit/Registry.java @@ -12,6 +12,7 @@ import org.bukkit.boss.KeyedBossBar; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; import org.bukkit.entity.Villager; +import org.bukkit.entity.memory.MemoryKey; import org.bukkit.loot.LootTables; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -131,6 +132,25 @@ public interface Registry extends Iterable { * @see Villager.Type */ Registry VILLAGER_TYPE = new SimpleRegistry<>(Villager.Type.class); + /** + * Memory Keys. + * + * @see MemoryKey + */ + Registry MEMORY_MODULE_TYPE = new Registry() { + + @NotNull + @Override + public Iterator iterator() { + return MemoryKey.values().iterator(); + } + + @Nullable + @Override + public MemoryKey get(@NotNull NamespacedKey key) { + return MemoryKey.getByKey(key); + } + }; /** * Get the object by its key. diff --git a/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java b/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java index 2dbb81c15..e6249c2bf 100644 --- a/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java @@ -9,6 +9,7 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.attribute.Attributable; import org.bukkit.block.Block; +import org.bukkit.entity.memory.MemoryKey; import org.bukkit.inventory.EntityEquipment; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -474,4 +475,29 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource * @return collision status */ boolean isCollidable(); + + /** + * Returns the value of the memory specified. + *

+ * Note that the value is null when the specific entity does not have that + * value by default. + * + * @param memoryKey memory to access + * @param the type of the return value + * @return a instance of the memory section value or null if not present + */ + @Nullable + T getMemory(@NotNull MemoryKey memoryKey); + + /** + * Sets the value of the memory specified. + *

+ * Note that the value will not be persisted when the specific entity does + * not have that value by default. + * + * @param memoryKey the memory to access + * @param memoryValue a typed memory value + * @param the type of the passed value + */ + void setMemory(@NotNull MemoryKey memoryKey, @Nullable T memoryValue); } diff --git a/paper-api/src/main/java/org/bukkit/entity/memory/MemoryKey.java b/paper-api/src/main/java/org/bukkit/entity/memory/MemoryKey.java new file mode 100644 index 000000000..139e0a0aa --- /dev/null +++ b/paper-api/src/main/java/org/bukkit/entity/memory/MemoryKey.java @@ -0,0 +1,74 @@ +package org.bukkit.entity.memory; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.bukkit.Keyed; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents a key used for accessing memory values of a + * {@link org.bukkit.entity.LivingEntity}. + * + * @param the class type of the memory value + */ +public final class MemoryKey implements Keyed { + + private final NamespacedKey namespacedKey; + private final Class tClass; + + private MemoryKey(NamespacedKey namespacedKey, Class tClass) { + this.namespacedKey = namespacedKey; + this.tClass = tClass; + MEMORY_KEYS.put(namespacedKey, this); + } + + @NotNull + @Override + public NamespacedKey getKey() { + return namespacedKey; + } + + /** + * Gets the class of values associated with this memory. + * + * @return the class of value objects + */ + @NotNull + public Class getMemoryClass() { + return tClass; + } + + private static final Map MEMORY_KEYS = new HashMap<>(); + // + public static final MemoryKey HOME = new MemoryKey<>(NamespacedKey.minecraft("home"), Location.class); + public static final MemoryKey MEETING_POINT = new MemoryKey<>(NamespacedKey.minecraft("meeting_point"), Location.class); + public static final MemoryKey JOB_SITE = new MemoryKey<>(NamespacedKey.minecraft("job_site"), Location.class); + + /** + * Returns a {@link MemoryKey} by a {@link NamespacedKey}. + * + * @param namespacedKey the {@link NamespacedKey} referencing a + * {@link MemoryKey} + * @return the {@link MemoryKey} or null when no {@link MemoryKey} is + * available under that key + */ + @Nullable + public static MemoryKey getByKey(@NotNull NamespacedKey namespacedKey) { + return MEMORY_KEYS.get(namespacedKey); + } + + /** + * Returns the set of all MemoryKeys. + * + * @return the memoryKeys + */ + @NotNull + public static Set values() { + return new HashSet<>(MEMORY_KEYS.values()); + } +} diff --git a/paper-api/src/test/java/org/bukkit/entity/memory/MemoryKeyTest.java b/paper-api/src/test/java/org/bukkit/entity/memory/MemoryKeyTest.java new file mode 100644 index 000000000..b955f6a7a --- /dev/null +++ b/paper-api/src/test/java/org/bukkit/entity/memory/MemoryKeyTest.java @@ -0,0 +1,41 @@ +package org.bukkit.entity.memory; + +import java.util.Arrays; +import java.util.List; +import org.bukkit.NamespacedKey; +import org.junit.Assert; +import org.junit.Test; + +public class MemoryKeyTest { + + @Test + public void shouldContainAllMemories() { + List memories = Arrays.asList(MemoryKey.HOME, MemoryKey.JOB_SITE, MemoryKey.MEETING_POINT); + Assert.assertTrue(MemoryKey.values().containsAll(memories)); + } + + @Test + public void shouldGetMemoryKeyHomeByNamespacedKey() { + Assert.assertEquals(MemoryKey.HOME, MemoryKey.getByKey(NamespacedKey.minecraft("home"))); + } + + @Test + public void shouldGetMemoryKeyJobSiteByNamespacedKey() { + Assert.assertEquals(MemoryKey.JOB_SITE, MemoryKey.getByKey(NamespacedKey.minecraft("job_site"))); + } + + @Test + public void shouldGetMemoryKeyMeetingPointByNamespacedKey() { + Assert.assertEquals(MemoryKey.MEETING_POINT, MemoryKey.getByKey(NamespacedKey.minecraft("meeting_point"))); + } + + @Test + public void shouldReturnNullWhenNamespacedKeyisNotPresentAsMemoryKey() { + Assert.assertEquals(null, MemoryKey.getByKey(NamespacedKey.minecraft("not_present"))); + } + + @Test + public void shouldReturnNullWhenNamespacedKeyisNull() { + Assert.assertNull(MemoryKey.getByKey(null)); + } +}