diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/EntityGoals.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/EntityGoals.java new file mode 100644 index 00000000..10fda81b --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/EntityGoals.java @@ -0,0 +1,45 @@ +package com.willfp.eco.core.entities.ai; + +import com.google.common.collect.HashBiMap; +import com.willfp.eco.core.entities.ai.entity.EntityGoalAvoidEntity; +import com.willfp.eco.core.serialization.KeyedDeserializer; +import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +/** + * Class to manage entity goals. + */ +public final class EntityGoals { + /** + * All registered deserializers. + */ + private static final Map>> BY_KEY = HashBiMap.create(); + + /** + * minecraft:avoid_entity. + */ + public static final KeyedDeserializer AVOID_ENTITY = register(EntityGoalAvoidEntity.DESERIALIZER); + + /** + * Get deserializer by key. + * + * @param key The key. + * @return The deserializer, or null if not found. + */ + @Nullable + public static KeyedDeserializer> getByKey(@NotNull final NamespacedKey key) { + return BY_KEY.get(key); + } + + private static >> T register(@NotNull final T toRegister) { + BY_KEY.put(toRegister.getKey(), toRegister); + return toRegister; + } + + private EntityGoals() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/entity/EntityGoalAvoidEntity.java b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/entity/EntityGoalAvoidEntity.java index b852699d..7d887ac4 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/entities/ai/entity/EntityGoalAvoidEntity.java +++ b/eco-api/src/main/java/com/willfp/eco/core/entities/ai/entity/EntityGoalAvoidEntity.java @@ -1,10 +1,18 @@ package com.willfp.eco.core.entities.ai.entity; +import com.willfp.eco.core.config.interfaces.Config; +import com.willfp.eco.core.entities.Entities; +import com.willfp.eco.core.entities.TestableEntity; import com.willfp.eco.core.entities.ai.EntityGoal; +import com.willfp.eco.core.serialization.KeyedDeserializer; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Mob; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.Objects; import java.util.function.Predicate; /** @@ -23,5 +31,53 @@ public record EntityGoalAvoidEntity( double fastSpeed, @NotNull Predicate filter ) implements EntityGoal { + /** + * The deserializer for the goal. + */ + public static final KeyedDeserializer DESERIALIZER = new Deserializer(); + @SuppressWarnings("unchecked") + private static final class Deserializer implements KeyedDeserializer { + @Override + @Nullable + public EntityGoalAvoidEntity deserialize(@NotNull final Config config) { + if (!( + config.has("avoidClass") + && config.has("fleeDistance") + && config.has("slowSpeed") + && config.has("fastSpeed") + && config.has("filter") + )) { + return null; + } + + try { + TestableEntity filter = Entities.lookup(config.getString("filter")); + + return new EntityGoalAvoidEntity( + (Class) + Objects.requireNonNull( + EntityType.valueOf(config.getString("avoidClass").toUpperCase()).getEntityClass() + ), + config.getDouble("fleeDistance"), + config.getDouble("slowSpeed"), + config.getDouble("fastSpeed"), + filter::matches + ); + } catch (Exception e) { + /* + Exceptions could be caused by configs having values of a wrong type, + invalid enum parameters, etc. Serializers shouldn't throw exceptions, + so we encapsulate them as null. + */ + return null; + } + } + + @NotNull + @Override + public NamespacedKey getKey() { + return NamespacedKey.minecraft("avoid_entity"); + } + } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/lookup/Testable.java b/eco-api/src/main/java/com/willfp/eco/core/lookup/Testable.java index 5b292fbd..ac6e5301 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/lookup/Testable.java +++ b/eco-api/src/main/java/com/willfp/eco/core/lookup/Testable.java @@ -2,12 +2,14 @@ package com.willfp.eco.core.lookup; import org.jetbrains.annotations.Nullable; +import java.util.function.Predicate; + /** * Interface for testing if any object matches another object. * * @param The type of object. */ -public interface Testable { +public interface Testable extends Predicate { /** * If object matches the test. * @@ -15,4 +17,9 @@ public interface Testable { * @return If matches. */ boolean matches(@Nullable T other); + + @Override + default boolean test(@Nullable T other) { + return this.matches(other); + } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/serialization/ConfigDeserializer.java b/eco-api/src/main/java/com/willfp/eco/core/serialization/ConfigDeserializer.java new file mode 100644 index 00000000..283aefe0 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/serialization/ConfigDeserializer.java @@ -0,0 +1,21 @@ +package com.willfp.eco.core.serialization; + +import com.willfp.eco.core.config.interfaces.Config; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Deserialize objects from configs. + * + * @param The type of object to deserialize. + */ +public interface ConfigDeserializer { + /** + * Deserialize a config to an object. + * + * @param config The config. + * @return The object, or null if invalid. + */ + @Nullable + T deserialize(@NotNull Config config); +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/serialization/ConfigSerializer.java b/eco-api/src/main/java/com/willfp/eco/core/serialization/ConfigSerializer.java new file mode 100644 index 00000000..c1667fb9 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/serialization/ConfigSerializer.java @@ -0,0 +1,20 @@ +package com.willfp.eco.core.serialization; + +import com.willfp.eco.core.config.interfaces.Config; +import org.jetbrains.annotations.NotNull; + +/** + * Serialize objects to configs. + * + * @param The type of object to serialize. + */ +public interface ConfigSerializer { + /** + * Serialize an object to a config. + * + * @param obj The object. + * @return The config. + */ + @NotNull + Config serialize(@NotNull T obj); +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/serialization/KeyedDeserializer.java b/eco-api/src/main/java/com/willfp/eco/core/serialization/KeyedDeserializer.java new file mode 100644 index 00000000..c6ad705d --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/serialization/KeyedDeserializer.java @@ -0,0 +1,14 @@ +package com.willfp.eco.core.serialization; + +import org.bukkit.Keyed; + +/** + * Deserialize objects from configs. + *

+ * Has a key. + * + * @param The type of object to deserialize. + */ +public interface KeyedDeserializer extends ConfigDeserializer, Keyed { + +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/serialization/KeyedSerializer.java b/eco-api/src/main/java/com/willfp/eco/core/serialization/KeyedSerializer.java new file mode 100644 index 00000000..e217f99f --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/serialization/KeyedSerializer.java @@ -0,0 +1,14 @@ +package com.willfp.eco.core.serialization; + +import org.bukkit.Keyed; + +/** + * Serialize objects to configs. + *

+ * Has a key. + * + * @param The type of object to serialize. + */ +public interface KeyedSerializer extends ConfigSerializer, Keyed { + +}