From 8cec3e5be5f323bf7293af6612ea01db302d01a5 Mon Sep 17 00:00:00 2001 From: Gabber235 Date: Sat, 14 Dec 2024 21:00:09 +0100 Subject: [PATCH] LookAtEntityInteractionBoundEntry --- .../entry/entity/ActivityEntityDisplay.kt | 9 + .../paper/entry/entity/EntityHandler.kt | 3 +- .../entity/GroupActivityEntityDisplay.kt | 13 +- .../entity/IndividualActivityEntityDisplay.kt | 20 +- .../entity/SharedActivityEntityDisplay.kt | 13 +- .../events/AsyncEntityDefinitionInteract.kt | 2 + .../entries/activity/LookCloseActivity.kt | 5 +- .../LookAtEntityInteractionBoundEntry.kt | 194 ++++++++++++++++++ .../entries/event/EntityInteractEventEntry.kt | 15 +- 9 files changed, 248 insertions(+), 26 deletions(-) create mode 100644 extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/bound/LookAtEntityInteractionBoundEntry.kt diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/ActivityEntityDisplay.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/ActivityEntityDisplay.kt index 8bec4ff119..0a74db64e4 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/ActivityEntityDisplay.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/ActivityEntityDisplay.kt @@ -1,7 +1,9 @@ package com.typewritermc.engine.paper.entry.entity +import com.typewritermc.core.entries.Ref import com.typewritermc.core.utils.point.Position import com.typewritermc.engine.paper.entry.entries.EntityDefinitionEntry +import com.typewritermc.engine.paper.entry.entries.EntityInstanceEntry import org.bukkit.Location import java.util.UUID @@ -10,6 +12,8 @@ interface ActivityEntityDisplay { val definition: EntityDefinitionEntry? get() = creator as? EntityDefinitionEntry + val instanceEntryRef: Ref + fun playerSeesEntity(playerId: UUID, entityId: Int): Boolean /** @@ -17,6 +21,11 @@ interface ActivityEntityDisplay { */ fun position(playerId: UUID): Position? + /** + * The entity state for the player. + */ + fun entityState(playerId: UUID): EntityState + /** * Whether the player can view the entity. * This is regardless of whether the entity is spawned in for the player. diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/EntityHandler.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/EntityHandler.kt index 526c33929b..3ac4cd5185 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/EntityHandler.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/EntityHandler.kt @@ -44,7 +44,8 @@ class EntityHandler : PacketListenerAbstract(), KoinComponent { .firstOrNull { it.playerSeesEntity(event.user.uuid, entityId) } ?: return val definition = display.definition ?: return - AsyncEntityDefinitionInteract(player, entityId, definition, packet.hand, packet.action).callEvent() + val instance = display.instanceEntryRef.get() ?: return + AsyncEntityDefinitionInteract(player, entityId, definition, instance, packet.hand, packet.action).callEvent() } fun shutdown() { diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/GroupActivityEntityDisplay.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/GroupActivityEntityDisplay.kt index d31ca3e7ce..9ca769adbd 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/GroupActivityEntityDisplay.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/GroupActivityEntityDisplay.kt @@ -9,13 +9,13 @@ import java.util.* import java.util.concurrent.ConcurrentHashMap class GroupActivityEntityDisplay( - private val ref: Ref, + override val instanceEntryRef: Ref, override val creator: EntityCreator, private val activityCreators: ActivityCreator, private val suppliers: List, Int>>, private val spawnPosition: Position, private val group: GroupEntry, -) : AudienceFilter(ref), TickableDisplay, ActivityEntityDisplay { +) : AudienceFilter(instanceEntryRef), TickableDisplay, ActivityEntityDisplay { private val activityManagers = ConcurrentHashMap>() private val entities = ConcurrentHashMap() @@ -34,7 +34,7 @@ class GroupActivityEntityDisplay( val groupId = group.groupId(player) ?: GroupId(player.uniqueId) activityManagers.computeIfAbsent(groupId) { val viewers = groupViewers(groupId) - val context = SharedActivityContext(ref, viewers) + val context = SharedActivityContext(instanceEntryRef, viewers) val activity = activityCreators.create(context, spawnPosition.toProperty()) val activityManager = ActivityManager(activity) activityManager.initialize(context) @@ -66,7 +66,7 @@ class GroupActivityEntityDisplay( val viewerId = viewers.firstOrNull()?.uniqueId val entityState = if (viewerId != null) entities[viewerId]?.state ?: EntityState() else EntityState() - val context = SharedActivityContext(ref, viewers, entityState) + val context = SharedActivityContext(instanceEntryRef, viewers, entityState) manager.tick(context) } @@ -83,7 +83,7 @@ class GroupActivityEntityDisplay( val groupId = group.groupId(player) ?: GroupId(player.uniqueId) // If no players are considered for this group, we can remove the activity manager if (consideredPlayers.none { groupId == group.groupId(it) }) { - activityManagers.remove(groupId)?.dispose(SharedActivityContext(ref, emptyList())) + activityManagers.remove(groupId)?.dispose(SharedActivityContext(instanceEntryRef, emptyList())) } } @@ -92,7 +92,7 @@ class GroupActivityEntityDisplay( entities.values.forEach { it.dispose() } entities.clear() activityManagers.forEach { (groupId, manager) -> - manager.dispose(SharedActivityContext(ref, groupViewers(groupId))) + manager.dispose(SharedActivityContext(instanceEntryRef, groupViewers(groupId))) } activityManagers.clear() } @@ -106,6 +106,7 @@ class GroupActivityEntityDisplay( val groupId = group.groupId(player) ?: GroupId(player.uniqueId) return activityManagers[groupId]?.position } + override fun entityState(playerId: UUID): EntityState = entities[playerId]?.state ?: EntityState() override fun canView(playerId: UUID): Boolean = canConsider(playerId) diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/IndividualActivityEntityDisplay.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/IndividualActivityEntityDisplay.kt index b6e6e2e8d7..6ab37f2ba4 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/IndividualActivityEntityDisplay.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/IndividualActivityEntityDisplay.kt @@ -1,23 +1,23 @@ package com.typewritermc.engine.paper.entry.entity -import lirand.api.extensions.server.server import com.typewritermc.core.entries.Ref import com.typewritermc.core.utils.point.Position import com.typewritermc.engine.paper.entry.entries.AudienceFilter import com.typewritermc.engine.paper.entry.entries.EntityInstanceEntry import com.typewritermc.engine.paper.entry.entries.PropertySupplier import com.typewritermc.engine.paper.entry.entries.TickableDisplay +import lirand.api.extensions.server.server import org.bukkit.entity.Player import java.util.* import java.util.concurrent.ConcurrentHashMap class IndividualActivityEntityDisplay( - private val ref: Ref, + override val instanceEntryRef: Ref, override val creator: EntityCreator, private val activityCreator: ActivityCreator, private val suppliers: List, Int>>, private val spawnPosition: Position, -) : AudienceFilter(ref), TickableDisplay, ActivityEntityDisplay { +) : AudienceFilter(instanceEntryRef), TickableDisplay, ActivityEntityDisplay { private val activityManagers = ConcurrentHashMap>() private val entities = ConcurrentHashMap() @@ -30,7 +30,7 @@ class IndividualActivityEntityDisplay( override fun onPlayerAdd(player: Player) { activityManagers.computeIfAbsent(player.uniqueId) { - val context = IndividualActivityContext(ref, player) + val context = IndividualActivityContext(instanceEntryRef, player) val activity = activityCreator.create(context, spawnPosition.toProperty()) val activityManager = ActivityManager(activity) activityManager.initialize(context) @@ -54,7 +54,7 @@ class IndividualActivityEntityDisplay( val player = server.getPlayer(pid) ?: return@forEach val isViewing = pid in this val entityState = entities[pid]?.state ?: EntityState() - manager.tick(IndividualActivityContext(ref, player, isViewing, entityState)) + manager.tick(IndividualActivityContext(instanceEntryRef, player, isViewing, entityState)) } entities.values.forEach { it.tick() } } @@ -66,7 +66,7 @@ class IndividualActivityEntityDisplay( override fun onPlayerRemove(player: Player) { super.onPlayerRemove(player) - activityManagers.remove(player.uniqueId)?.dispose(IndividualActivityContext(ref, player)) + activityManagers.remove(player.uniqueId)?.dispose(IndividualActivityContext(instanceEntryRef, player)) } override fun dispose() { @@ -74,7 +74,12 @@ class IndividualActivityEntityDisplay( entities.values.forEach { it.dispose() } entities.clear() activityManagers.entries.forEach { (playerId, activityManager) -> - activityManager.dispose(IndividualActivityContext(ref, server.getPlayer(playerId) ?: return@forEach)) + activityManager.dispose( + IndividualActivityContext( + instanceEntryRef, + server.getPlayer(playerId) ?: return@forEach + ) + ) } activityManagers.clear() } @@ -84,6 +89,7 @@ class IndividualActivityEntityDisplay( } override fun position(playerId: UUID): Position? = activityManagers[playerId]?.position + override fun entityState(playerId: UUID): EntityState = entities[playerId]?.state ?: EntityState() override fun canView(playerId: UUID): Boolean = canConsider(playerId) override fun entityId(playerId: UUID): Int { diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/SharedActivityEntityDisplay.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/SharedActivityEntityDisplay.kt index 1e78859249..2d8d9d653f 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/SharedActivityEntityDisplay.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/entry/entity/SharedActivityEntityDisplay.kt @@ -7,7 +7,6 @@ import com.typewritermc.engine.paper.entry.entries.EntityInstanceEntry import com.typewritermc.engine.paper.entry.entries.PropertySupplier import com.typewritermc.engine.paper.entry.entries.TickableDisplay import com.typewritermc.engine.paper.utils.config -import org.bukkit.Location import org.bukkit.entity.Player import java.util.* import java.util.concurrent.ConcurrentHashMap @@ -15,12 +14,12 @@ import java.util.concurrent.ConcurrentHashMap val entityShowRange by config("entity.show-range", 50.0, "The range at which entities are shown") class SharedActivityEntityDisplay( - private val ref: Ref, + override val instanceEntryRef: Ref, override val creator: EntityCreator, private val activityCreators: ActivityCreator, private val suppliers: List, Int>>, private val spawnPosition: Position, -) : AudienceFilter(ref), TickableDisplay, ActivityEntityDisplay { +) : AudienceFilter(instanceEntryRef), TickableDisplay, ActivityEntityDisplay { private var activityManager: ActivityManager? = null private val entities = ConcurrentHashMap() @@ -32,7 +31,7 @@ class SharedActivityEntityDisplay( override fun initialize() { super.initialize() - val context = SharedActivityContext(ref, players) + val context = SharedActivityContext(instanceEntryRef, players) activityManager = ActivityManager(activityCreators.create(context, spawnPosition.toProperty())) activityManager?.initialize(context) @@ -54,7 +53,7 @@ class SharedActivityEntityDisplay( // But there is no real solution to this. // So we pick the first entity's state and use to try and keep the state consistent. val entityState = entities.values.firstOrNull()?.state ?: EntityState() - activityManager?.tick(SharedActivityContext(ref, players, entityState)) + activityManager?.tick(SharedActivityContext(instanceEntryRef, players, entityState)) entities.values.forEach { it.tick() } } @@ -67,7 +66,7 @@ class SharedActivityEntityDisplay( super.dispose() entities.values.forEach { it.dispose() } entities.clear() - activityManager?.dispose(SharedActivityContext(ref, players)) + activityManager?.dispose(SharedActivityContext(instanceEntryRef, players)) activityManager = null } @@ -76,7 +75,7 @@ class SharedActivityEntityDisplay( } override fun position(playerId: UUID): Position? = activityManager?.position - + override fun entityState(playerId: UUID): EntityState = entities[playerId]?.state ?: EntityState() override fun canView(playerId: UUID): Boolean = canConsider(playerId) override fun entityId(playerId: UUID): Int { diff --git a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/events/AsyncEntityDefinitionInteract.kt b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/events/AsyncEntityDefinitionInteract.kt index 1259979d5d..1fdc93857a 100644 --- a/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/events/AsyncEntityDefinitionInteract.kt +++ b/engine/engine-paper/src/main/kotlin/com/typewritermc/engine/paper/events/AsyncEntityDefinitionInteract.kt @@ -3,6 +3,7 @@ package com.typewritermc.engine.paper.events import com.github.retrooper.packetevents.protocol.player.InteractionHand import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity.InteractAction import com.typewritermc.engine.paper.entry.entries.EntityDefinitionEntry +import com.typewritermc.engine.paper.entry.entries.EntityInstanceEntry import org.bukkit.entity.Player import org.bukkit.event.HandlerList import org.bukkit.event.player.PlayerEvent @@ -28,6 +29,7 @@ class AsyncEntityDefinitionInteract( player: Player, val entityId: Int, val definition: EntityDefinitionEntry, + val instance: EntityInstanceEntry, val hand: InteractionHand, val action: InteractAction, ) : PlayerEvent(player, true) { diff --git a/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/activity/LookCloseActivity.kt b/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/activity/LookCloseActivity.kt index 4d20806522..137d772646 100644 --- a/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/activity/LookCloseActivity.kt +++ b/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/activity/LookCloseActivity.kt @@ -7,7 +7,6 @@ import com.typewritermc.engine.paper.entry.entity.* import com.typewritermc.engine.paper.entry.entries.GenericEntityActivityEntry import com.typewritermc.engine.paper.snippets.snippet import com.typewritermc.engine.paper.utils.isLookable -import org.bukkit.GameMode import org.bukkit.entity.Player import kotlin.math.abs import kotlin.math.atan2 @@ -144,6 +143,10 @@ fun updateLookDirection( return yaw to pitch } +fun normalizeYaw(yaw: Float): Float { + return (yaw + 180) % 360 - 180 +} + class Velocity(var value: Float) fun smoothDamp( diff --git a/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/bound/LookAtEntityInteractionBoundEntry.kt b/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/bound/LookAtEntityInteractionBoundEntry.kt new file mode 100644 index 0000000000..422de375c4 --- /dev/null +++ b/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/bound/LookAtEntityInteractionBoundEntry.kt @@ -0,0 +1,194 @@ +package com.typewritermc.entity.entries.bound + +import com.typewritermc.core.books.pages.Colors +import com.typewritermc.core.entries.Ref +import com.typewritermc.core.entries.emptyRef +import com.typewritermc.core.entries.priority +import com.typewritermc.core.extension.annotations.Default +import com.typewritermc.core.extension.annotations.Entry +import com.typewritermc.core.extension.annotations.Help +import com.typewritermc.core.interaction.InteractionBound +import com.typewritermc.core.utils.point.toVector +import com.typewritermc.engine.paper.entry.* +import com.typewritermc.engine.paper.entry.entity.ActivityEntityDisplay +import com.typewritermc.engine.paper.entry.entries.EntityInstanceEntry +import com.typewritermc.engine.paper.interaction.ListenerInteractionBound +import com.typewritermc.engine.paper.interaction.interactionContext +import com.typewritermc.engine.paper.plugin +import com.typewritermc.engine.paper.utils.distanceSqrt +import com.typewritermc.engine.paper.utils.toPosition +import com.typewritermc.entity.entries.activity.* +import com.typewritermc.entity.entries.event.InteractingEntityInstance +import org.bukkit.NamespacedKey +import org.bukkit.attribute.Attribute +import org.bukkit.attribute.AttributeModifier +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.player.PlayerMoveEvent +import org.bukkit.event.player.PlayerTeleportEvent +import org.koin.java.KoinJavaComponent.get +import java.time.Duration +import java.time.Instant +import kotlin.math.abs + + +@Entry( + "look_at_entity_interaction_bound", + "An interaction which forces the player to look at an entity", + Colors.MEDIUM_PURPLE, + "mingcute:look-up-fill" +) +class LookAtEntityInteractionBoundEntry( + override val id: String = "", + override val name: String = "", + override val criteria: List = emptyList(), + override val modifiers: List = emptyList(), + override val triggers: List> = emptyList(), + @Default("2.0") + val radius: Double = 2.0, + @Help("If left empty, the entity where they interacted with will be used.") + val npc: Ref = emptyRef(), +) : InteractionBoundEntry { + override fun build(player: Player): InteractionBound = LookAtNpcInteractionBound(player, radius, npc, priority) +} + +class LookAtNpcInteractionBound( + private val player: Player, + private val radius: Double, + private val instanceEntryRef: Ref, + override val priority: Int, +) : ListenerInteractionBound { + private val startLocation = player.location + private val key = NamespacedKey.fromString("zoom", plugin)!! + + override fun initialize() { + super.initialize() + updateZoom(0.0) + } + + private fun updateZoom(distance: Double) { + val zoom = calculateZoom(distance) + val modifier = AttributeModifier(key, zoom, AttributeModifier.Operation.MULTIPLY_SCALAR_1) + + player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED)?.let { attribute -> + attribute.removeModifier(key) + + attribute.addModifier(modifier) + } + } + + private fun calculateZoom(distance: Double): Double { + val minZoom = -0.6 + val maxZoom = 0.0 + + val normalizedDistance = (distance / (radius * radius)).coerceIn(0.0, 1.0) + val zoomRange = maxZoom - minZoom + + val t = 1 - normalizedDistance + return minZoom + ((1 - (t * t * t * t)) * zoomRange) + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private fun onMove(event: PlayerMoveEvent) { + if (event.player.uniqueId != player.uniqueId) return + val location = event.to + val distance = location.distanceSqrt(startLocation) ?: Double.MAX_VALUE + + updateZoom(distance) + if (distance < radius * radius) return + + handleEvent(event) + } + + @EventHandler + private fun onTeleport(event: PlayerTeleportEvent) { + onMove(event) + } + + private val yawVelocity = Velocity(0f) + private val pitchVelocity = Velocity(0f) + + private var state: AnimationState = AnimationState.Animating + private val animationThreshold = 0.5f + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private fun onLook(event: PlayerMoveEvent) { + if (event.player.uniqueId != player.uniqueId) return + if (!event.hasChangedOrientation() && !event.hasExplicitlyChangedPosition()) return + if (state.isAnimating()) return + + state = AnimationState.Moved(Instant.now()) + } + + override fun tick() { + super.tick() + state = state.transition() + if (!state.isAnimating()) return + + val context = player.interactionContext ?: return + val ref = + if (instanceEntryRef.isSet) instanceEntryRef + else context[InteractingEntityInstance] as? Ref + ?: return + + val display = get(AudienceManager::class.java)[ref] as? ActivityEntityDisplay ?: return + + val entityState = display.entityState(player.uniqueId) + val position = display.position(player.uniqueId) + val target = position?.add(0.0, entityState.eyeHeight, 0.0) ?: return + + val playerEyePosition = player.eyeLocation.toPosition() + val direction = target.toVector() + .minus(playerEyePosition) + .normalize() + + val targetYaw = getLookYaw(direction.x, direction.z) + val targetPitch = getLookPitch(direction.x, direction.y, direction.z) + + val (newYaw, newPitch) = updateLookDirection( + LookDirection(playerEyePosition.yaw, playerEyePosition.pitch), + LookDirection(targetYaw, targetPitch), + yawVelocity, + pitchVelocity, + smoothTime = 0.20f + ) + + player.teleportAsync(player.location.clone().apply { + yaw = newYaw + pitch = newPitch + }) + val yawDiff = abs(normalizeYaw(targetYaw - newYaw)) + val pitchDiff = abs(targetPitch - newPitch) + + if (yawDiff < animationThreshold && pitchDiff < animationThreshold) { + state = AnimationState.Idle + yawVelocity.value = 0f + pitchVelocity.value = 0f + } + } + + override fun teardown() { + player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED)?.removeModifier(key) + super.teardown() + } +} + +private sealed interface AnimationState { + fun isAnimating(): Boolean = this is Animating + + fun transition(): AnimationState + + data object Idle : AnimationState { + override fun transition(): AnimationState = this + } + + data class Moved(val lastMove: Instant) : AnimationState { + fun canAnimate(): Boolean = Duration.between(lastMove, Instant.now()).toMillis() > 500 + override fun transition(): AnimationState = if (canAnimate()) Animating else this + } + + data object Animating : AnimationState { + override fun transition(): AnimationState = this + } +} \ No newline at end of file diff --git a/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/event/EntityInteractEventEntry.kt b/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/event/EntityInteractEventEntry.kt index c7e3b51af4..e696c170e9 100644 --- a/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/event/EntityInteractEventEntry.kt +++ b/extensions/EntityExtension/src/main/kotlin/com/typewritermc/entity/entries/event/EntityInteractEventEntry.kt @@ -5,15 +5,16 @@ import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientIn import com.typewritermc.core.books.pages.Colors import com.typewritermc.core.entries.Query import com.typewritermc.core.entries.Ref -import com.typewritermc.engine.paper.entry.TriggerableEntry import com.typewritermc.core.entries.emptyRef import com.typewritermc.core.entries.ref import com.typewritermc.core.extension.annotations.Entry import com.typewritermc.core.extension.annotations.EntryListener +import com.typewritermc.core.interaction.GlobalContextKey import com.typewritermc.core.interaction.context -import com.typewritermc.engine.paper.entry.* +import com.typewritermc.engine.paper.entry.TriggerableEntry import com.typewritermc.engine.paper.entry.entries.EntityDefinitionEntry import com.typewritermc.engine.paper.entry.entries.EventEntry +import com.typewritermc.engine.paper.entry.startDialogueWithOrNextDialogue import com.typewritermc.engine.paper.events.AsyncEntityDefinitionInteract @Entry( @@ -39,5 +40,11 @@ class EntityInteractEventEntry( fun onEntityInteract(event: AsyncEntityDefinitionInteract, query: Query) { if (event.hand != InteractionHand.MAIN_HAND || event.action == WrapperPlayClientInteractEntity.InteractAction.INTERACT_AT) return val definition = event.definition.ref() - query.findWhere {it.definition == definition }.startDialogueWithOrNextDialogue(event.player, context()) -} \ No newline at end of file + + query.findWhere { it.definition == definition }.startDialogueWithOrNextDialogue(event.player, context { + val instance = event.instance + InteractingEntityInstance withValue instance.ref() + }) +} + +object InteractingEntityInstance : GlobalContextKey>(Ref::class)