Skip to content

Commit

Permalink
fix: ensure section-transition chunk is loaded & use chunk-ticket whi…
Browse files Browse the repository at this point in the history
…lst teleport is running
  • Loading branch information
Boy0000 committed Oct 26, 2024
1 parent be6c8b3 commit 65d05d4
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.mineinabyss.deeperworld.movement

object EmptyTeleportHandler : TeleportHandler {

override fun handleTeleport() {}
override fun isValidTeleport() = true
}
Original file line number Diff line number Diff line change
@@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -14,34 +16,51 @@ 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<TeleportFlag> = 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<TeleportFlag> = 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.
oldLeashedEntities.values.flatten().forEach { it.setLeashHolder(null) }
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
}
}
Expand All @@ -62,9 +81,10 @@ class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location,
private fun leashedEntities(): Map<LivingEntity, List<LivingEntity>> {
// 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<LivingEntity>().associateWith {
it.location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0)
Expand All @@ -74,6 +94,7 @@ class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location,
}

private fun Entity.recursiveLeashEntities(): List<LivingEntity> {
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 }
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
Expand Down

0 comments on commit 65d05d4

Please sign in to comment.