From 65d05d40b68869b5f410c83494c0552b2d50dcad Mon Sep 17 00:00:00 2001 From: Boy Date: Sat, 26 Oct 2024 15:58:01 +0200 Subject: [PATCH] fix: ensure section-transition chunk is loaded & use chunk-ticket whilst teleport is running --- .../BedrockBlockingInvalidTeleportHandler.kt | 7 +++- .../movement/EmptyTeleportHandler.kt | 7 ++++ .../movement/InvalidTeleportHandler.kt | 5 ++- .../deeperworld/movement/MovementHandler.kt | 36 ++++-------------- .../movement/TransitionTeleportHandler.kt | 37 +++++++++++++++---- .../UndoMovementInvalidTeleportHandler.kt | 5 ++- 6 files changed, 54 insertions(+), 43 deletions(-) create mode 100644 src/main/kotlin/com/mineinabyss/deeperworld/movement/EmptyTeleportHandler.kt diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/BedrockBlockingInvalidTeleportHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/BedrockBlockingInvalidTeleportHandler.kt index d41227b..7aea398 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/BedrockBlockingInvalidTeleportHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/BedrockBlockingInvalidTeleportHandler.kt @@ -3,15 +3,18 @@ package com.mineinabyss.deeperworld.movement import com.github.shynixn.mccoroutine.bukkit.launch import com.mineinabyss.deeperworld.deeperWorld import com.mineinabyss.deeperworld.listeners.MovementListener +import com.mineinabyss.deeperworld.movement.transition.SectionTransition import com.mineinabyss.idofront.location.up import com.mineinabyss.idofront.time.ticks import kotlinx.coroutines.delay import org.bukkit.Location import org.bukkit.Material +import org.bukkit.entity.Entity import org.bukkit.entity.Player -class BedrockBlockingInvalidTeleportHandler(player: Player, from: Location, to: Location) : - InvalidTeleportHandler(player, from, to) { +class BedrockBlockingInvalidTeleportHandler(player: Player, from: Location, to: Location) : InvalidTeleportHandler(player, from, to) { + + constructor(player: Player, transition: SectionTransition) : this(player, transition.from, transition.to) override fun handleInvalidTeleport() { from.block.type = Material.BEDROCK diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/EmptyTeleportHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/EmptyTeleportHandler.kt new file mode 100644 index 0000000..909636f --- /dev/null +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/EmptyTeleportHandler.kt @@ -0,0 +1,7 @@ +package com.mineinabyss.deeperworld.movement + +object EmptyTeleportHandler : TeleportHandler { + + override fun handleTeleport() {} + override fun isValidTeleport() = true +} \ No newline at end of file diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/InvalidTeleportHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/InvalidTeleportHandler.kt index 43f6540..7700640 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/InvalidTeleportHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/InvalidTeleportHandler.kt @@ -1,11 +1,12 @@ package com.mineinabyss.deeperworld.movement +import com.mineinabyss.deeperworld.movement.transition.SectionTransition import com.mineinabyss.idofront.messaging.error import org.bukkit.Location import org.bukkit.entity.Player -abstract class InvalidTeleportHandler(val player: Player, val from: Location, val to: Location) : - TeleportHandler { +abstract class InvalidTeleportHandler(val player: Player, val from: Location, val to: Location) : TeleportHandler { + constructor(player: Player, transition: SectionTransition) : this(player, transition.from, transition.to) final override fun handleTeleport() { handleInvalidTeleport() player.error("There is no where for you to teleport") diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt index fbb854a..8395179 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt @@ -56,36 +56,14 @@ object MovementHandler { } } - - private fun getTeleportHandler( - player: Player, - sectionTransition: SectionTransition - ): TeleportHandler { - if (sectionTransition.teleportUnnecessary || player.uniqueId in teleportCooldown) return object : TeleportHandler { - override fun handleTeleport() {} - - override fun isValidTeleport() = true - } - - val teleportEntity = player.vehicle ?: player - teleportCooldown += teleportEntity.uniqueId - - if (player.gameMode != GameMode.SPECTATOR && sectionTransition.to.block.isSolid) { - return if (sectionTransition.kind == TransitionKind.ASCEND) { - UndoMovementInvalidTeleportHandler( - player, - sectionTransition.from, - sectionTransition.to - ) - } else { - BedrockBlockingInvalidTeleportHandler( - player, - sectionTransition.from, - sectionTransition.to - ) + private fun getTeleportHandler(player: Player, sectionTransition: SectionTransition): TeleportHandler { + return when { + sectionTransition.teleportUnnecessary || player.uniqueId in teleportCooldown -> EmptyTeleportHandler + player.gameMode != GameMode.SPECTATOR && sectionTransition.to.block.isSolid -> when (sectionTransition.kind) { + TransitionKind.ASCEND -> UndoMovementInvalidTeleportHandler(player, sectionTransition) + else -> BedrockBlockingInvalidTeleportHandler(player, sectionTransition) } + else -> TransitionTeleportHandler(player.vehicle ?: player, sectionTransition) } - - return TransitionTeleportHandler(teleportEntity, sectionTransition.from, sectionTransition.to) } } diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/TransitionTeleportHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/TransitionTeleportHandler.kt index 1103363..c24b18f 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/TransitionTeleportHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/TransitionTeleportHandler.kt @@ -2,10 +2,12 @@ package com.mineinabyss.deeperworld.movement import com.github.shynixn.mccoroutine.bukkit.launch import com.mineinabyss.deeperworld.deeperWorld +import com.mineinabyss.deeperworld.movement.transition.SectionTransition import com.mineinabyss.idofront.time.ticks import io.papermc.paper.entity.TeleportFlag import kotlinx.coroutines.delay import kotlinx.coroutines.future.asDeferred +import kotlinx.coroutines.future.await import org.bukkit.Location import org.bukkit.entity.Entity import org.bukkit.entity.LivingEntity @@ -14,11 +16,26 @@ import org.bukkit.event.player.PlayerTeleportEvent class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location, val to: Location) : TeleportHandler { + constructor(teleportEntity: Entity, transition: SectionTransition) : this(teleportEntity, transition.from, transition.to) + + init { + MovementHandler.teleportCooldown += teleportEntity.uniqueId + } + + private val teleportFlags: Array = listOf( + TeleportFlag.Relative.YAW, + TeleportFlag.Relative.PITCH, + TeleportFlag.Relative.X, + TeleportFlag.Relative.Y, + TeleportFlag.Relative.Z, + TeleportFlag.EntityState.RETAIN_PASSENGERS, + TeleportFlag.EntityState.RETAIN_VEHICLE + ).toTypedArray() + override fun handleTeleport() { val oldLeashedEntities = leashedEntities() val spectators = spectatorEntities() val oldVelocity = teleportEntity.velocity - val teleportFlags: Array = listOf(TeleportFlag.Relative.YAW, TeleportFlag.Relative.PITCH, TeleportFlag.Relative.X, TeleportFlag.Relative.Y, TeleportFlag.Relative.Z, TeleportFlag.EntityState.RETAIN_PASSENGERS, TeleportFlag.EntityState.RETAIN_VEHICLE).toTypedArray() // Unleash all the leashed entities before teleporting them, to prevent leads from dropping. // The leashes are restored after teleportation. @@ -26,22 +43,24 @@ class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location, spectators.values.flatten().forEach { it.spectatorTarget = null } deeperWorld.plugin.launch { - teleportEntity.teleportAsync(to, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() + to.world.getChunkAtAsync(to).await().addPluginChunkTicket(deeperWorld.plugin) + teleportEntity.teleportAsync(to, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).await() teleportEntity.velocity = oldVelocity oldLeashedEntities.forEach { (leashHolder, leashEntities) -> leashEntities.forEach { - it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() + it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).await() it.setLeashHolder(leashHolder) } } spectators.forEach { (spectatorTarget, spectators) -> spectators.forEach { - it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() + it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).await() it.spectatorTarget = spectatorTarget } } delay(10.ticks) + to.chunk.removePluginChunkTicket(deeperWorld.plugin) MovementHandler.teleportCooldown -= teleportEntity.uniqueId } } @@ -62,9 +81,10 @@ class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location, private fun leashedEntities(): Map> { // Max leashed entity range is 10 blocks, therefore these parameter values return when (teleportEntity) { - is Player -> mapOf(teleportEntity to teleportEntity.location - .getNearbyEntitiesByType(LivingEntity::class.java, 20.0) - .filter { it.isLeashed && it.leashHolder.uniqueId == teleportEntity.uniqueId }) + is Player -> mapOf( + teleportEntity to teleportEntity.location + .getNearbyEntitiesByType(LivingEntity::class.java, 20.0) + .filter { it.isLeashed && it.leashHolder.uniqueId == teleportEntity.uniqueId }) else -> teleportEntity.passengers.filterIsInstance().associateWith { it.location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0) @@ -74,6 +94,7 @@ class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location, } private fun Entity.recursiveLeashEntities(): List { - return location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0).filter { it.isLeashed && it.leashHolder.uniqueId == this.uniqueId } + return location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0) + .filter { it.isLeashed && it.leashHolder.uniqueId == this.uniqueId } } } diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/UndoMovementInvalidTeleportHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/UndoMovementInvalidTeleportHandler.kt index 3086ac3..8902389 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/UndoMovementInvalidTeleportHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/UndoMovementInvalidTeleportHandler.kt @@ -1,10 +1,11 @@ package com.mineinabyss.deeperworld.movement +import com.mineinabyss.deeperworld.movement.transition.SectionTransition import org.bukkit.Location import org.bukkit.entity.Player -class UndoMovementInvalidTeleportHandler(player: Player, from: Location, to: Location) : - InvalidTeleportHandler(player, from, to) { +class UndoMovementInvalidTeleportHandler(player: Player, from: Location, to: Location) : InvalidTeleportHandler(player, from, to) { + constructor(player: Player, transition: SectionTransition) : this(player, transition.from, transition.to) override fun handleInvalidTeleport() { player.teleport(from) }