Skip to content

Commit

Permalink
refactor: swap away from packets entirely for minecart syncing
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy0000 committed Oct 17, 2024
1 parent e784e4e commit 6ba383d
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ object MovementListener : Listener {

@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
fun PlayerMoveEvent.move() {
if (!hasExplicitlyChangedPosition()) return
if (player.hasPermission(Permissions.ADMIN_PERMISSION) && player.canMoveSections) {
MovementHandler.handleMovement(player, from, to)
}
if (!hasExplicitlyChangedBlock() || !player.hasPermission(Permissions.ADMIN_PERMISSION) || !player.canMoveSections) return
MovementHandler.handleMovement(player, from, to)
}

@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@ object PlayerListener : Listener {
fun PlayerTeleportEvent.onPlayerTeleport() {
if (player.gameMode == CREATIVE || !player.canMoveSections) return
if (cause != ENDER_PEARL && cause != CHORUS_FRUIT) return
if (to.section != null && to.section == player.location.section && !to.inSectionTransition) return

if (
to.section == null ||
to.section != player.location.section ||
to.inSectionTransition
) {
player.error("Teleportation is disabled between Layers and Sections.")
isCancelled = true
}
player.error("Teleportation is disabled between Layers and Sections.")
isCancelled = true
}

@EventHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,23 @@ import org.bukkit.GameMode
import org.bukkit.Location
import org.bukkit.attribute.Attribute
import org.bukkit.entity.Player
import java.util.*
import kotlin.time.Duration.Companion.seconds
import kotlin.time.toJavaDuration

object MovementHandler {
private val sectionCheckers = listOf(ConfigSectionChecker)

val teleportCooldown = mutableSetOf<UUID>()
fun handleMovement(player: Player, from: Location, to: Location) {
if (sectionCheckers.any { it.inSection(player) }) {
sectionCheckers.firstNotNullOfOrNull { it.checkForTransition(player, from, to) }?.let {
with(getTeleportHandler(player, it)) {
if (this.isValidTeleport()) {
it.toEvent(player).call {
this@with.handleTeleport()
}
} else {
this.handleTeleport()
}
if (this.isValidTeleport()) it.toEvent(player).call { this@with.handleTeleport() }
else this.handleTeleport()
}
} ?: return
} else {
player.applyOutOfBoundsDamage()
}
}
} else player.applyOutOfBoundsDamage()
}

//TODO abstract this away. Should instead do out of bounds action if out of bounds.
Expand Down Expand Up @@ -66,11 +61,14 @@ object MovementHandler {
player: Player,
sectionTransition: SectionTransition
): TeleportHandler {
if (sectionTransition.teleportUnnecessary) return object : TeleportHandler {
if (sectionTransition.teleportUnnecessary || player.uniqueId in teleportCooldown) return object : TeleportHandler {
override fun handleTeleport() {}

override fun isValidTeleport() = true
}

teleportCooldown += player.uniqueId

if (player.gameMode != GameMode.SPECTATOR && sectionTransition.to.block.isSolid) {
return if (sectionTransition.kind == TransitionKind.ASCEND) {
UndoMovementInvalidTeleportHandler(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,86 +1,41 @@
package com.mineinabyss.deeperworld.movement

import com.github.shynixn.mccoroutine.bukkit.launch
import com.mineinabyss.deeperworld.datastructures.VehicleTree
import com.mineinabyss.deeperworld.deeperWorld
import com.mineinabyss.deeperworld.extensions.getPassengersRecursive
import com.mineinabyss.deeperworld.extensions.getRootVehicle
import com.mineinabyss.idofront.time.ticks
import io.papermc.paper.entity.TeleportFlag
import kotlinx.coroutines.delay
import kotlinx.coroutines.future.asDeferred
import org.bukkit.Location
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 player: Player, 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 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.forEach {
it.setLeashHolder(null)
}

val rootVehicle = player.getRootVehicle()
if (rootVehicle != null) {
to.yaw = player.location.yaw
to.pitch = player.location.pitch

// Prevent teleportation of other players in the vehicle-passenger structure.
rootVehicle.getPassengersRecursive().filterIsInstance<Player>().forEach {
if (it != player) {
it.vehicle?.removePassenger(it)
}
}

val oldFallDistance = rootVehicle.fallDistance
val oldVelocity = rootVehicle.velocity

val vehicleTree = VehicleTree(rootVehicle)

// Dismount every passenger in the vehicleTree in order to teleport them separately with a delay.
// This avoids the bug of entities not rendering if they are teleported within 1 tick of the player.
vehicleTree.root.applyAll {
it.value.passengers.forEach { passenger ->
it.value.removePassenger(passenger)
}
for (it in oldLeashedEntities) it.setLeashHolder(null)
for (it in spectators) 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)
}

// Delay the teleportation by 1 tick after passenger removal to avoid occasional
// "Removing ticking entity!" exceptions.
deeperWorld.plugin.launch {
delay(1.ticks)

player.teleportWithSpectatorsAsync(to) {
SectionTeleportPacketAdapter(
player,
oldLeashedEntities,
oldFallDistance,
oldVelocity,
vehicleTree
).addPacketListener()
}

spectators.forEach { spectator ->
spectator.teleportAsync(player.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await()
spectator.spectatorTarget = player
}
} else {
val oldFallDistance = player.fallDistance
val oldVelocity = player.velocity

player.teleportWithSpectatorsAsync(to) {
player.fallDistance = oldFallDistance
player.velocity = oldVelocity

if (oldLeashedEntities.isNotEmpty()) {
SectionTeleportPacketAdapter(
player,
oldLeashedEntities,
oldFallDistance,
oldVelocity
).addPacketListener()
}
}
delay(10.ticks)
MovementHandler.teleportCooldown -= player.uniqueId
}
}

Expand All @@ -91,26 +46,6 @@ class TransitionTeleportHandler(val player: Player, val from: Location, val to:
private fun Player.getLeashedEntities(): List<LivingEntity> {
// Max leashed entity range is 10 blocks, therefore these parameter values
return location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0)
.filter { it.isLeashed && it.leashHolder == this }
}

private fun Player.teleportWithSpectatorsAsync(loc: Location, thenRun: (Boolean) -> Unit) {
val nearbySpectators =
location.getNearbyEntitiesByType(Player::class.java, 5.0)
.filter { it.spectatorTarget == this }

nearbySpectators.forEach {
it.spectatorTarget = null
}

teleportAsync(loc).thenAccept { success ->
if (!success) return@thenAccept
nearbySpectators.forEach {
it.teleport(loc)
it.spectatorTarget = this
}
thenRun(success)
}
.filter { it.isLeashed && it.leashHolder.uniqueId == this.uniqueId }
}

}

0 comments on commit 6ba383d

Please sign in to comment.