Tempt now uses TestableItem

This commit is contained in:
Auxilor
2022-03-02 19:12:59 +00:00
parent 2294c3758d
commit fbc7bb6f07
7 changed files with 157 additions and 15 deletions

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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?

View File

@@ -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()
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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