Tempt now uses TestableItem
This commit is contained in:
@@ -8,11 +8,11 @@ import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
|||||||
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
import com.willfp.eco.core.serialization.KeyedDeserializer;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.entity.Mob;
|
import org.bukkit.entity.Mob;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,9 +24,20 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
public record EntityGoalTempt(
|
public record EntityGoalTempt(
|
||||||
double speed,
|
double speed,
|
||||||
Collection<ItemStack> items,
|
Collection<TestableItem> items,
|
||||||
boolean canBeScared
|
boolean canBeScared
|
||||||
) implements EntityGoal<Mob> {
|
) 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.
|
* The deserializer for the goal.
|
||||||
*/
|
*/
|
||||||
@@ -48,10 +59,9 @@ public record EntityGoalTempt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Collection<ItemStack> items = config.getStrings("items").stream()
|
Collection<TestableItem> items = config.getStrings("items").stream()
|
||||||
.map(Items::lookup)
|
.map(Items::lookup)
|
||||||
.filter(it -> !(it instanceof EmptyTestableItem))
|
.filter(it -> !(it instanceof EmptyTestableItem))
|
||||||
.map(TestableItem::getItem)
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
return new EntityGoalTempt(
|
return new EntityGoalTempt(
|
||||||
|
|||||||
@@ -49,13 +49,11 @@ public record EntityGoalUseItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ItemStack item = Items.lookup(config.getString("item")).getItem();
|
|
||||||
Sound sound = Sound.valueOf(config.getString("sound").toUpperCase());
|
|
||||||
TestableEntity filter = Entities.lookup(config.getString("condition"));
|
TestableEntity filter = Entities.lookup(config.getString("condition"));
|
||||||
|
|
||||||
return new EntityGoalUseItem(
|
return new EntityGoalUseItem(
|
||||||
item,
|
Items.lookup(config.getString("item")).getItem(),
|
||||||
sound,
|
Sound.valueOf(config.getString("sound").toUpperCase()),
|
||||||
filter::matches
|
filter::matches
|
||||||
);
|
);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -24,16 +24,19 @@ fun NamespacedKey.toResourceLocation(): ResourceLocation =
|
|||||||
fun ItemStack.asNMSStack(): net.minecraft.world.item.ItemStack =
|
fun ItemStack.asNMSStack(): net.minecraft.world.item.ItemStack =
|
||||||
impl.asNMSStack(this)
|
impl.asNMSStack(this)
|
||||||
|
|
||||||
|
fun net.minecraft.world.item.ItemStack.asBukkitStack(): ItemStack =
|
||||||
|
impl.asBukkitStack(this)
|
||||||
|
|
||||||
fun ItemStack.mergeIfNeeded(nmsStack: net.minecraft.world.item.ItemStack) =
|
fun ItemStack.mergeIfNeeded(nmsStack: net.minecraft.world.item.ItemStack) =
|
||||||
impl.mergeIfNeeded(this, nmsStack)
|
impl.mergeIfNeeded(this, nmsStack)
|
||||||
|
|
||||||
fun LivingEntity.toBukkitEntity(): org.bukkit.entity.LivingEntity? =
|
fun LivingEntity.toBukkitEntity(): org.bukkit.entity.LivingEntity? =
|
||||||
impl.toBukkitEntity(this)
|
impl.toBukkitEntity(this)
|
||||||
|
|
||||||
fun <T: EntityGoal<*>> T.getVersionSpecificEntityGoalFactory(): EntityGoalFactory<T>? =
|
fun <T : EntityGoal<*>> T.getVersionSpecificEntityGoalFactory(): EntityGoalFactory<T>? =
|
||||||
impl.getVersionSpecificEntityGoalFactory(this)
|
impl.getVersionSpecificEntityGoalFactory(this)
|
||||||
|
|
||||||
fun <T: TargetGoal<*>> T.getVersionSpecificEntityGoalFactory(): TargetGoalFactory<T>? =
|
fun <T : TargetGoal<*>> T.getVersionSpecificEntityGoalFactory(): TargetGoalFactory<T>? =
|
||||||
impl.getVersionSpecificTargetGoalFactory(this)
|
impl.getVersionSpecificTargetGoalFactory(this)
|
||||||
|
|
||||||
interface CommonsProvider {
|
interface CommonsProvider {
|
||||||
@@ -45,6 +48,8 @@ interface CommonsProvider {
|
|||||||
|
|
||||||
fun asNMSStack(itemStack: ItemStack): net.minecraft.world.item.ItemStack
|
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 mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack)
|
||||||
|
|
||||||
fun toBukkitEntity(entity: LivingEntity): org.bukkit.entity.LivingEntity?
|
fun toBukkitEntity(entity: LivingEntity): org.bukkit.entity.LivingEntity?
|
||||||
|
|||||||
@@ -1,20 +1,137 @@
|
|||||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||||
|
|
||||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalTempt
|
import com.willfp.eco.core.entities.ai.entity.EntityGoalTempt
|
||||||
|
import com.willfp.eco.core.items.TestableItem
|
||||||
|
import com.willfp.eco.core.recipe.parts.GroupedTestableItems
|
||||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||||
import com.willfp.eco.internal.spigot.proxy.common.asNMSStack
|
import net.minecraft.world.entity.Entity
|
||||||
|
import net.minecraft.world.entity.LivingEntity
|
||||||
import net.minecraft.world.entity.PathfinderMob
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
import net.minecraft.world.entity.ai.goal.Goal
|
import net.minecraft.world.entity.ai.goal.Goal
|
||||||
import net.minecraft.world.entity.ai.goal.TemptGoal
|
import net.minecraft.world.entity.ai.targeting.TargetingConditions
|
||||||
import net.minecraft.world.item.crafting.Ingredient
|
import org.bukkit.craftbukkit.v1_17_R1.entity.CraftLivingEntity
|
||||||
|
import org.bukkit.craftbukkit.v1_17_R1.event.CraftEventFactory
|
||||||
|
import org.bukkit.event.entity.EntityTargetEvent
|
||||||
|
import java.util.EnumSet
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
object TemptGoalFactory : EntityGoalFactory<EntityGoalTempt> {
|
object TemptGoalFactory : EntityGoalFactory<EntityGoalTempt> {
|
||||||
override fun create(apiGoal: EntityGoalTempt, entity: PathfinderMob): Goal {
|
override fun create(apiGoal: EntityGoalTempt, entity: PathfinderMob): Goal {
|
||||||
return TemptGoal(
|
return EnhancedTemptGoal(
|
||||||
entity,
|
entity,
|
||||||
apiGoal.speed,
|
apiGoal.speed,
|
||||||
Ingredient.of(*apiGoal.items.map { it.asNMSStack() }.toTypedArray()),
|
GroupedTestableItems(apiGoal.items),
|
||||||
apiGoal.canBeScared
|
apiGoal.canBeScared
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||||
|
class EnhancedTemptGoal(
|
||||||
|
private val mob: PathfinderMob,
|
||||||
|
private val speedModifier: Double,
|
||||||
|
private val item: TestableItem,
|
||||||
|
private val canScare: Boolean
|
||||||
|
) : Goal() {
|
||||||
|
private val targetingConditions: TargetingConditions
|
||||||
|
private var px = 0.0
|
||||||
|
private var py = 0.0
|
||||||
|
private var pz = 0.0
|
||||||
|
private var pRotX = 0.0
|
||||||
|
private var pRotY = 0.0
|
||||||
|
private var player: LivingEntity? = null
|
||||||
|
private var calmDown = 0
|
||||||
|
private var isRunning = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK))
|
||||||
|
targetingConditions = TEMP_TARGETING.copy().selector { shouldFollow(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canUse(): Boolean {
|
||||||
|
return if (calmDown > 0) {
|
||||||
|
--calmDown
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
player = mob.level.getNearestPlayer(targetingConditions, mob as LivingEntity)
|
||||||
|
// CraftBukkit start
|
||||||
|
if (player != null) {
|
||||||
|
val event = CraftEventFactory.callEntityTargetLivingEvent(
|
||||||
|
mob,
|
||||||
|
player,
|
||||||
|
EntityTargetEvent.TargetReason.TEMPT
|
||||||
|
)
|
||||||
|
if (event.isCancelled) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
player = if (event.target == null) null else (event.target as CraftLivingEntity?)!!.handle
|
||||||
|
}
|
||||||
|
// CraftBukkit end
|
||||||
|
player != null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldFollow(entity: LivingEntity): Boolean {
|
||||||
|
return item.matches(entity.mainHandItem.asBukkitCopy()) || item.matches(entity.offhandItem.asBukkitCopy())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canContinueToUse(): Boolean {
|
||||||
|
if (canScare()) {
|
||||||
|
val p = player ?: return false
|
||||||
|
|
||||||
|
if (mob.distanceToSqr(p) < 36.0) {
|
||||||
|
if (p.distanceToSqr(px, py, pz) > 0.010000000000000002) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (abs(p.xRot.toDouble() - pRotX) > 5.0 || abs(
|
||||||
|
p.getYRot().toDouble() - pRotY
|
||||||
|
) > 5.0
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
px = p.x
|
||||||
|
py = p.y
|
||||||
|
pz = p.z
|
||||||
|
}
|
||||||
|
pRotX = p.xRot.toDouble()
|
||||||
|
pRotY = p.getYRot().toDouble()
|
||||||
|
}
|
||||||
|
return canUse()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun canScare(): Boolean {
|
||||||
|
return canScare
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun start() {
|
||||||
|
val p = player ?: return
|
||||||
|
|
||||||
|
px = p.x
|
||||||
|
py = p.y
|
||||||
|
pz = p.z
|
||||||
|
isRunning = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stop() {
|
||||||
|
player = null
|
||||||
|
mob.navigation.stop()
|
||||||
|
calmDown = 100
|
||||||
|
isRunning = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick() {
|
||||||
|
player ?: return
|
||||||
|
|
||||||
|
mob.lookControl.setLookAt(player, (mob.maxHeadYRot + 20).toFloat(), mob.maxHeadXRot.toFloat())
|
||||||
|
if (mob.distanceToSqr(player as Entity) < 6.25) {
|
||||||
|
mob.navigation.stop()
|
||||||
|
} else {
|
||||||
|
mob.navigation.moveTo(player as Entity, speedModifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TEMP_TARGETING = TargetingConditions.forNonCombat().range(10.0).ignoreLineOfSight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ class CommonsInitializer : CommonsInitializerProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun asBukkitStack(itemStack: net.minecraft.world.item.ItemStack): ItemStack {
|
||||||
|
return CraftItemStack.asBukkitCopy(itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
||||||
if (itemStack !is CraftItemStack) {
|
if (itemStack !is CraftItemStack) {
|
||||||
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ class CommonsInitializer : CommonsInitializerProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun asBukkitStack(itemStack: net.minecraft.world.item.ItemStack): ItemStack {
|
||||||
|
return CraftItemStack.asBukkitCopy(itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
||||||
if (itemStack !is CraftItemStack) {
|
if (itemStack !is CraftItemStack) {
|
||||||
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ class CommonsInitializer : CommonsInitializerProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun asBukkitStack(itemStack: net.minecraft.world.item.ItemStack): ItemStack {
|
||||||
|
return CraftItemStack.asBukkitCopy(itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
||||||
if (itemStack !is CraftItemStack) {
|
if (itemStack !is CraftItemStack) {
|
||||||
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
||||||
|
|||||||
Reference in New Issue
Block a user