diff --git a/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt b/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt index 11ad813..fbb854a 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/MovementHandler.kt @@ -67,7 +67,8 @@ object MovementHandler { override fun isValidTeleport() = true } - teleportCooldown += player.uniqueId + val teleportEntity = player.vehicle ?: player + teleportCooldown += teleportEntity.uniqueId if (player.gameMode != GameMode.SPECTATOR && sectionTransition.to.block.isSolid) { return if (sectionTransition.kind == TransitionKind.ASCEND) { @@ -85,6 +86,6 @@ object MovementHandler { } } - return TransitionTeleportHandler(player, sectionTransition.from, sectionTransition.to) + 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 82ae886..1103363 100644 --- a/src/main/kotlin/com/mineinabyss/deeperworld/movement/TransitionTeleportHandler.kt +++ b/src/main/kotlin/com/mineinabyss/deeperworld/movement/TransitionTeleportHandler.kt @@ -7,35 +7,42 @@ import io.papermc.paper.entity.TeleportFlag import kotlinx.coroutines.delay import kotlinx.coroutines.future.asDeferred import org.bukkit.Location +import org.bukkit.entity.Entity import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerTeleportEvent -class TransitionTeleportHandler(val player: Player, val from: Location, val to: Location) : TeleportHandler { +class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location, val to: Location) : TeleportHandler { override fun handleTeleport() { - val oldLeashedEntities = player.getLeashedEntities() - val spectators = player.world.players.filter { it.spectatorTarget?.uniqueId == player.uniqueId } + 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. - for (it in oldLeashedEntities) it.setLeashHolder(null) - for (it in spectators) it.spectatorTarget = null + oldLeashedEntities.values.flatten().forEach { it.setLeashHolder(null) } + spectators.values.flatten().forEach { it.spectatorTarget = null } deeperWorld.plugin.launch { - player.teleportAsync(to, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() - oldLeashedEntities.forEach { leashEntity -> - leashEntity.teleportAsync(player.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() - leashEntity.setLeashHolder(player) + teleportEntity.teleportAsync(to, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() + teleportEntity.velocity = oldVelocity + oldLeashedEntities.forEach { (leashHolder, leashEntities) -> + leashEntities.forEach { + it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() + it.setLeashHolder(leashHolder) + } } - spectators.forEach { spectator -> - spectator.teleportAsync(player.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() - spectator.spectatorTarget = player + spectators.forEach { (spectatorTarget, spectators) -> + spectators.forEach { + it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await() + it.spectatorTarget = spectatorTarget + } } delay(10.ticks) - MovementHandler.teleportCooldown -= player.uniqueId + MovementHandler.teleportCooldown -= teleportEntity.uniqueId } } @@ -43,9 +50,30 @@ class TransitionTeleportHandler(val player: Player, val from: Location, val to: return true } - private fun Player.getLeashedEntities(): List { + private fun spectatorEntities(): Map> { + return when (teleportEntity) { + is Player -> mapOf(teleportEntity to teleportEntity.world.players.filter { it.spectatorTarget?.uniqueId == teleportEntity.uniqueId }) + else -> teleportEntity.passengers.associateWith { p -> + p.world.players.filter { it.spectatorTarget?.uniqueId == p.uniqueId } + } + } + } + + private fun leashedEntities(): Map> { // Max leashed entity range is 10 blocks, therefore these parameter values - return location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0) - .filter { it.isLeashed && it.leashHolder.uniqueId == this.uniqueId } + return when (teleportEntity) { + 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) + .filter { it.isLeashed && it.leashHolder.uniqueId == teleportEntity.uniqueId } + } + } + } + + private fun Entity.recursiveLeashEntities(): List { + return location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0).filter { it.isLeashed && it.leashHolder.uniqueId == this.uniqueId } } }