Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44924cdf83 | ||
|
|
75363181e4 | ||
|
|
1fc9d66457 | ||
|
|
2fdbe0da28 | ||
|
|
a1922cb195 | ||
|
|
725e950092 | ||
|
|
bf123d3105 | ||
|
|
dca952c10a | ||
|
|
b2e5896885 | ||
|
|
38542dad5e | ||
|
|
852a9c5fb1 | ||
|
|
12aa0e349e | ||
|
|
351f5d8c16 | ||
|
|
7e4b3075ed | ||
|
|
cf0d725189 | ||
|
|
a9f33fb846 | ||
|
|
4a9ab7a0eb | ||
|
|
3982ab99a6 | ||
|
|
1fb39e55d2 | ||
|
|
56d32b532d | ||
|
|
0d0800dfb5 | ||
|
|
f32110687f | ||
|
|
dbf39f3621 | ||
|
|
9a2f0e3df8 | ||
|
|
56fb9b40b9 | ||
|
|
fbc7bb6f07 | ||
|
|
2294c3758d | ||
|
|
c573da6e31 | ||
|
|
6362931e6b | ||
|
|
0be1f45edc | ||
|
|
9700aa7eac | ||
|
|
75eaf58aa2 | ||
|
|
63352989b1 | ||
|
|
dd5e0e3847 | ||
|
|
4f009c6d57 | ||
|
|
09d4db816e | ||
|
|
fb7799e931 | ||
|
|
13a1965f03 | ||
|
|
3abefb73f9 | ||
|
|
a35f5bb405 | ||
|
|
88a7fb53a3 | ||
|
|
866ba8440d | ||
|
|
61896bbddd | ||
|
|
7a4891d4e3 | ||
|
|
dbd5cd341e | ||
|
|
7df707a59d | ||
|
|
92dfa32d07 | ||
|
|
5cad1d31e3 | ||
|
|
e4c0418fd4 | ||
|
|
54c74d0138 | ||
|
|
6e21bdeb5b | ||
|
|
00439a1b04 | ||
|
|
87684abbbb | ||
|
|
0cbf78733e | ||
|
|
ecf0e7c356 | ||
|
|
f20d9884b5 | ||
|
|
61d713ad4d | ||
|
|
ca5cce3f40 | ||
|
|
1c8edac807 | ||
|
|
98b465f8f3 | ||
|
|
3c3e34eda3 | ||
|
|
02ad6f7810 | ||
|
|
5369ee7d42 | ||
|
|
c441e0761f | ||
|
|
a02dd06c20 | ||
|
|
957af5c5bf | ||
|
|
2c51a6900f | ||
|
|
e09e9b4e8d | ||
|
|
02497d485b | ||
|
|
bd32f3bc8d | ||
|
|
7176342e15 | ||
|
|
32ef8d8c5c | ||
|
|
92f8787eb9 | ||
|
|
5403f7a9ed | ||
|
|
2924d6f560 | ||
|
|
36c0708c17 | ||
|
|
b9fe54e883 | ||
|
|
5cc2f23547 | ||
|
|
30514ba780 | ||
|
|
02e6c5e8f3 | ||
|
|
fac97329aa | ||
|
|
cdf5cc3abe | ||
|
|
4cb630d201 | ||
|
|
79d6277d94 | ||
|
|
1a90fa6707 |
@@ -23,6 +23,7 @@ dependencies {
|
||||
implementation(project(":eco-core:core-backend"))
|
||||
implementation(project(path = ":eco-core:core-nms:v1_17_R1", configuration = "reobf"))
|
||||
implementation(project(path = ":eco-core:core-nms:v1_18_R1", configuration = "reobf"))
|
||||
implementation(project(path = ":eco-core:core-nms:v1_18_R2", configuration = "reobf"))
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -92,9 +93,9 @@ allprojects {
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
|
||||
|
||||
// Adventure
|
||||
compileOnly("net.kyori:adventure-api:4.9.3")
|
||||
compileOnly("net.kyori:adventure-text-serializer-gson:4.9.3")
|
||||
compileOnly("net.kyori:adventure-text-serializer-legacy:4.9.3")
|
||||
compileOnly("net.kyori:adventure-api:4.10.0")
|
||||
compileOnly("net.kyori:adventure-text-serializer-gson:4.10.0")
|
||||
compileOnly("net.kyori:adventure-text-serializer-legacy:4.10.0")
|
||||
|
||||
// Other
|
||||
compileOnly("com.google.guava:guava:31.0.1-jre")
|
||||
@@ -113,6 +114,7 @@ allprojects {
|
||||
exclude(group = "org.spongepowered", module = "configurate-hocon")
|
||||
exclude(group = "com.darkblade12", module = "particleeffect")
|
||||
exclude(group = "com.github.cryptomorin", module = "XSeries")
|
||||
exclude(group = "net.wesjd", module = "anvilgui")
|
||||
}
|
||||
|
||||
configurations.testImplementation {
|
||||
@@ -129,8 +131,8 @@ allprojects {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate("org.bstats", "com.willfp.eco.shaded.bstats")
|
||||
relocate("net.kyori.adventure.text.minimessage", "com.willfp.eco.shaded.minimessage")
|
||||
relocate("org.bstats", "com.willfp.eco.libs.bstats")
|
||||
relocate("redempt.crunch", "com.willfp.eco.libs.crunch")
|
||||
}
|
||||
|
||||
compileJava {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
dependencies {
|
||||
// Adventure
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.1.0'
|
||||
|
||||
// Other
|
||||
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
|
||||
@@ -33,4 +32,4 @@ publishing {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.willfp.eco.core.config.wrapper.ConfigFactory;
|
||||
import com.willfp.eco.core.data.ProfileHandler;
|
||||
import com.willfp.eco.core.data.keys.KeyRegistry;
|
||||
import com.willfp.eco.core.drops.DropQueueFactory;
|
||||
import com.willfp.eco.core.entities.ai.EntityController;
|
||||
import com.willfp.eco.core.events.EventManager;
|
||||
import com.willfp.eco.core.extensions.ExtensionLoader;
|
||||
import com.willfp.eco.core.factory.MetadataValueFactory;
|
||||
@@ -20,6 +21,7 @@ import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,7 +34,6 @@ import java.util.logging.Logger;
|
||||
* @see Eco#getHandler()
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@SuppressWarnings("removal")
|
||||
public interface Handler {
|
||||
/**
|
||||
* Create a scheduler.
|
||||
@@ -262,4 +263,23 @@ public interface Handler {
|
||||
@NotNull
|
||||
PluginProps getProps(@Nullable PluginProps existing,
|
||||
@NotNull Class<? extends EcoPlugin> plugin);
|
||||
|
||||
/**
|
||||
* Format a string with MiniMessage.
|
||||
*
|
||||
* @param message The message.
|
||||
* @return The formatted string.
|
||||
*/
|
||||
@NotNull
|
||||
String formatMiniMessage(@NotNull String message);
|
||||
|
||||
/**
|
||||
* Create controlled entity from a mob.
|
||||
*
|
||||
* @param mob The mob.
|
||||
* @param <T> The mob type.
|
||||
* @return The controlled entity.
|
||||
*/
|
||||
@NotNull
|
||||
<T extends Mob> EntityController<T> createEntityController(@NotNull T mob);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base interface for all custom goals.
|
||||
* <p>
|
||||
* Can be used both for entity goals and target goals.
|
||||
*
|
||||
* @param <T> The type of mob that this goal can be applied to.
|
||||
*/
|
||||
public abstract class CustomGoal<T extends Mob> implements EntityGoal<T>, TargetGoal<T> {
|
||||
/**
|
||||
* The flags for the goal.
|
||||
*/
|
||||
private final Set<GoalFlag> flags = EnumSet.noneOf(GoalFlag.class);
|
||||
|
||||
/**
|
||||
* Initialize the goal with a mob.
|
||||
* <p>
|
||||
* This will be run before any implementation code, treat this as the constructor.
|
||||
*
|
||||
* @param mob The mob.
|
||||
*/
|
||||
public abstract void initialize(@NotNull T mob);
|
||||
|
||||
/**
|
||||
* Get if the goal can be used.
|
||||
* Will start the goal if this returns true.
|
||||
*
|
||||
* @return If the goal can be used.
|
||||
*/
|
||||
public abstract boolean canUse();
|
||||
|
||||
/**
|
||||
* Tick the goal.
|
||||
* <p>
|
||||
* Runs ever tick as long as {@link this#canUse()} returns true.
|
||||
* <p>
|
||||
* Runs after {@link this#start()}.
|
||||
*/
|
||||
public void tick() {
|
||||
// Override when needed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the goal.
|
||||
* <p>
|
||||
* Runs once {@link this#canUse()} returns true.
|
||||
*/
|
||||
public void start() {
|
||||
// Override when needed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the goal.
|
||||
* <p>
|
||||
* Runs once {@link this#canUse()} returns false.
|
||||
*/
|
||||
public void stop() {
|
||||
// Override when needed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the goal can continue to be used.
|
||||
*
|
||||
* @return If the goal can continue to be used.
|
||||
*/
|
||||
public boolean canContinueToUse() {
|
||||
return this.canUse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the goal is interruptable.
|
||||
*
|
||||
* @return If interruptable.
|
||||
*/
|
||||
public boolean isInterruptable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the goal flags.
|
||||
*
|
||||
* @return The flags.
|
||||
*/
|
||||
public EnumSet<GoalFlag> getFlags() {
|
||||
return EnumSet.copyOf(this.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flags for the goal.
|
||||
*
|
||||
* @param flags The flags.
|
||||
*/
|
||||
public final void setFlags(@NotNull final GoalFlag... flags) {
|
||||
this.setFlags(EnumSet.copyOf(List.of(flags)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flags for the goal.
|
||||
*
|
||||
* @param flags The flags.
|
||||
*/
|
||||
public void setFlags(@NotNull final EnumSet<GoalFlag> flags) {
|
||||
this.flags.clear();
|
||||
this.flags.addAll(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T addToEntity(@NotNull final T entity,
|
||||
final int priority) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Shorthand syntax is not supported for custom goals by default as they can be both entity and target goals."
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* An entity controller allows for adding targets and goals to entities.
|
||||
*
|
||||
* @param <T> The wrapped mob.
|
||||
*/
|
||||
public interface EntityController<T extends Mob> {
|
||||
/**
|
||||
* Add a target goal to the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @param priority The priority.
|
||||
* @param goal The goal.
|
||||
* @return The entity controller.
|
||||
*/
|
||||
EntityController<T> addTargetGoal(int priority,
|
||||
@NotNull TargetGoal<? super T> goal);
|
||||
|
||||
/**
|
||||
* Remove all target goals from the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @return The entity controller.
|
||||
*/
|
||||
EntityController<T> clearTargetGoals();
|
||||
|
||||
/**
|
||||
* Remove a target goal from the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @param goal The goal.
|
||||
* @return The entity controller.
|
||||
*/
|
||||
EntityController<T> removeTargetGoal(@NotNull TargetGoal<? super T> goal);
|
||||
|
||||
/**
|
||||
* Add an entity goal to the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @param priority The priority.
|
||||
* @param goal The goal.
|
||||
* @return The entity controller.
|
||||
*/
|
||||
EntityController<T> addEntityGoal(int priority,
|
||||
@NotNull EntityGoal<? super T> goal);
|
||||
|
||||
/**
|
||||
* Remove an entity goal from the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @param goal The goal.
|
||||
* @return The entity controller.
|
||||
*/
|
||||
EntityController<T> removeEntityGoal(@NotNull EntityGoal<? super T> goal);
|
||||
|
||||
/**
|
||||
* Remove all entity goals from the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @return The entity controller.
|
||||
*/
|
||||
EntityController<T> clearEntityGoals();
|
||||
|
||||
/**
|
||||
* Remove all goals from the entity.
|
||||
* <p>
|
||||
* Mutates the instance.
|
||||
*
|
||||
* @return The entity controller.
|
||||
*/
|
||||
default EntityController<T> clearAllGoals() {
|
||||
this.clearTargetGoals();
|
||||
return this.clearEntityGoals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mob back from the controlled entity.
|
||||
* <p>
|
||||
* Not required to apply changes, as the mob instance will be altered.
|
||||
*
|
||||
* @return The mob.
|
||||
*/
|
||||
T getEntity();
|
||||
|
||||
/**
|
||||
* Create an entity controller for an entity in order to modify targets and goals.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @param <T> The mob type.
|
||||
* @return The entity controller.
|
||||
*/
|
||||
static <T extends Mob> EntityController<T> getFor(@NotNull final T entity) {
|
||||
return Eco.getHandler().createEntityController(entity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A goal for entity AI.
|
||||
*
|
||||
* @param <T> The type of mob that the goal can be applied to.
|
||||
*/
|
||||
public interface EntityGoal<T extends Mob> extends Goal<T> {
|
||||
@Override
|
||||
default T addToEntity(@NotNull T entity, int priority) {
|
||||
return EntityController.getFor(entity)
|
||||
.addEntityGoal(priority, this)
|
||||
.getEntity();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalAvoidEntity;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreakDoors;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreatheAir;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreed;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalCatLieOnBed;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalCatSitOnBed;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalEatGrass;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFleeSun;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFloat;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFollowBoats;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFollowMobs;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalIllusionerBlindnessSpell;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalIllusionerMirrorSpell;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalInteract;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLookAtPlayer;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMeleeAttack;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveBackToVillage;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveThroughVillage;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveTowardsRestriction;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveTowardsTarget;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalOcelotAttack;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalOpenDoors;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalPanic;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRandomLookAround;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRandomStroll;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRandomSwimming;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRangedAttack;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRangedBowAttack;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRangedCrossbowAttack;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRestrictSun;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalStrollThroughVillage;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalTempt;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalTryFindWater;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalUseItem;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalWaterAvoidingRandomFlying;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalWaterAvoidingRandomStroll;
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalWolfBeg;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
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<NamespacedKey, KeyedDeserializer<? extends EntityGoal<?>>> BY_KEY = HashBiMap.create();
|
||||
|
||||
static {
|
||||
register(EntityGoalAvoidEntity.DESERIALIZER);
|
||||
register(EntityGoalBreakDoors.DESERIALIZER);
|
||||
register(EntityGoalBreatheAir.DESERIALIZER);
|
||||
register(EntityGoalEatGrass.DESERIALIZER);
|
||||
register(EntityGoalFleeSun.DESERIALIZER);
|
||||
register(EntityGoalFloat.DESERIALIZER);
|
||||
register(EntityGoalFollowBoats.DESERIALIZER);
|
||||
register(EntityGoalFollowMobs.DESERIALIZER);
|
||||
register(EntityGoalInteract.DESERIALIZER);
|
||||
register(EntityGoalLeapAtTarget.DESERIALIZER);
|
||||
register(EntityGoalLookAtPlayer.DESERIALIZER);
|
||||
register(EntityGoalMeleeAttack.DESERIALIZER);
|
||||
register(EntityGoalMoveBackToVillage.DESERIALIZER);
|
||||
register(EntityGoalMoveThroughVillage.DESERIALIZER);
|
||||
register(EntityGoalMoveTowardsRestriction.DESERIALIZER);
|
||||
register(EntityGoalMoveTowardsTarget.DESERIALIZER);
|
||||
register(EntityGoalOcelotAttack.DESERIALIZER);
|
||||
register(EntityGoalOpenDoors.DESERIALIZER);
|
||||
register(EntityGoalPanic.DESERIALIZER);
|
||||
register(EntityGoalRandomLookAround.DESERIALIZER);
|
||||
register(EntityGoalRandomStroll.DESERIALIZER);
|
||||
register(EntityGoalRandomSwimming.DESERIALIZER);
|
||||
register(EntityGoalRangedAttack.DESERIALIZER);
|
||||
register(EntityGoalRangedBowAttack.DESERIALIZER);
|
||||
register(EntityGoalRangedCrossbowAttack.DESERIALIZER);
|
||||
register(EntityGoalRestrictSun.DESERIALIZER);
|
||||
register(EntityGoalStrollThroughVillage.DESERIALIZER);
|
||||
register(EntityGoalTempt.DESERIALIZER);
|
||||
register(EntityGoalTryFindWater.DESERIALIZER);
|
||||
register(EntityGoalUseItem.DESERIALIZER);
|
||||
register(EntityGoalWaterAvoidingRandomFlying.DESERIALIZER);
|
||||
register(EntityGoalWaterAvoidingRandomStroll.DESERIALIZER);
|
||||
register(EntityGoalWolfBeg.DESERIALIZER);
|
||||
register(EntityGoalBreed.DESERIALIZER);
|
||||
register(EntityGoalCatSitOnBed.DESERIALIZER);
|
||||
register(EntityGoalCatLieOnBed.DESERIALIZER);
|
||||
register(EntityGoalIllusionerBlindnessSpell.DESERIALIZER);
|
||||
register(EntityGoalIllusionerMirrorSpell.DESERIALIZER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get deserializer by key.
|
||||
*
|
||||
* @param key The key.
|
||||
* @return The deserializer, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
public static KeyedDeserializer<? extends EntityGoal<? extends Mob>> getByKey(@NotNull final NamespacedKey key) {
|
||||
return BY_KEY.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get deserializer by key, with a defined type (to prevent cluttering code with unsafe casts).
|
||||
*
|
||||
* @param key The key.
|
||||
* @param clazz The type of target goal.
|
||||
* @param <T> The type of mob the goal can be applied to.
|
||||
* @return The deserializer, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public static <T extends Mob> KeyedDeserializer<EntityGoal<T>> getByKeyOfType(@NotNull final NamespacedKey key,
|
||||
@NotNull final Class<T> clazz) {
|
||||
return (KeyedDeserializer<EntityGoal<T>>) BY_KEY.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply goal to entity given key and config.
|
||||
* <p>
|
||||
* If the key or config are invalid, the goal will not be applied.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @param key The key.
|
||||
* @param config The config.
|
||||
* @param priority The priority.
|
||||
* @param <T> The entity type.
|
||||
* @return The entity.
|
||||
*/
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Mob> T applyToEntity(@NotNull final T entity,
|
||||
@NotNull final NamespacedKey key,
|
||||
@NotNull final Config config,
|
||||
final int priority) {
|
||||
KeyedDeserializer<EntityGoal<T>> deserializer = getByKeyOfType(key, (Class<T>) entity.getClass());
|
||||
if (deserializer == null) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
EntityGoal<T> goal = deserializer.deserialize(config);
|
||||
|
||||
if (goal == null) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
return goal.addToEntity(entity, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a deserializer for an entity goal.
|
||||
*
|
||||
* @param toRegister The entity goal to register.
|
||||
* @param <T> The type of deserializer.
|
||||
* @return The deserializer.
|
||||
*/
|
||||
@NotNull
|
||||
public static <T extends KeyedDeserializer<? extends EntityGoal<?>>> 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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A generic goal for entity AI.
|
||||
*
|
||||
* @param <T> The type of mob that the goal can be applied to.
|
||||
*/
|
||||
public interface Goal<T extends Mob> {
|
||||
/**
|
||||
* Add the entity goal to an entity.
|
||||
* <p>
|
||||
* The lower the priority, the higher up the execution order; so
|
||||
* priority 0 will execute first. Lower priority (higher number) goals
|
||||
* will only execute if all higher priority goals are stopped.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @param priority The priority.
|
||||
* @return The entity, modified.
|
||||
*/
|
||||
T addToEntity(@NotNull T entity, int priority);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
/**
|
||||
* Flags for ai goals.
|
||||
*/
|
||||
public enum GoalFlag {
|
||||
/**
|
||||
* Move.
|
||||
*/
|
||||
MOVE,
|
||||
|
||||
/**
|
||||
* Look around.
|
||||
*/
|
||||
LOOK,
|
||||
|
||||
/**
|
||||
* Jump.
|
||||
*/
|
||||
JUMP,
|
||||
|
||||
/**
|
||||
* Target.
|
||||
*/
|
||||
TARGET
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A goal for entity target AI.
|
||||
*
|
||||
* @param <T> The type of mob that the goal can be applied to.
|
||||
*/
|
||||
public interface TargetGoal<T extends Mob> extends Goal<T> {
|
||||
@Override
|
||||
default T addToEntity(@NotNull T entity, int priority) {
|
||||
return EntityController.getFor(entity)
|
||||
.addTargetGoal(priority, this)
|
||||
.getEntity();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.willfp.eco.core.entities.ai;
|
||||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalDefendVillage;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalHurtBy;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNearestAttackable;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNearestAttackableWitch;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNearestHealableRaider;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNonTameRandom;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalOwnerHurtBy;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalOwnerTarget;
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalResetUniversalAnger;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Class to manage target goals.
|
||||
*/
|
||||
public final class TargetGoals {
|
||||
/**
|
||||
* All registered deserializers.
|
||||
*/
|
||||
private static final Map<NamespacedKey, KeyedDeserializer<? extends TargetGoal<?>>> BY_KEY = HashBiMap.create();
|
||||
|
||||
static {
|
||||
register(TargetGoalDefendVillage.DESERIALIZER);
|
||||
register(TargetGoalHurtBy.DESERIALIZER);
|
||||
register(TargetGoalNearestAttackable.DESERIALIZER);
|
||||
register(TargetGoalNearestAttackableWitch.DESERIALIZER);
|
||||
register(TargetGoalNearestHealableRaider.DESERIALIZER);
|
||||
register(TargetGoalNonTameRandom.DESERIALIZER);
|
||||
register(TargetGoalOwnerTarget.DESERIALIZER);
|
||||
register(TargetGoalOwnerHurtBy.DESERIALIZER);
|
||||
register(TargetGoalResetUniversalAnger.DESERIALIZER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get deserializer by key.
|
||||
*
|
||||
* @param key The key.
|
||||
* @return The deserializer, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
public static KeyedDeserializer<? extends TargetGoal<? extends Mob>> getByKey(@NotNull final NamespacedKey key) {
|
||||
return BY_KEY.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get deserializer by key, with a defined type (to prevent cluttering code with unsafe casts).
|
||||
*
|
||||
* @param key The key.
|
||||
* @param clazz The type of target goal.
|
||||
* @param <T> The type of mob the goal can be applied to.
|
||||
* @return The deserializer, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public static <T extends Mob> KeyedDeserializer<TargetGoal<T>> getByKeyOfType(@NotNull final NamespacedKey key,
|
||||
@NotNull final Class<T> clazz) {
|
||||
return (KeyedDeserializer<TargetGoal<T>>) BY_KEY.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply goal to entity given key and config.
|
||||
* <p>
|
||||
* If the key or config are invalid, the goal will not be applied.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @param key The key.
|
||||
* @param config The config.
|
||||
* @param priority The priority.
|
||||
* @param <T> The entity type.
|
||||
* @return The entity.
|
||||
*/
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Mob> T applyToEntity(@NotNull final T entity,
|
||||
@NotNull final NamespacedKey key,
|
||||
@NotNull final Config config,
|
||||
final int priority) {
|
||||
KeyedDeserializer<TargetGoal<T>> deserializer = getByKeyOfType(key, (Class<T>) entity.getClass());
|
||||
if (deserializer == null) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
TargetGoal<T> goal = deserializer.deserialize(config);
|
||||
|
||||
if (goal == null) {
|
||||
return entity;
|
||||
}
|
||||
|
||||
return goal.addToEntity(entity, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a deserializer for a target goal.
|
||||
*
|
||||
* @param toRegister The target goal to register.
|
||||
* @param <T> The type of deserializer.
|
||||
* @return The deserializer.
|
||||
*/
|
||||
@NotNull
|
||||
public static <T extends KeyedDeserializer<? extends TargetGoal<?>>> T register(@NotNull final T toRegister) {
|
||||
BY_KEY.put(toRegister.getKey(), toRegister);
|
||||
return toRegister;
|
||||
}
|
||||
|
||||
private TargetGoals() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
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.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Avoid entities.
|
||||
*
|
||||
* @param entity The entity type to avoid.
|
||||
* @param distance The distance to flee to.
|
||||
* @param slowSpeed The slow movement speed.
|
||||
* @param fastSpeed The fast movement speed.
|
||||
*/
|
||||
public record EntityGoalAvoidEntity(
|
||||
@NotNull TestableEntity entity,
|
||||
double distance,
|
||||
double slowSpeed,
|
||||
double fastSpeed
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalAvoidEntity> DESERIALIZER = new Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalAvoidEntity> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalAvoidEntity deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("entity")
|
||||
&& config.has("distance")
|
||||
&& config.has("slowSpeed")
|
||||
&& config.has("fastSpeed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
TestableEntity entity = Entities.lookup(config.getString("entity"));
|
||||
|
||||
return new EntityGoalAvoidEntity(
|
||||
entity,
|
||||
config.getDouble("distance"),
|
||||
config.getDouble("slowSpeed"),
|
||||
config.getDouble("fastSpeed")
|
||||
);
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to break down doors.
|
||||
*
|
||||
* @param ticks The time taken to break the door. Minimum value is 240, as set by the game.
|
||||
*/
|
||||
public record EntityGoalBreakDoors(
|
||||
int ticks
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalBreakDoors> DESERIALIZER = new EntityGoalBreakDoors.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalBreakDoors> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalBreakDoors deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("ticks")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalBreakDoors(
|
||||
config.getInt("ticks")
|
||||
);
|
||||
} 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("break_doors");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Breathe air.
|
||||
*/
|
||||
public record EntityGoalBreatheAir(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalBreatheAir> DESERIALIZER = new EntityGoalBreatheAir.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalBreatheAir> {
|
||||
@Override
|
||||
public EntityGoalBreatheAir deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalBreatheAir();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("breathe_air");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows animals to breed.
|
||||
*
|
||||
* @param speed The speed at which to move to a partner.
|
||||
*/
|
||||
public record EntityGoalBreed(
|
||||
double speed
|
||||
) implements EntityGoal<Animals> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalBreed> DESERIALIZER = new EntityGoalBreed.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalBreed> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalBreed deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalBreed(
|
||||
config.getDouble("speed")
|
||||
);
|
||||
} 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("breed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Cat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows a cat to lie on a bed.
|
||||
*
|
||||
* @param speed The speed at which to move to the bed.
|
||||
* @param range The range at which to search for beds.
|
||||
*/
|
||||
public record EntityGoalCatLieOnBed(
|
||||
double speed,
|
||||
int range
|
||||
) implements EntityGoal<Cat> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalCatLieOnBed> DESERIALIZER = new EntityGoalCatLieOnBed.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalCatLieOnBed> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalCatLieOnBed deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("range")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalCatLieOnBed(
|
||||
config.getDouble("speed"),
|
||||
config.getInt("range")
|
||||
);
|
||||
} 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("cat_lie_on_bed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Cat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows a cat to sit on a bed.
|
||||
*
|
||||
* @param speed The speed at which to move to the bed.
|
||||
*/
|
||||
public record EntityGoalCatSitOnBed(
|
||||
double speed
|
||||
) implements EntityGoal<Cat> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalCatSitOnBed> DESERIALIZER = new EntityGoalCatSitOnBed.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalCatSitOnBed> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalCatSitOnBed deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalCatSitOnBed(
|
||||
config.getDouble("speed")
|
||||
);
|
||||
} 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("cat_sit_on_bed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to eat the ground.
|
||||
*/
|
||||
public record EntityGoalEatGrass(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalEatGrass> DESERIALIZER = new EntityGoalEatGrass.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalEatGrass> {
|
||||
@Override
|
||||
public EntityGoalEatGrass deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalEatGrass();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("eat_grass");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Will make the entity actively avoid the sunlight.
|
||||
*
|
||||
* @param speed The speed at which to flee.
|
||||
*/
|
||||
public record EntityGoalFleeSun(
|
||||
double speed
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalFleeSun> DESERIALIZER = new EntityGoalFleeSun.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalFleeSun> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalFleeSun deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalFleeSun(
|
||||
config.getDouble("speed")
|
||||
);
|
||||
} 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("flee_sun");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to float on water.
|
||||
*/
|
||||
public record EntityGoalFloat(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalFloat> DESERIALIZER = new EntityGoalFloat.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalFloat> {
|
||||
@Override
|
||||
public EntityGoalFloat deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalFloat();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("float");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Follow boats.
|
||||
*/
|
||||
public record EntityGoalFollowBoats(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalFollowBoats> DESERIALIZER = new EntityGoalFollowBoats.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalFollowBoats> {
|
||||
@Override
|
||||
public EntityGoalFollowBoats deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalFollowBoats();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("follow_boats");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to follow and gather around all types of mobs, both hostile and neutral mobs.
|
||||
*
|
||||
* @param speed The speed at which to follow.
|
||||
* @param minDistance The minimum follow distance.
|
||||
* @param maxDistance The maximum follow distance.
|
||||
*/
|
||||
public record EntityGoalFollowMobs(
|
||||
double speed,
|
||||
double minDistance,
|
||||
double maxDistance
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalFollowMobs> DESERIALIZER = new EntityGoalFollowMobs.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalFollowMobs> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalFollowMobs deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("minDistance")
|
||||
&& config.has("maxDistance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalFollowMobs(
|
||||
config.getDouble("speed"),
|
||||
config.getDouble("minDistance"),
|
||||
config.getDouble("maxDistance")
|
||||
);
|
||||
} 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("follow_mobs");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Illusioner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an illusioner to perform the blindness spell.
|
||||
*/
|
||||
public record EntityGoalIllusionerBlindnessSpell(
|
||||
) implements EntityGoal<Illusioner> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalIllusionerBlindnessSpell> DESERIALIZER = new EntityGoalIllusionerBlindnessSpell.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalIllusionerBlindnessSpell> {
|
||||
@Override
|
||||
public EntityGoalIllusionerBlindnessSpell deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalIllusionerBlindnessSpell();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("illusioner_blindness_spell");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Illusioner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an illusioner to perform the mirror spell.
|
||||
*/
|
||||
public record EntityGoalIllusionerMirrorSpell(
|
||||
) implements EntityGoal<Illusioner> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalIllusionerMirrorSpell> DESERIALIZER = new EntityGoalIllusionerMirrorSpell.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalIllusionerMirrorSpell> {
|
||||
@Override
|
||||
public EntityGoalIllusionerMirrorSpell deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalIllusionerMirrorSpell();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("illusioner_mirror_spell");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
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.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Interact with other mobs.
|
||||
*
|
||||
* @param target The type of entity to interact with.
|
||||
* @param range The range at which to interact.
|
||||
* @param chance The chance for interaction, between 0 and 1.
|
||||
*/
|
||||
public record EntityGoalInteract(
|
||||
@NotNull TestableEntity target,
|
||||
double range,
|
||||
double chance
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalInteract> DESERIALIZER = new EntityGoalInteract.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalInteract> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalInteract deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("target")
|
||||
&& config.has("range")
|
||||
&& config.has("chance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalInteract(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getDouble("range"),
|
||||
config.getDouble("chance")
|
||||
);
|
||||
} 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("interact");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to jump towards a target.
|
||||
*
|
||||
* @param velocity The leap velocity.
|
||||
*/
|
||||
public record EntityGoalLeapAtTarget(
|
||||
double velocity
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalLeapAtTarget> DESERIALIZER = new EntityGoalLeapAtTarget.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalLeapAtTarget> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalLeapAtTarget deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("velocity")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalLeapAtTarget(
|
||||
config.getDouble("velocity")
|
||||
);
|
||||
} 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("leap_at_target");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to look at the player by rotating the head bone pose within a set limit.
|
||||
*
|
||||
* @param range The range at which to look at the player.
|
||||
* @param chance The chance to look at the player, between 0 and 1.
|
||||
*/
|
||||
public record EntityGoalLookAtPlayer(
|
||||
double range,
|
||||
double chance
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalLookAtPlayer> DESERIALIZER = new EntityGoalLookAtPlayer.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalLookAtPlayer> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalLookAtPlayer deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("range")
|
||||
&& config.has("chance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalLookAtPlayer(
|
||||
config.getDouble("range"),
|
||||
config.getDouble("chance")
|
||||
);
|
||||
} 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("look_at_player");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows entities to make close combat melee attacks.
|
||||
*
|
||||
* @param speed The speed at which to attack the target.
|
||||
* @param pauseWhenMobIdle If the entity should pause attacking when the target is idle.
|
||||
*/
|
||||
public record EntityGoalMeleeAttack(
|
||||
double speed,
|
||||
boolean pauseWhenMobIdle
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalMeleeAttack> DESERIALIZER = new EntityGoalMeleeAttack.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalMeleeAttack> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalMeleeAttack deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("pauseWhenMobIdle")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalMeleeAttack(
|
||||
config.getDouble("speed"),
|
||||
config.getBool("pauseWhenMobIdle")
|
||||
);
|
||||
} 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("melee_attack");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to navigate and search for a nearby village.
|
||||
*
|
||||
* @param speed The speed at which to move back to the village.
|
||||
* @param canDespawn If the entity can despawn.
|
||||
*/
|
||||
public record EntityGoalMoveBackToVillage(
|
||||
double speed,
|
||||
boolean canDespawn
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalMoveBackToVillage> DESERIALIZER = new EntityGoalMoveBackToVillage.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalMoveBackToVillage> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalMoveBackToVillage deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("canDespawn")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalMoveBackToVillage(
|
||||
config.getDouble("speed"),
|
||||
config.getBool("canDespawn")
|
||||
);
|
||||
} 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("move_back_to_village");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows the entity to create paths around the village.
|
||||
*
|
||||
* @param speed The speed at which to move through the village.
|
||||
* @param onlyAtNight If the entity can only move through village at night.
|
||||
* @param distance The distance to move through the village.
|
||||
* @param canPassThroughDoors If the entity can pass through doors.
|
||||
*/
|
||||
public record EntityGoalMoveThroughVillage(
|
||||
double speed,
|
||||
boolean onlyAtNight,
|
||||
int distance,
|
||||
boolean canPassThroughDoors
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalMoveThroughVillage> DESERIALIZER = new EntityGoalMoveThroughVillage.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalMoveThroughVillage> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalMoveThroughVillage deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("onlyAtNight")
|
||||
&& config.has("distance")
|
||||
&& config.has("canPassThroughDoors")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalMoveThroughVillage(
|
||||
config.getDouble("speed"),
|
||||
config.getBool("onlyAtNight"),
|
||||
config.getInt("distance"),
|
||||
config.getBool("canPassThroughDoors")
|
||||
);
|
||||
} 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("move_through_village");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Move towards restriction.
|
||||
*
|
||||
* @param speed The speed at which to move towards the restriction.
|
||||
*/
|
||||
public record EntityGoalMoveTowardsRestriction(
|
||||
double speed
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalMoveTowardsRestriction> DESERIALIZER = new EntityGoalMoveTowardsRestriction.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalMoveTowardsRestriction> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalMoveTowardsRestriction deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalMoveTowardsRestriction(
|
||||
config.getDouble("speed")
|
||||
);
|
||||
} 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("move_towards_restriction");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to move towards a target.
|
||||
*
|
||||
* @param speed The speed at which to move towards the target.
|
||||
* @param maxDistance The maximum distance the target can be where the entity will still move towards it.
|
||||
*/
|
||||
public record EntityGoalMoveTowardsTarget(
|
||||
double speed,
|
||||
double maxDistance
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalMoveTowardsTarget> DESERIALIZER = new EntityGoalMoveTowardsTarget.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalMoveTowardsTarget> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalMoveTowardsTarget deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("maxDistance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalMoveTowardsTarget(
|
||||
config.getDouble("speed"),
|
||||
config.getDouble("maxDistance")
|
||||
);
|
||||
} 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("move_towards_target");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Attack like an ocelot.
|
||||
*/
|
||||
public record EntityGoalOcelotAttack(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalOcelotAttack> DESERIALIZER = new EntityGoalOcelotAttack.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalOcelotAttack> {
|
||||
@Override
|
||||
public EntityGoalOcelotAttack deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalOcelotAttack();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("ocelot_attack");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to interact and open a door.
|
||||
*
|
||||
* @param delayClosing If closing the door should be delayed.
|
||||
*/
|
||||
public record EntityGoalOpenDoors(
|
||||
boolean delayClosing
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalOpenDoors> DESERIALIZER = new EntityGoalOpenDoors.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalOpenDoors> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalOpenDoors deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("delayClosing")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalOpenDoors(
|
||||
config.getBool("delayClosing")
|
||||
);
|
||||
} 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("open_doors");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to react when it receives damage.
|
||||
*
|
||||
* @param speed The speed at which to panic.
|
||||
*/
|
||||
public record EntityGoalPanic(
|
||||
double speed
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalPanic> DESERIALIZER = new EntityGoalPanic.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalPanic> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalPanic deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalPanic(
|
||||
config.getDouble("speed")
|
||||
);
|
||||
} 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("panic");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to choose a random direction to look in for a random duration within a range.
|
||||
*/
|
||||
public record EntityGoalRandomLookAround(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRandomLookAround> DESERIALIZER = new EntityGoalRandomLookAround.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRandomLookAround> {
|
||||
@Override
|
||||
public EntityGoalRandomLookAround deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalRandomLookAround();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("random_look_around");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to choose a random direction to walk towards.
|
||||
*
|
||||
* @param speed The speed at which to move around.
|
||||
* @param interval The amount of ticks to wait (on average) between strolling around.
|
||||
* @param canDespawn If the entity can despawn.
|
||||
*/
|
||||
public record EntityGoalRandomStroll(
|
||||
double speed,
|
||||
int interval,
|
||||
boolean canDespawn
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRandomStroll> DESERIALIZER = new EntityGoalRandomStroll.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRandomStroll> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalRandomStroll deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("interval")
|
||||
&& config.has("canDespawn")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalRandomStroll(
|
||||
config.getDouble("speed"),
|
||||
config.getInt("interval"),
|
||||
config.getBool("canDespawn")
|
||||
);
|
||||
} 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("random_stroll");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to swim in a random point in water.
|
||||
*
|
||||
* @param speed The speed at which to move around.
|
||||
* @param interval The amount of ticks to wait (on average) between strolling around.
|
||||
*/
|
||||
public record EntityGoalRandomSwimming(
|
||||
double speed,
|
||||
int interval
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRandomSwimming> DESERIALIZER = new EntityGoalRandomSwimming.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRandomSwimming> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalRandomSwimming deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("interval")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalRandomSwimming(
|
||||
config.getDouble("speed"),
|
||||
config.getInt("interval")
|
||||
);
|
||||
} 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("random_swimming");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Ranged attack.
|
||||
* <p>
|
||||
* Only supports mobs that have ranged attacks.
|
||||
*
|
||||
* @param speed The speed.
|
||||
* @param minInterval The minimum interval between attacks (in ticks).
|
||||
* @param maxInterval The maximum interval between attacks (in ticks).
|
||||
* @param maxRange The max range at which to attack.
|
||||
*/
|
||||
public record EntityGoalRangedAttack(
|
||||
double speed,
|
||||
int minInterval,
|
||||
int maxInterval,
|
||||
double maxRange
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRangedAttack> DESERIALIZER = new EntityGoalRangedAttack.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRangedAttack> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalRangedAttack deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("minInterval")
|
||||
&& config.has("maxInterval")
|
||||
&& config.has("range")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalRangedAttack(
|
||||
config.getDouble("speed"),
|
||||
config.getInt("minInterval"),
|
||||
config.getInt("maxInterval"),
|
||||
config.getDouble("range")
|
||||
);
|
||||
} 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("ranged_attack");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Ranged attack.
|
||||
* <p>
|
||||
* Only supports monsters that have bow attacks.
|
||||
*
|
||||
* @param speed The speed.
|
||||
* @param interval The interval between attacks (in ticks).
|
||||
* @param range The max range at which to attack.
|
||||
*/
|
||||
public record EntityGoalRangedBowAttack(
|
||||
double speed,
|
||||
int interval,
|
||||
double range
|
||||
) implements EntityGoal<Monster> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRangedBowAttack> DESERIALIZER = new EntityGoalRangedBowAttack.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRangedBowAttack> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalRangedBowAttack deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("interval")
|
||||
&& config.has("range")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalRangedBowAttack(
|
||||
config.getDouble("speed"),
|
||||
config.getInt("interval"),
|
||||
config.getDouble("range")
|
||||
);
|
||||
} 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("ranged_bow_attack");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Ranged attack.
|
||||
* <p>
|
||||
* Only supports monsters that have crossbow attacks.
|
||||
*
|
||||
* @param speed The speed.
|
||||
* @param range The max range at which to attack.
|
||||
*/
|
||||
public record EntityGoalRangedCrossbowAttack(
|
||||
double speed,
|
||||
double range
|
||||
) implements EntityGoal<Monster> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRangedCrossbowAttack> DESERIALIZER = new EntityGoalRangedCrossbowAttack.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRangedCrossbowAttack> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalRangedCrossbowAttack deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("range")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalRangedCrossbowAttack(
|
||||
config.getDouble("speed"),
|
||||
config.getDouble("range")
|
||||
);
|
||||
} 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("ranged_crossbow_attack");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to actively avoid direct sunlight.
|
||||
*/
|
||||
public record EntityGoalRestrictSun(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalRestrictSun> DESERIALIZER = new EntityGoalRestrictSun.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalRestrictSun> {
|
||||
@Override
|
||||
public EntityGoalRestrictSun deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalRestrictSun();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("restrict_sun");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows the entity to create paths around the village.
|
||||
*
|
||||
* @param searchRange The search range.
|
||||
*/
|
||||
public record EntityGoalStrollThroughVillage(
|
||||
int searchRange
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalStrollThroughVillage> DESERIALIZER = new EntityGoalStrollThroughVillage.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalStrollThroughVillage> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalStrollThroughVillage deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("searchRange")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalStrollThroughVillage(
|
||||
config.getInt("searchRange")
|
||||
);
|
||||
} 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("stroll_through_village");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.items.Items;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Allows an entity to be tempted by a set item.
|
||||
*
|
||||
* @param speed The speed at which the entity follows the item.
|
||||
* @param items The items that the entity will be attracted by.
|
||||
* @param canBeScared If the entity can be scared and lose track of the item.
|
||||
*/
|
||||
public record EntityGoalTempt(
|
||||
double speed,
|
||||
@NotNull Collection<TestableItem> items,
|
||||
boolean canBeScared
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* @param speed The speed at which the entity follows the item.
|
||||
* @param item The item that the entity will be attracted by.
|
||||
* @param canBeScared If the entity can be scared and lose track of the item.
|
||||
*/
|
||||
public EntityGoalTempt(final double speed,
|
||||
@NotNull final TestableItem item,
|
||||
final boolean canBeScared) {
|
||||
this(speed, List.of(item), canBeScared);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalTempt> DESERIALIZER = new EntityGoalTempt.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalTempt> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalTempt deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("items")
|
||||
&& config.has("canBeScared")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Collection<TestableItem> items = config.getStrings("items").stream()
|
||||
.map(Items::lookup)
|
||||
.filter(it -> !(it instanceof EmptyTestableItem))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new EntityGoalTempt(
|
||||
config.getDouble("speed"),
|
||||
items,
|
||||
config.getBool("canBeScared")
|
||||
);
|
||||
} 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("tempt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to move to water when on land.
|
||||
*/
|
||||
public record EntityGoalTryFindWater(
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalTryFindWater> DESERIALIZER = new EntityGoalTryFindWater.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalTryFindWater> {
|
||||
@Override
|
||||
public EntityGoalTryFindWater deserialize(@NotNull final Config config) {
|
||||
return new EntityGoalTryFindWater();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("try_find_water");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
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.items.Items;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Use item.
|
||||
*
|
||||
* @param item The item.
|
||||
* @param sound The sound to play on use.
|
||||
* @param condition The condition when to use the item.
|
||||
*/
|
||||
public record EntityGoalUseItem(
|
||||
@NotNull ItemStack item,
|
||||
@NotNull Sound sound,
|
||||
@NotNull Predicate<LivingEntity> condition
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalUseItem> DESERIALIZER = new EntityGoalUseItem.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalUseItem> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalUseItem deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("item")
|
||||
&& config.has("sound")
|
||||
&& config.has("condition")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
TestableEntity filter = Entities.lookup(config.getString("condition"));
|
||||
|
||||
return new EntityGoalUseItem(
|
||||
Items.lookup(config.getString("item")).getItem(),
|
||||
Sound.valueOf(config.getString("sound").toUpperCase()),
|
||||
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("use_item");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Fly randomly while avoiding water.
|
||||
*
|
||||
* @param speed The speed.
|
||||
*/
|
||||
public record EntityGoalWaterAvoidingRandomFlying(
|
||||
double speed
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalWaterAvoidingRandomFlying> DESERIALIZER = new EntityGoalWaterAvoidingRandomFlying.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalWaterAvoidingRandomFlying> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalWaterAvoidingRandomFlying deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalWaterAvoidingRandomFlying(
|
||||
config.getDouble("speed")
|
||||
);
|
||||
} 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("water_avoiding_random_flying");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Stroll randomly while avoiding water.
|
||||
*
|
||||
* @param speed The speed.
|
||||
* @param chance The chance to stroll every tick, between 0 and 1.
|
||||
*/
|
||||
public record EntityGoalWaterAvoidingRandomStroll(
|
||||
double speed,
|
||||
double chance
|
||||
) implements EntityGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalWaterAvoidingRandomStroll> DESERIALIZER = new EntityGoalWaterAvoidingRandomStroll.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalWaterAvoidingRandomStroll> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalWaterAvoidingRandomStroll deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("speed")
|
||||
&& config.has("chance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalWaterAvoidingRandomStroll(
|
||||
config.getDouble("speed"),
|
||||
config.getDouble("chance")
|
||||
);
|
||||
} 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("water_avoiding_random_stroll");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.entities.ai.entity;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Wolf;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows a wolf to beg.
|
||||
*
|
||||
* @param distance The distance at which to beg from.
|
||||
*/
|
||||
public record EntityGoalWolfBeg(
|
||||
double distance
|
||||
) implements EntityGoal<Wolf> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<EntityGoalWolfBeg> DESERIALIZER = new EntityGoalWolfBeg.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<EntityGoalWolfBeg> {
|
||||
@Override
|
||||
@Nullable
|
||||
public EntityGoalWolfBeg deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("distance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new EntityGoalWolfBeg(
|
||||
config.getDouble("distance")
|
||||
);
|
||||
} 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("wolf_beg");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.IronGolem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Defend village.
|
||||
*/
|
||||
public record TargetGoalDefendVillage(
|
||||
) implements TargetGoal<IronGolem> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalDefendVillage> DESERIALIZER = new TargetGoalDefendVillage.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalDefendVillage> {
|
||||
@Override
|
||||
public TargetGoalDefendVillage deserialize(@NotNull final Config config) {
|
||||
return new TargetGoalDefendVillage();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("defend_village");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
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.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Allows an entity to react when hit by set target.
|
||||
*
|
||||
* @param blacklist The entities not to attack when hurt by.
|
||||
*/
|
||||
@SuppressWarnings({"varargs"})
|
||||
public record TargetGoalHurtBy(
|
||||
@NotNull TestableEntity blacklist
|
||||
) implements TargetGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalHurtBy> DESERIALIZER = new TargetGoalHurtBy.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalHurtBy> {
|
||||
@Override
|
||||
@Nullable
|
||||
public TargetGoalHurtBy deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("blacklist")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new TargetGoalHurtBy(
|
||||
Entities.lookup(config.getString("blacklist"))
|
||||
);
|
||||
} 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("hurt_by");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
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.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Raider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Allows an entity to attack the closest target within a given subset of specific target types.
|
||||
*
|
||||
* @param target The type of entities to attack.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
* @param checkCanNavigate If navigation should be checked.
|
||||
* @param reciprocalChance 1 in reciprocalChance chance of not activating on any tick.
|
||||
* @param targetFilter The filter for targets to match.
|
||||
*/
|
||||
public record TargetGoalNearestAttackable(
|
||||
@NotNull TestableEntity target,
|
||||
boolean checkVisibility,
|
||||
boolean checkCanNavigate,
|
||||
int reciprocalChance,
|
||||
@NotNull Predicate<LivingEntity> targetFilter
|
||||
) implements TargetGoal<Raider> {
|
||||
/**
|
||||
* @param target The type of entities to attack.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
* @param checkCanNavigate If navigation should be checked.
|
||||
* @param reciprocalChance 1 in reciprocalChance chance of not activating on any tick.
|
||||
*/
|
||||
public TargetGoalNearestAttackable(@NotNull final TestableEntity target,
|
||||
final boolean checkVisibility,
|
||||
final boolean checkCanNavigate,
|
||||
final int reciprocalChance) {
|
||||
this(target, checkVisibility, checkCanNavigate, reciprocalChance, it -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalNearestAttackable> DESERIALIZER = new TargetGoalNearestAttackable.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalNearestAttackable> {
|
||||
@Override
|
||||
@Nullable
|
||||
public TargetGoalNearestAttackable deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("target")
|
||||
&& config.has("checkVisibility")
|
||||
&& config.has("checkCanNavigate")
|
||||
&& config.has("reciprocalChance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (config.has("targetFilter")) {
|
||||
TestableEntity filter = Entities.lookup(config.getString("targetFilter"));
|
||||
|
||||
return new TargetGoalNearestAttackable(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility"),
|
||||
config.getBool("checkCanNavigate"),
|
||||
config.getInt("reciprocalChance"),
|
||||
filter::matches
|
||||
);
|
||||
} else {
|
||||
return new TargetGoalNearestAttackable(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility"),
|
||||
config.getBool("checkCanNavigate"),
|
||||
config.getInt("reciprocalChance")
|
||||
);
|
||||
}
|
||||
} 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("nearest_attackable");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
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.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Raider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Allows an entity to attack the closest target within a given subset of specific target types.
|
||||
*
|
||||
* @param target The type of entities to attack.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
* @param checkCanNavigate If navigation should be checked.
|
||||
* @param reciprocalChance 1 in reciprocalChance chance of not activating on any tick.
|
||||
* @param targetFilter The filter for targets to match.
|
||||
*/
|
||||
public record TargetGoalNearestAttackableWitch(
|
||||
@NotNull TestableEntity target,
|
||||
boolean checkVisibility,
|
||||
boolean checkCanNavigate,
|
||||
int reciprocalChance,
|
||||
@NotNull Predicate<LivingEntity> targetFilter
|
||||
) implements TargetGoal<Raider> {
|
||||
/**
|
||||
* @param target The type of entities to attack.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
* @param checkCanNavigate If navigation should be checked.
|
||||
* @param reciprocalChance 1 in reciprocalChance chance of not activating on any tick.
|
||||
*/
|
||||
public TargetGoalNearestAttackableWitch(@NotNull final TestableEntity target,
|
||||
final boolean checkVisibility,
|
||||
final boolean checkCanNavigate,
|
||||
final int reciprocalChance) {
|
||||
this(target, checkVisibility, checkCanNavigate, reciprocalChance, it -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalNearestAttackableWitch> DESERIALIZER = new TargetGoalNearestAttackableWitch.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalNearestAttackableWitch> {
|
||||
@Override
|
||||
@Nullable
|
||||
public TargetGoalNearestAttackableWitch deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("target")
|
||||
&& config.has("checkVisibility")
|
||||
&& config.has("checkCanNavigate")
|
||||
&& config.has("reciprocalChance")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (config.has("targetFilter")) {
|
||||
TestableEntity filter = Entities.lookup(config.getString("targetFilter"));
|
||||
|
||||
return new TargetGoalNearestAttackableWitch(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility"),
|
||||
config.getBool("checkCanNavigate"),
|
||||
config.getInt("reciprocalChance"),
|
||||
filter::matches
|
||||
);
|
||||
} else {
|
||||
return new TargetGoalNearestAttackableWitch(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility"),
|
||||
config.getBool("checkCanNavigate"),
|
||||
config.getInt("reciprocalChance")
|
||||
);
|
||||
}
|
||||
} 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("nearest_attackable_witch");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
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.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Raider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Target nearest attackable raider.
|
||||
*
|
||||
* @param target The types of entities to heal.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
* @param targetFilter The filter for targets to match.
|
||||
*/
|
||||
public record TargetGoalNearestHealableRaider(
|
||||
@NotNull TestableEntity target,
|
||||
boolean checkVisibility,
|
||||
@NotNull Predicate<LivingEntity> targetFilter
|
||||
) implements TargetGoal<Raider> {
|
||||
/**
|
||||
* @param target The target.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
*/
|
||||
public TargetGoalNearestHealableRaider(@NotNull final TestableEntity target,
|
||||
final boolean checkVisibility) {
|
||||
this(target, checkVisibility, it -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalNearestHealableRaider> DESERIALIZER = new TargetGoalNearestHealableRaider.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalNearestHealableRaider> {
|
||||
@Override
|
||||
@Nullable
|
||||
public TargetGoalNearestHealableRaider deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("target")
|
||||
&& config.has("checkVisibility")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (config.has("targetFilter")) {
|
||||
TestableEntity filter = Entities.lookup(config.getString("targetFilter"));
|
||||
|
||||
return new TargetGoalNearestHealableRaider(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility"),
|
||||
filter::matches
|
||||
);
|
||||
} else {
|
||||
return new TargetGoalNearestHealableRaider(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility")
|
||||
);
|
||||
}
|
||||
} 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("nearest_healable_raider");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
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.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Target random non-tame entity.
|
||||
*
|
||||
* @param target The types of entities to heal.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
* @param targetFilter The filter for targets to match.
|
||||
*/
|
||||
public record TargetGoalNonTameRandom(
|
||||
@NotNull TestableEntity target,
|
||||
boolean checkVisibility,
|
||||
@NotNull Predicate<LivingEntity> targetFilter
|
||||
) implements TargetGoal<Tameable> {
|
||||
/**
|
||||
* @param target The types of entities to heal.
|
||||
* @param checkVisibility If visibility should be checked.
|
||||
*/
|
||||
public TargetGoalNonTameRandom(@NotNull final TestableEntity target,
|
||||
final boolean checkVisibility) {
|
||||
this(target, checkVisibility, it -> true);
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalNonTameRandom> DESERIALIZER = new TargetGoalNonTameRandom.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalNonTameRandom> {
|
||||
@Override
|
||||
@Nullable
|
||||
public TargetGoalNonTameRandom deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("targetClass")
|
||||
&& config.has("checkVisibility")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (config.has("targetFilter")) {
|
||||
TestableEntity filter = Entities.lookup(config.getString("targetFilter"));
|
||||
|
||||
return new TargetGoalNonTameRandom(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility"),
|
||||
filter::matches
|
||||
);
|
||||
} else {
|
||||
return new TargetGoalNonTameRandom(
|
||||
Entities.lookup(config.getString("target")),
|
||||
config.getBool("checkVisibility")
|
||||
);
|
||||
}
|
||||
} 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("non_tame_random");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to react when the owner is hit by a target.
|
||||
*/
|
||||
public record TargetGoalOwnerHurtBy(
|
||||
) implements TargetGoal<Tameable> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalOwnerHurtBy> DESERIALIZER = new TargetGoalOwnerHurtBy.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalOwnerHurtBy> {
|
||||
@Override
|
||||
public TargetGoalOwnerHurtBy deserialize(@NotNull final Config config) {
|
||||
return new TargetGoalOwnerHurtBy();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("owner_hurt_by");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Allows an entity to react when the owner hits a target.
|
||||
*/
|
||||
public record TargetGoalOwnerTarget(
|
||||
) implements TargetGoal<Tameable> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalOwnerTarget> DESERIALIZER = new TargetGoalOwnerTarget.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalOwnerTarget> {
|
||||
@Override
|
||||
public TargetGoalOwnerTarget deserialize(@NotNull final Config config) {
|
||||
return new TargetGoalOwnerTarget();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return NamespacedKey.minecraft("owner_target");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.willfp.eco.core.entities.ai.target;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal;
|
||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Reset universal anger.
|
||||
* <p>
|
||||
* Can only be applied to neutral mobs.
|
||||
*
|
||||
* @param triggerOthers If this should cause other nearby entities to trigger.
|
||||
*/
|
||||
public record TargetGoalResetUniversalAnger(
|
||||
boolean triggerOthers
|
||||
) implements TargetGoal<Mob> {
|
||||
/**
|
||||
* The deserializer for the goal.
|
||||
*/
|
||||
public static final KeyedDeserializer<TargetGoalResetUniversalAnger> DESERIALIZER = new TargetGoalResetUniversalAnger.Deserializer();
|
||||
|
||||
/**
|
||||
* Deserialize configs into the goal.
|
||||
*/
|
||||
private static final class Deserializer implements KeyedDeserializer<TargetGoalResetUniversalAnger> {
|
||||
@Override
|
||||
@Nullable
|
||||
public TargetGoalResetUniversalAnger deserialize(@NotNull final Config config) {
|
||||
if (!(
|
||||
config.has("triggerOthers")
|
||||
)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new TargetGoalResetUniversalAnger(
|
||||
config.getBool("triggerOthers")
|
||||
);
|
||||
} 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("reset_universal_anger");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <T> The type of object.
|
||||
*/
|
||||
public interface Testable<T> {
|
||||
public interface Testable<T> extends Predicate<T> {
|
||||
/**
|
||||
* If object matches the test.
|
||||
*
|
||||
@@ -15,4 +17,9 @@ public interface Testable<T> {
|
||||
* @return If matches.
|
||||
*/
|
||||
boolean matches(@Nullable T other);
|
||||
|
||||
@Override
|
||||
default boolean test(@Nullable T other) {
|
||||
return this.matches(other);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ public final class ProxyConstants {
|
||||
*/
|
||||
public static final List<String> SUPPORTED_VERSIONS = Arrays.asList(
|
||||
"v1_17_R1",
|
||||
"v1_18_R1"
|
||||
"v1_18_R1",
|
||||
"v1_18_R2"
|
||||
);
|
||||
|
||||
private ProxyConstants() {
|
||||
|
||||
@@ -31,6 +31,7 @@ public final class Recipes {
|
||||
* Cached recipes from matrix.
|
||||
*/
|
||||
private static final LoadingCache<ItemStack[], Optional<CraftingRecipe>> RECIPES_FROM_MATRIX = Caffeine.newBuilder()
|
||||
.maximumSize(2048L)
|
||||
.build(
|
||||
matrix -> RECIPES.values().stream().filter(recipe -> recipe.test(matrix)).findFirst()
|
||||
);
|
||||
|
||||
@@ -57,6 +57,23 @@ public class GroupedTestableItems implements TestableItem {
|
||||
throw new IllegalStateException("Empty group of children!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get matching child for an ItemStack.
|
||||
*
|
||||
* @param itemStack The ItemStack.
|
||||
* @return The matching child, or null if the item matches nothing.
|
||||
*/
|
||||
@Nullable
|
||||
public TestableItem getMatchingChild(@NotNull final ItemStack itemStack) {
|
||||
for (TestableItem child : children) {
|
||||
if (child.matches(itemStack)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the children.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core.recipe.parts;
|
||||
|
||||
import com.willfp.eco.core.items.Items;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Material;
|
||||
@@ -35,7 +36,13 @@ public class MaterialTestableItem implements TestableItem {
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(@Nullable final ItemStack itemStack) {
|
||||
return itemStack != null && itemStack.getType() == material;
|
||||
boolean simpleMatches = itemStack != null && itemStack.getType() == material;
|
||||
|
||||
if (!simpleMatches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !Items.isCustomItem(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,7 +7,9 @@ import com.willfp.eco.core.Prerequisite;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.recipe.Recipes;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.GroupedTestableItems;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import com.willfp.eco.util.ListUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -66,9 +68,10 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
|
||||
|
||||
@Override
|
||||
public boolean test(@NotNull final ItemStack[] matrix) {
|
||||
List<ItemStack> dynamicMatrix = Arrays.asList(matrix);
|
||||
boolean matches = true;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
if (!parts.get(i).matches(matrix[i])) {
|
||||
if (!parts.get(i).matches(ListUtils.getOrNull(dynamicMatrix, i))) {
|
||||
matches = false;
|
||||
}
|
||||
}
|
||||
@@ -102,23 +105,38 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
|
||||
}
|
||||
|
||||
char character = String.valueOf(i).toCharArray()[0];
|
||||
ItemStack item = parts.get(i).getItem();
|
||||
|
||||
if (parts.get(i) instanceof TestableStack) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
|
||||
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
|
||||
assert lore != null;
|
||||
lore.add("");
|
||||
String add = Eco.getHandler().getEcoPlugin().getLangYml().getFormattedString("multiple-in-craft");
|
||||
add = add.replace("%amount%", String.valueOf(item.getAmount()));
|
||||
lore.add(add);
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
List<TestableItem> items = new ArrayList<>();
|
||||
if (parts.get(i) instanceof GroupedTestableItems group) {
|
||||
items.addAll(group.getChildren());
|
||||
} else {
|
||||
items.add(parts.get(i));
|
||||
}
|
||||
|
||||
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(item));
|
||||
List<ItemStack> displayedItems = new ArrayList<>();
|
||||
|
||||
for (TestableItem testableItem : items) {
|
||||
if (testableItem instanceof TestableStack) {
|
||||
ItemStack item = testableItem.getItem().clone();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
|
||||
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
|
||||
assert lore != null;
|
||||
lore.add("");
|
||||
String add = Eco.getHandler().getEcoPlugin().getLangYml().getFormattedString("multiple-in-craft");
|
||||
add = add.replace("%amount%", String.valueOf(item.getAmount()));
|
||||
lore.add(add);
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
displayedItems.add(item);
|
||||
} else {
|
||||
displayedItems.add(testableItem.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(displayedItems));
|
||||
}
|
||||
|
||||
if (Prerequisite.HAS_1_18.isMet() && !Prerequisite.HAS_PAPER.isMet()) {
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.willfp.eco.core.requirement;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A requirement is a defined goal that a player must meet.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
public abstract class Requirement {
|
||||
/**
|
||||
* Create a new requirement.
|
||||
*/
|
||||
protected Requirement() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the player meets the requirement.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param args The arguments.
|
||||
* @return The requirement.
|
||||
*/
|
||||
public abstract boolean doesPlayerMeet(@NotNull Player player,
|
||||
@NotNull List<String> args);
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.willfp.eco.core.requirement;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Contains methods and fields pertaining to requirements.
|
||||
*
|
||||
* @deprecated See {@link Requirement}.
|
||||
*/
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public final class Requirements {
|
||||
/**
|
||||
* Requires a player to have a permission.
|
||||
*/
|
||||
public static final Requirement HAS_PERMISSION = new com.willfp.eco.core.requirement.impl.RequirementHasPermission();
|
||||
|
||||
/**
|
||||
* Placeholder equals value.
|
||||
*/
|
||||
public static final Requirement PLACEHOLDER_EQUALS = new com.willfp.eco.core.requirement.impl.RequirementPlaceholderEquals();
|
||||
|
||||
/**
|
||||
* Numeric placeholder greater than value.
|
||||
*/
|
||||
public static final Requirement PLACEHOLDER_GREATER_THAN = new com.willfp.eco.core.requirement.impl.RequirementPlaceholderGreaterThan();
|
||||
|
||||
/**
|
||||
* Numeric placeholder less than value.
|
||||
*/
|
||||
public static final Requirement PLACEHOLDER_LESS_THAN = new com.willfp.eco.core.requirement.impl.RequirementPlaceholderLessThan();
|
||||
|
||||
/**
|
||||
* Get Requirements matching ID.
|
||||
*
|
||||
* @param name The ID to search for.
|
||||
* @return The matching Requirements.
|
||||
*/
|
||||
public static Requirement getByID(@NotNull final String name) {
|
||||
return switch (name.toLowerCase()) {
|
||||
case "has-permission" -> HAS_PERMISSION;
|
||||
case "placeholder-equals" -> PLACEHOLDER_EQUALS;
|
||||
case "placeholder-greater-than" -> PLACEHOLDER_GREATER_THAN;
|
||||
case "placeholder-less-than" -> PLACEHOLDER_LESS_THAN;
|
||||
default -> new Requirement() {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
private Requirements() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementHasPermission extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return player.hasPermission(args.get(0));
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementPlaceholderEquals extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return PlaceholderManager.translatePlaceholders(args.get(0), player).equalsIgnoreCase(args.get(1));
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementPlaceholderGreaterThan extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double actual;
|
||||
try {
|
||||
actual = Double.parseDouble(PlaceholderManager.translatePlaceholders(args.get(0), player));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double expected;
|
||||
try {
|
||||
expected = Double.parseDouble(args.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return actual >= expected;
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.willfp.eco.core.requirement.impl;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Moved to API in 6.26.0 after being marked for removal. This class should never be referenced, it
|
||||
* was moved back to the API in order to remove backend components related to Requirements.
|
||||
*
|
||||
* @deprecated No typing, weak definitions, and not an API component. Shouldn't be in eco.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@ApiStatus.ScheduledForRemoval(inVersion = "6.27.0")
|
||||
@Deprecated(since = "6.26.0", forRemoval = true)
|
||||
public class RequirementPlaceholderLessThan extends com.willfp.eco.core.requirement.Requirement {
|
||||
@Override
|
||||
public boolean doesPlayerMeet(@NotNull final Player player,
|
||||
@NotNull final List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double actual;
|
||||
try {
|
||||
actual = Double.parseDouble(PlaceholderManager.translatePlaceholders(args.get(0), player));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double expected;
|
||||
try {
|
||||
expected = Double.parseDouble(args.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return actual < expected;
|
||||
}
|
||||
|
||||
static {
|
||||
Eco.getHandler().getEcoPlugin().getLogger().severe("Loading for-removal Requirements system! This will throw an error once 6.27.0 is released."
|
||||
+ "Make sure you're running the latest version of all your plugins!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
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.
|
||||
* <p>
|
||||
* Deserializers should <b>never</b> throw errors due to invalid configs,
|
||||
* all edge cases must be covered, and all failures must be encapsulated as null.
|
||||
*
|
||||
* @param <T> The type of object to deserialize.
|
||||
*/
|
||||
public interface ConfigDeserializer<T> {
|
||||
/**
|
||||
* Deserialize a config to an object.
|
||||
*
|
||||
* @param config The config.
|
||||
* @return The object, or null if invalid.
|
||||
*/
|
||||
@Nullable
|
||||
T deserialize(@NotNull Config config);
|
||||
}
|
||||
@@ -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 <T> The type of object to serialize.
|
||||
*/
|
||||
public interface ConfigSerializer<T> {
|
||||
/**
|
||||
* Serialize an object to a config.
|
||||
*
|
||||
* @param obj The object.
|
||||
* @return The config.
|
||||
*/
|
||||
@NotNull
|
||||
Config serialize(@NotNull T obj);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.willfp.eco.core.serialization;
|
||||
|
||||
import org.bukkit.Keyed;
|
||||
|
||||
/**
|
||||
* Deserializer with a key.
|
||||
*
|
||||
* @param <T> The type of object to deserialize.
|
||||
* @see ConfigDeserializer
|
||||
*/
|
||||
public interface KeyedDeserializer<T> extends ConfigDeserializer<T>, Keyed {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.willfp.eco.core.serialization;
|
||||
|
||||
import org.bukkit.Keyed;
|
||||
|
||||
/**
|
||||
* Serializer with a key.
|
||||
*
|
||||
* @param <T> The type of object to serialize.
|
||||
* @see ConfigSerializer
|
||||
*/
|
||||
public interface KeyedSerializer<T> extends ConfigSerializer<T>, Keyed {
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -9,28 +8,16 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for blocks.
|
||||
*/
|
||||
public final class BlockUtils {
|
||||
/**
|
||||
* If the meta set function has been set.
|
||||
*/
|
||||
private static boolean initialized = false;
|
||||
|
||||
/**
|
||||
* The block break function.
|
||||
*/
|
||||
private static BiConsumer<Player, Block> blockBreakConsumer = null;
|
||||
|
||||
private static Set<Block> getNearbyBlocks(@NotNull final Block start,
|
||||
@NotNull final List<Material> allowedMaterials,
|
||||
@NotNull final Set<Block> blocks,
|
||||
@@ -75,12 +62,11 @@ public final class BlockUtils {
|
||||
*
|
||||
* @param player The player to break the block as.
|
||||
* @param block The block to break.
|
||||
* @deprecated Added into spigot API in 1.17.1
|
||||
*/
|
||||
@Deprecated(since = "6.26.2", forRemoval = true)
|
||||
public static void breakBlock(@NotNull final Player player,
|
||||
@NotNull final Block block) {
|
||||
Validate.isTrue(initialized, "Must be initialized!");
|
||||
Validate.notNull(blockBreakConsumer, "Must be initialized!");
|
||||
|
||||
Location location = block.getLocation();
|
||||
World world = location.getWorld();
|
||||
assert world != null;
|
||||
@@ -89,7 +75,7 @@ public final class BlockUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
blockBreakConsumer.accept(player, block);
|
||||
player.breakBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,20 +93,6 @@ public final class BlockUtils {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the block break function.
|
||||
*
|
||||
* @param function The function.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void initialize(@NotNull final BiConsumer<Player, Block> function) {
|
||||
Validate.isTrue(!initialized, "Already initialized!");
|
||||
|
||||
blockBreakConsumer = function;
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
private BlockUtils() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
@@ -5,11 +5,10 @@ import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.willfp.eco.core.Prerequisite;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
@@ -324,17 +323,16 @@ public final class StringUtils {
|
||||
|
||||
private static String processFormatting(@NotNull final String message) {
|
||||
String processedMessage = message;
|
||||
// Run MiniMessage first so it doesn't complain
|
||||
processedMessage = translateMiniMessage(processedMessage);
|
||||
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
|
||||
processedMessage = translateGradients(processedMessage);
|
||||
processedMessage = translateHexColorCodes(processedMessage);
|
||||
if (Prerequisite.HAS_PAPER.isMet()) {
|
||||
processedMessage = translateMiniMessage(processedMessage);
|
||||
}
|
||||
return processedMessage;
|
||||
}
|
||||
|
||||
private static String translateMiniMessage(@NotNull final String message) {
|
||||
return LEGACY_COMPONENT_SERIALIZER.serialize(MiniMessage.get().parse(message));
|
||||
return Eco.getHandler().formatMiniMessage(message);
|
||||
}
|
||||
|
||||
private static String translateHexColorCodes(@NotNull final String message) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
@file:JvmName("EntityExtensions")
|
||||
|
||||
package com.willfp.eco.core.entities
|
||||
|
||||
import com.willfp.eco.core.entities.ai.EntityController
|
||||
import org.bukkit.entity.Mob
|
||||
|
||||
/**
|
||||
* @see EntityController.getFor
|
||||
*/
|
||||
val <T : Mob> T.controller: EntityController<T>
|
||||
get() = EntityController.getFor(this)
|
||||
@@ -5,7 +5,7 @@ dependencies {
|
||||
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
|
||||
compileOnly 'me.clip:placeholderapi:2.10.10'
|
||||
compileOnly 'org.reflections:reflections:0.9.12'
|
||||
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
compileOnly 'net.kyori:adventure-text-minimessage:4.10.0'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.1.0'
|
||||
compileOnly 'org.objenesis:objenesis:3.2'
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.willfp.eco.internal.fast
|
||||
|
||||
import com.willfp.eco.core.fast.FastItemStack
|
||||
import org.bukkit.inventory.ItemFlag
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
abstract class EcoFastItemStack<T: Any>(
|
||||
val handle: T,
|
||||
val bukkit: ItemStack
|
||||
) : FastItemStack {
|
||||
override fun unwrap(): ItemStack {
|
||||
return bukkit
|
||||
}
|
||||
|
||||
fun getBitModifier(hideFlag: ItemFlag): Int {
|
||||
return 1 shl hideFlag.ordinal
|
||||
}
|
||||
}
|
||||
10
eco-core/core-nms/nms-common/build.gradle.kts
Normal file
10
eco-core/core-nms/nms-common/build.gradle.kts
Normal file
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id("io.papermc.paperweight.userdev") version "1.3.4"
|
||||
}
|
||||
|
||||
group = "com.willfp"
|
||||
version = rootProject.version
|
||||
|
||||
dependencies {
|
||||
paperDevBundle("1.17.1-R0.1-SNAPSHOT")
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common
|
||||
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.TargetGoalFactory
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Mob
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
private lateinit var impl: CommonsProvider
|
||||
|
||||
val NBT_TAG_STRING by lazy { impl.nbtTagString }
|
||||
|
||||
fun Mob.toPathfinderMob(): PathfinderMob? =
|
||||
impl.toPathfinderMob(this)
|
||||
|
||||
fun NamespacedKey.toResourceLocation(): ResourceLocation =
|
||||
impl.toResourceLocation(this)
|
||||
|
||||
fun ItemStack.asNMSStack(): net.minecraft.world.item.ItemStack =
|
||||
impl.asNMSStack(this)
|
||||
|
||||
fun net.minecraft.world.item.ItemStack.asBukkitStack(): ItemStack =
|
||||
impl.asBukkitStack(this)
|
||||
|
||||
fun ItemStack.mergeIfNeeded(nmsStack: net.minecraft.world.item.ItemStack) =
|
||||
impl.mergeIfNeeded(this, nmsStack)
|
||||
|
||||
fun LivingEntity.toBukkitEntity(): org.bukkit.entity.LivingEntity? =
|
||||
impl.toBukkitEntity(this)
|
||||
|
||||
fun <T : EntityGoal<*>> T.getVersionSpecificEntityGoalFactory(): EntityGoalFactory<T>? =
|
||||
impl.getVersionSpecificEntityGoalFactory(this)
|
||||
|
||||
fun <T : TargetGoal<*>> T.getVersionSpecificEntityGoalFactory(): TargetGoalFactory<T>? =
|
||||
impl.getVersionSpecificTargetGoalFactory(this)
|
||||
|
||||
interface CommonsProvider {
|
||||
val nbtTagString: Int
|
||||
|
||||
fun toPathfinderMob(mob: Mob): PathfinderMob?
|
||||
|
||||
fun toResourceLocation(namespacedKey: NamespacedKey): ResourceLocation
|
||||
|
||||
fun asNMSStack(itemStack: ItemStack): net.minecraft.world.item.ItemStack
|
||||
|
||||
fun asBukkitStack(itemStack: net.minecraft.world.item.ItemStack): ItemStack
|
||||
|
||||
fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack)
|
||||
|
||||
fun toBukkitEntity(entity: LivingEntity): org.bukkit.entity.LivingEntity?
|
||||
|
||||
fun <T : EntityGoal<*>> getVersionSpecificEntityGoalFactory(goal: T): EntityGoalFactory<T>? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun <T : TargetGoal<*>> getVersionSpecificTargetGoalFactory(goal: T): TargetGoalFactory<T>? {
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun setIfNeeded(provider: CommonsProvider) {
|
||||
if (::impl.isInitialized) {
|
||||
return
|
||||
}
|
||||
|
||||
impl = provider
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai
|
||||
|
||||
import com.willfp.eco.core.entities.ai.CustomGoal
|
||||
import com.willfp.eco.core.entities.ai.GoalFlag
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import java.util.EnumSet
|
||||
|
||||
object CustomGoalFactory : EntityGoalFactory<CustomGoal<*>>, TargetGoalFactory<CustomGoal<*>> {
|
||||
override fun create(apiGoal: CustomGoal<*>, entity: PathfinderMob): Goal {
|
||||
return NMSCustomGoal(apiGoal, entity)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal): Boolean = goal is NMSCustomGoal<*>
|
||||
|
||||
fun isGoalOfType(goal: Goal, apiGoal: CustomGoal<*>): Boolean {
|
||||
if (goal !is NMSCustomGoal<*>) return false
|
||||
|
||||
// ew
|
||||
return goal.customEntityGoal::class.java.name == apiGoal::class.java.name
|
||||
}
|
||||
}
|
||||
|
||||
private fun Collection<Goal.Flag>.toEcoFlags(): Collection<GoalFlag> {
|
||||
return this.mapNotNull {
|
||||
when (it) {
|
||||
Goal.Flag.JUMP -> GoalFlag.JUMP
|
||||
Goal.Flag.LOOK -> GoalFlag.LOOK
|
||||
Goal.Flag.MOVE -> GoalFlag.MOVE
|
||||
Goal.Flag.TARGET -> GoalFlag.TARGET
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Collection<GoalFlag>.toNMSFlags(): Collection<Goal.Flag> {
|
||||
return this.mapNotNull {
|
||||
when (it) {
|
||||
GoalFlag.JUMP -> Goal.Flag.JUMP
|
||||
GoalFlag.LOOK -> Goal.Flag.LOOK
|
||||
GoalFlag.MOVE -> Goal.Flag.MOVE
|
||||
GoalFlag.TARGET -> Goal.Flag.TARGET
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class NMSCustomGoal<T : org.bukkit.entity.Mob>(
|
||||
val customEntityGoal: CustomGoal<T>,
|
||||
entity: PathfinderMob
|
||||
) : Goal() {
|
||||
init {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
customEntityGoal.initialize(entity.bukkitMob as T)
|
||||
this.setFlags(EnumSet.copyOf(customEntityGoal.flags.toNMSFlags()))
|
||||
}
|
||||
|
||||
override fun canUse(): Boolean {
|
||||
return customEntityGoal.canUse()
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
customEntityGoal.tick()
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
customEntityGoal.start()
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
customEntityGoal.stop()
|
||||
}
|
||||
|
||||
override fun canContinueToUse(): Boolean {
|
||||
return customEntityGoal.canContinueToUse()
|
||||
}
|
||||
|
||||
override fun isInterruptable(): Boolean {
|
||||
return customEntityGoal.isInterruptable
|
||||
}
|
||||
|
||||
override fun setFlags(controls: EnumSet<Flag>) {
|
||||
super.setFlags(controls)
|
||||
customEntityGoal.flags = EnumSet.copyOf(controls.toEcoFlags())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai
|
||||
|
||||
import com.willfp.eco.core.entities.ai.CustomGoal
|
||||
import com.willfp.eco.core.entities.ai.EntityController
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal
|
||||
import com.willfp.eco.internal.spigot.proxy.common.toPathfinderMob
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import org.bukkit.entity.Mob
|
||||
|
||||
class EcoEntityController<T : Mob>(
|
||||
private val handle: T
|
||||
) : EntityController<T> {
|
||||
override fun addEntityGoal(priority: Int, goal: EntityGoal<in T>): EntityController<T> {
|
||||
val nms = getNms() ?: return this
|
||||
|
||||
nms.goalSelector.addGoal(
|
||||
priority,
|
||||
goal.getGoalFactory()?.create(goal, nms) ?: return this
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
override fun removeEntityGoal(goal: EntityGoal<in T>): EntityController<T> {
|
||||
val nms = getNms() ?: return this
|
||||
|
||||
val predicate: (Goal) -> Boolean = if (goal is CustomGoal<*>) {
|
||||
{ CustomGoalFactory.isGoalOfType(it, goal) }
|
||||
} else {
|
||||
{ goal.getGoalFactory()?.isGoalOfType(it) == true }
|
||||
}
|
||||
|
||||
for (wrapped in nms.goalSelector.availableGoals.toSet()) {
|
||||
if (predicate(wrapped.goal)) {
|
||||
nms.goalSelector.removeGoal(wrapped.goal)
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
override fun clearEntityGoals(): EntityController<T> {
|
||||
val nms = getNms() ?: return this
|
||||
nms.goalSelector.availableGoals.clear()
|
||||
return this
|
||||
}
|
||||
|
||||
override fun addTargetGoal(priority: Int, goal: TargetGoal<in T>): EntityController<T> {
|
||||
val nms = getNms() ?: return this
|
||||
|
||||
nms.targetSelector.addGoal(
|
||||
priority, goal.getGoalFactory()?.create(goal, nms) ?: return this
|
||||
)
|
||||
|
||||
nms.targetSelector
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
override fun removeTargetGoal(goal: TargetGoal<in T>): EntityController<T> {
|
||||
val nms = getNms() ?: return this
|
||||
|
||||
val predicate: (Goal) -> Boolean = if (goal is CustomGoal<*>) {
|
||||
{ CustomGoalFactory.isGoalOfType(it, goal) }
|
||||
} else {
|
||||
{ goal.getGoalFactory()?.isGoalOfType(it) == true }
|
||||
}
|
||||
|
||||
for (wrapped in nms.targetSelector.availableGoals.toSet()) {
|
||||
if (predicate(wrapped.goal)) {
|
||||
nms.targetSelector.removeGoal(wrapped.goal)
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
override fun clearTargetGoals(): EntityController<T> {
|
||||
val nms = getNms() ?: return this
|
||||
nms.targetSelector.availableGoals.clear()
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getNms(): PathfinderMob? {
|
||||
return handle.toPathfinderMob()
|
||||
}
|
||||
|
||||
override fun getEntity(): T {
|
||||
return handle
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai
|
||||
|
||||
import com.willfp.eco.core.entities.ai.CustomGoal
|
||||
import com.willfp.eco.core.entities.ai.EntityGoal
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalAvoidEntity
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreakDoors
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreatheAir
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreed
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalCatLieOnBed
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalCatSitOnBed
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalEatGrass
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFleeSun
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFloat
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFollowBoats
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFollowMobs
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalIllusionerBlindnessSpell
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalIllusionerMirrorSpell
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalInteract
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLookAtPlayer
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMeleeAttack
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveBackToVillage
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveThroughVillage
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveTowardsRestriction
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalMoveTowardsTarget
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalOcelotAttack
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalOpenDoors
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalPanic
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRandomLookAround
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRandomStroll
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRandomSwimming
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRangedAttack
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRangedBowAttack
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRangedCrossbowAttack
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalRestrictSun
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalStrollThroughVillage
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalTempt
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalTryFindWater
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalUseItem
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalWaterAvoidingRandomFlying
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalWaterAvoidingRandomStroll
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalWolfBeg
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.AvoidEntityGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.BreakDoorsGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.BreatheAirGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.BreedGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.CatLieOnBedGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.CatSitOnBedGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.EatGrassGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.FleeSunGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.FloatGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.FollowBoatsGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.FollowMobsGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.IllusionerBlindnessSpellGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.IllusionerMirrorSpellGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.InteractGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.LeapAtTargetGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.LookAtPlayerGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.MeleeAttackGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.MoveBackToVillageGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.MoveThroughVillageGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.MoveTowardsRestrictionGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.MoveTowardsTargetGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.OcelotAttackGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.OpenDoorsGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.PanicGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RandomLookAroundGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RandomStrollGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RandomSwimmingGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RangedAttackGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RangedBowAttackGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RangedCrossbowAttackGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.RestrictSunGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.StrollThroughVillageGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.TemptGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.TryFindWaterGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.UseItemGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.WaterAvoidingRandomFlyingGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.WaterAvoidingRandomStrollGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.entity.WolfBegGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.getVersionSpecificEntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
fun <T : EntityGoal<*>> T.getGoalFactory(): EntityGoalFactory<T>? {
|
||||
val versionSpecific = this.getVersionSpecificEntityGoalFactory()
|
||||
if (versionSpecific != null) {
|
||||
return versionSpecific
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (this) {
|
||||
is EntityGoalAvoidEntity -> AvoidEntityGoalFactory
|
||||
is EntityGoalBreakDoors -> BreakDoorsGoalFactory
|
||||
is EntityGoalBreatheAir -> BreatheAirGoalFactory
|
||||
is EntityGoalEatGrass -> EatGrassGoalFactory
|
||||
is EntityGoalFleeSun -> FleeSunGoalFactory
|
||||
is EntityGoalFloat -> FloatGoalFactory
|
||||
is EntityGoalFollowBoats -> FollowBoatsGoalFactory
|
||||
is EntityGoalFollowMobs -> FollowMobsGoalFactory
|
||||
is EntityGoalInteract -> InteractGoalFactory
|
||||
is EntityGoalLeapAtTarget -> LeapAtTargetGoalFactory
|
||||
is EntityGoalLookAtPlayer -> LookAtPlayerGoalFactory
|
||||
is EntityGoalMeleeAttack -> MeleeAttackGoalFactory
|
||||
is EntityGoalMoveBackToVillage -> MoveBackToVillageGoalFactory
|
||||
is EntityGoalMoveThroughVillage -> MoveThroughVillageGoalFactory
|
||||
is EntityGoalMoveTowardsRestriction -> MoveTowardsRestrictionGoalFactory
|
||||
is EntityGoalMoveTowardsTarget -> MoveTowardsTargetGoalFactory
|
||||
is EntityGoalOcelotAttack -> OcelotAttackGoalFactory
|
||||
is EntityGoalOpenDoors -> OpenDoorsGoalFactory
|
||||
is EntityGoalPanic -> PanicGoalFactory
|
||||
is EntityGoalRandomLookAround -> RandomLookAroundGoalFactory
|
||||
is EntityGoalRandomStroll -> RandomStrollGoalFactory
|
||||
is EntityGoalRandomSwimming -> RandomSwimmingGoalFactory
|
||||
is EntityGoalRangedAttack -> RangedAttackGoalFactory
|
||||
is EntityGoalRangedBowAttack -> RangedBowAttackGoalFactory
|
||||
is EntityGoalRangedCrossbowAttack -> RangedCrossbowAttackGoalFactory
|
||||
is EntityGoalRestrictSun -> RestrictSunGoalFactory
|
||||
is EntityGoalStrollThroughVillage -> StrollThroughVillageGoalFactory
|
||||
is EntityGoalTempt -> TemptGoalFactory
|
||||
is EntityGoalTryFindWater -> TryFindWaterGoalFactory
|
||||
is EntityGoalUseItem -> UseItemGoalFactory
|
||||
is EntityGoalWaterAvoidingRandomFlying -> WaterAvoidingRandomFlyingGoalFactory
|
||||
is EntityGoalWaterAvoidingRandomStroll -> WaterAvoidingRandomStrollGoalFactory
|
||||
is EntityGoalWolfBeg -> WolfBegGoalFactory
|
||||
is EntityGoalBreed -> BreedGoalFactory
|
||||
is EntityGoalCatSitOnBed -> CatSitOnBedGoalFactory
|
||||
is EntityGoalCatLieOnBed -> CatLieOnBedGoalFactory
|
||||
is EntityGoalIllusionerBlindnessSpell -> IllusionerBlindnessSpellGoalFactory
|
||||
is EntityGoalIllusionerMirrorSpell -> IllusionerMirrorSpellGoalFactory
|
||||
is CustomGoal<*> -> CustomGoalFactory
|
||||
else -> null
|
||||
} as EntityGoalFactory<T>?
|
||||
}
|
||||
|
||||
interface EntityGoalFactory<T : EntityGoal<*>> {
|
||||
fun create(apiGoal: T, entity: PathfinderMob): Goal?
|
||||
fun isGoalOfType(goal: Goal): Boolean
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai
|
||||
|
||||
import com.willfp.eco.core.entities.ai.CustomGoal
|
||||
import com.willfp.eco.core.entities.ai.TargetGoal
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalHurtBy
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNearestAttackable
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNearestAttackableWitch
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNearestHealableRaider
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalNonTameRandom
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalOwnerHurtBy
|
||||
import com.willfp.eco.core.entities.ai.target.TargetGoalOwnerTarget
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.HurtByGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.NearestAttackableGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.NearestAttackableWitchGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.NearestHealableRaiderGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.NonTameRandomGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.OwnerHurtByGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.target.OwnerTargetGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.getVersionSpecificEntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
fun <T : TargetGoal<*>> T.getGoalFactory(): TargetGoalFactory<T>? {
|
||||
val versionSpecific = this.getVersionSpecificEntityGoalFactory()
|
||||
if (versionSpecific != null) {
|
||||
return versionSpecific
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (this) {
|
||||
is TargetGoalHurtBy -> HurtByGoalFactory
|
||||
is TargetGoalNearestAttackable -> NearestAttackableGoalFactory
|
||||
is TargetGoalNearestAttackableWitch -> NearestAttackableWitchGoalFactory
|
||||
is TargetGoalNearestHealableRaider -> NearestHealableRaiderGoalFactory
|
||||
is TargetGoalNonTameRandom -> NonTameRandomGoalFactory
|
||||
is TargetGoalOwnerHurtBy -> OwnerHurtByGoalFactory
|
||||
is TargetGoalOwnerTarget -> OwnerTargetGoalFactory
|
||||
is CustomGoal<*> -> CustomGoalFactory
|
||||
else -> null
|
||||
} as TargetGoalFactory<T>?
|
||||
}
|
||||
|
||||
interface TargetGoalFactory<T : TargetGoal<*>> {
|
||||
fun create(apiGoal: T, entity: PathfinderMob): Goal?
|
||||
fun isGoalOfType(goal: Goal): Boolean
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalAvoidEntity
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.toBukkitEntity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.AvoidEntityGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object AvoidEntityGoalFactory : EntityGoalFactory<EntityGoalAvoidEntity> {
|
||||
override fun create(apiGoal: EntityGoalAvoidEntity, entity: PathfinderMob): Goal {
|
||||
return AvoidEntityGoal(
|
||||
entity,
|
||||
LivingEntity::class.java,
|
||||
apiGoal.distance.toFloat(),
|
||||
apiGoal.slowSpeed,
|
||||
apiGoal.fastSpeed
|
||||
) { apiGoal.entity.test(it.toBukkitEntity()) }
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is AvoidEntityGoal<*>
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreakDoors
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.BreakDoorGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object BreakDoorsGoalFactory : EntityGoalFactory<EntityGoalBreakDoors> {
|
||||
override fun create(apiGoal: EntityGoalBreakDoors, entity: PathfinderMob): Goal {
|
||||
return BreakDoorGoal(
|
||||
entity,
|
||||
apiGoal.ticks
|
||||
) { true }
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is BreakDoorGoal
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreatheAir
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.BreathAirGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object BreatheAirGoalFactory : EntityGoalFactory<EntityGoalBreatheAir> {
|
||||
override fun create(apiGoal: EntityGoalBreatheAir, entity: PathfinderMob): Goal {
|
||||
return BreathAirGoal(
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is BreathAirGoal
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalBreed
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.BreedGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.animal.Animal
|
||||
|
||||
object BreedGoalFactory : EntityGoalFactory<EntityGoalBreed> {
|
||||
override fun create(apiGoal: EntityGoalBreed, entity: PathfinderMob): Goal? {
|
||||
return BreedGoal(
|
||||
entity as? Animal ?: return null,
|
||||
apiGoal.speed
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is BreedGoal
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalCatLieOnBed
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.CatLieOnBedGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.animal.Cat
|
||||
|
||||
object CatLieOnBedGoalFactory : EntityGoalFactory<EntityGoalCatLieOnBed> {
|
||||
override fun create(apiGoal: EntityGoalCatLieOnBed, entity: PathfinderMob): Goal? {
|
||||
return CatLieOnBedGoal(
|
||||
entity as? Cat ?: return null,
|
||||
apiGoal.speed,
|
||||
apiGoal.range
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is CatLieOnBedGoal
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalCatSitOnBed
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.CatSitOnBlockGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.animal.Cat
|
||||
|
||||
object CatSitOnBedGoalFactory : EntityGoalFactory<EntityGoalCatSitOnBed> {
|
||||
override fun create(apiGoal: EntityGoalCatSitOnBed, entity: PathfinderMob): Goal? {
|
||||
return CatSitOnBlockGoal(
|
||||
entity as? Cat ?: return null,
|
||||
apiGoal.speed
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is CatSitOnBlockGoal
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalEatGrass
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.EatBlockGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object EatGrassGoalFactory : EntityGoalFactory<EntityGoalEatGrass> {
|
||||
override fun create(apiGoal: EntityGoalEatGrass, entity: PathfinderMob): Goal {
|
||||
return EatBlockGoal(
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is EatBlockGoal
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFleeSun
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.FleeSunGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object FleeSunGoalFactory : EntityGoalFactory<EntityGoalFleeSun> {
|
||||
override fun create(apiGoal: EntityGoalFleeSun, entity: PathfinderMob): Goal {
|
||||
return FleeSunGoal(
|
||||
entity,
|
||||
apiGoal.speed
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is FleeSunGoal
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFloat
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.FloatGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object FloatGoalFactory : EntityGoalFactory<EntityGoalFloat> {
|
||||
override fun create(apiGoal: EntityGoalFloat, entity: PathfinderMob): Goal {
|
||||
return FloatGoal(
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is FloatGoal
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFollowBoats
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.FollowBoatGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object FollowBoatsGoalFactory : EntityGoalFactory<EntityGoalFollowBoats> {
|
||||
override fun create(apiGoal: EntityGoalFollowBoats, entity: PathfinderMob): Goal {
|
||||
return FollowBoatGoal(
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is FollowBoatGoal
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalFollowMobs
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.FollowMobGoal
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
|
||||
object FollowMobsGoalFactory : EntityGoalFactory<EntityGoalFollowMobs> {
|
||||
override fun create(apiGoal: EntityGoalFollowMobs, entity: PathfinderMob): Goal {
|
||||
return FollowMobGoal(
|
||||
entity,
|
||||
apiGoal.speed,
|
||||
apiGoal.minDistance.toFloat(),
|
||||
apiGoal.maxDistance.toFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is FollowMobGoal
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.opengoals.IllusionerBlindnessSpellGoal
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.monster.Illusioner
|
||||
|
||||
object IllusionerBlindnessSpellGoalFactory : EntityGoalFactory<EntityGoalLeapAtTarget> {
|
||||
override fun create(apiGoal: EntityGoalLeapAtTarget, entity: PathfinderMob): Goal? {
|
||||
if (entity !is Illusioner) return null
|
||||
|
||||
return IllusionerBlindnessSpellGoal(
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is IllusionerBlindnessSpellGoal
|
||||
|| goal::class.java.name.contains("IllusionerBlindnessSpellGoal")
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.opengoals.IllusionerMirrorSpellGoal
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.monster.Illusioner
|
||||
|
||||
object IllusionerMirrorSpellGoalFactory : EntityGoalFactory<EntityGoalLeapAtTarget> {
|
||||
override fun create(apiGoal: EntityGoalLeapAtTarget, entity: PathfinderMob): Goal? {
|
||||
if (entity !is Illusioner) return null
|
||||
|
||||
return IllusionerMirrorSpellGoal(
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is IllusionerMirrorSpellGoal
|
||||
|| goal::class.java.name.contains("IllusionerMirrorSpellGoal")
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.TestableEntity
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalInteract
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import com.willfp.eco.internal.spigot.proxy.common.toBukkitEntity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.ai.goal.InteractGoal
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
object InteractGoalFactory : EntityGoalFactory<EntityGoalInteract> {
|
||||
override fun create(apiGoal: EntityGoalInteract, entity: PathfinderMob): Goal {
|
||||
return EnhancedInteractGoal(
|
||||
entity,
|
||||
apiGoal.target,
|
||||
apiGoal.range.toFloat(),
|
||||
apiGoal.chance.toFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is InteractGoal
|
||||
}
|
||||
|
||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||
private class EnhancedInteractGoal(
|
||||
mob: PathfinderMob,
|
||||
private val target: TestableEntity,
|
||||
range: Float,
|
||||
chance: Float
|
||||
) : InteractGoal(
|
||||
mob,
|
||||
LivingEntity::class.java,
|
||||
range,
|
||||
chance
|
||||
) {
|
||||
override fun canUse(): Boolean {
|
||||
return if (mob.random.nextFloat() >= probability) {
|
||||
false
|
||||
} else {
|
||||
@Suppress("SENSELESS_COMPARISON")
|
||||
if (mob.target != null) {
|
||||
lookAt = mob.target
|
||||
}
|
||||
val lookAt = if (lookAtType == Player::class.java) {
|
||||
mob.level.getNearestPlayer(lookAtContext, mob, mob.x, mob.eyeY, mob.z)
|
||||
} else {
|
||||
mob.level.getNearestEntity(
|
||||
mob.level.getEntitiesOfClass(
|
||||
lookAtType, mob.boundingBox.inflate(
|
||||
lookDistance.toDouble(), 3.0, lookDistance.toDouble()
|
||||
)
|
||||
) { target.matches(it.toBukkitEntity()) }, // Change this line to check with TestableEntity.
|
||||
lookAtContext, mob, mob.x, mob.eyeY, mob.z
|
||||
)
|
||||
}
|
||||
lookAt != null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||
|
||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget
|
||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.goal.Goal
|
||||
import net.minecraft.world.entity.ai.goal.LeapAtTargetGoal
|
||||
|
||||
object LeapAtTargetGoalFactory : EntityGoalFactory<EntityGoalLeapAtTarget> {
|
||||
override fun create(apiGoal: EntityGoalLeapAtTarget, entity: PathfinderMob): Goal {
|
||||
return LeapAtTargetGoal(
|
||||
entity,
|
||||
apiGoal.velocity.toFloat()
|
||||
)
|
||||
}
|
||||
|
||||
override fun isGoalOfType(goal: Goal) = goal is LeapAtTargetGoal
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user