Skip to content

Commit

Permalink
feat(unfinished): support syncing entities between sections without p…
Browse files Browse the repository at this point in the history
…layers
  • Loading branch information
Boy0000 committed Oct 18, 2024
1 parent be6c8b3 commit 1423829
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ object MovementListener : Listener {

@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
fun VehicleMoveEvent.move() {
val players = vehicle.getPassengersRecursive().filterIsInstance<Player>()
vehicle.getPassengersRecursive().filterIsInstance<Player>()
.filterNot { it.hasPermission(Permissions.ADMIN_PERMISSION) && it.canMoveSections }
.forEach { it.leaveVehicle() }

players.firstOrNull { it.hasPermission(Permissions.ADMIN_PERMISSION) && it.canMoveSections }?.let {
MovementHandler.handleMovement(it, from, to)
}
MovementHandler.handleMovement(vehicle, from, to)
}

@EventHandler
fun EntityMoveEvent.entityMove() {
if (!hasExplicitlyChangedPosition()) return
if (entity.getPassengersRecursive().isEmpty()) return
entity.getPassengersRecursive().filterIsInstance<Player>()
.filter { rider -> rider.hasPermission(Permissions.ADMIN_PERMISSION) && rider.canMoveSections }
.forEach { MovementHandler.handleMovement(it, from, to) }
//if (!hasExplicitlyChangedPosition()) return
//if (entity.getPassengersRecursive().isEmpty()) return
//entity.getPassengersRecursive().filterIsInstance<Player>()
// .filter { rider -> rider.hasPermission(Permissions.ADMIN_PERMISSION) && rider.canMoveSections }
// .forEach { MovementHandler.handleMovement(it, from, to) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ 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(override val entity: Entity, from: Location, to: Location) :
InvalidTeleportHandler(from, to) {
override fun handleInvalidTeleport() {
from.block.type = Material.BEDROCK

Expand All @@ -29,12 +30,12 @@ class BedrockBlockingInvalidTeleportHandler(player: Player, from: Location, to:
MovementListener.temporaryBedrock.remove(spawnedBedrock)
}

val oldFallDistance = player.fallDistance
val oldVelocity = player.velocity
val oldFallDistance = entity.fallDistance
val oldVelocity = entity.velocity

player.teleport(from.up(1))
entity.teleport(from.up(1))

player.fallDistance = oldFallDistance
player.velocity = oldVelocity
entity.fallDistance = oldFallDistance
entity.velocity = oldVelocity
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ 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) :
abstract class InvalidTeleportHandler(val from: Location, val to: Location) :
TeleportHandler {
final override fun handleTeleport() {
handleInvalidTeleport()
player.error("There is no where for you to teleport")
entity.error("There is no where for you to teleport")
}

override fun isValidTeleport(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import com.mineinabyss.deeperworld.movement.transition.ConfigSectionChecker
import com.mineinabyss.deeperworld.movement.transition.SectionTransition
import com.mineinabyss.deeperworld.movement.transition.TransitionKind
import com.mineinabyss.deeperworld.movement.transition.toEvent
import com.mineinabyss.deeperworld.world.section.section
import com.mineinabyss.idofront.events.call
import com.mineinabyss.idofront.textcomponents.miniMsg
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.title.Title
import org.bukkit.GameMode
import org.bukkit.Location
import org.bukkit.attribute.Attribute
import org.bukkit.entity.Entity
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
import java.util.*
import kotlin.time.Duration.Companion.seconds
Expand All @@ -21,15 +24,25 @@ 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()
fun handleMovement(entity: Entity, from: Location, to: Location) {
if (sectionCheckers.any { it.inSection(entity) }) {
sectionCheckers.firstNotNullOfOrNull { it.checkForTransition(entity, from, to) }?.let {
val handler = getTeleportHandler(entity, it)
val entity = handler.entity
when {
entity is Player -> when {
handler.isValidTeleport() -> it.toEvent(entity).call { handler.handleTeleport() }
else -> handler.handleTeleport()
}
else -> {
if (handler.isValidTeleport()) entity.passengers.filterIsInstance<Player>().forEach { p ->
if (!it.toEvent(p).callEvent()) p.leaveVehicle()
}.also { handler.handleTeleport() }
else handler.handleTeleport()
}
}
}
} else player.applyOutOfBoundsDamage()
} else (entity as? Player)?.applyOutOfBoundsDamage()
}

//TODO abstract this away. Should instead do out of bounds action if out of bounds.
Expand Down Expand Up @@ -58,34 +71,25 @@ object MovementHandler {


private fun getTeleportHandler(
player: Player,
entity: Entity,
sectionTransition: SectionTransition
): TeleportHandler {
if (sectionTransition.teleportUnnecessary || player.uniqueId in teleportCooldown) return object : TeleportHandler {
val entity = entity.vehicle ?: entity
if (sectionTransition.teleportUnnecessary || entity.uniqueId in teleportCooldown) return object : TeleportHandler {
override val entity: Entity = entity
override fun handleTeleport() {}

override fun isValidTeleport() = true
override fun isValidTeleport() = false
}
teleportCooldown += entity.uniqueId
teleportCooldown += entity.passengers.map { it.uniqueId }

val teleportEntity = player.vehicle ?: player
teleportCooldown += teleportEntity.uniqueId

if (player.gameMode != GameMode.SPECTATOR && sectionTransition.to.block.isSolid) {
if (entity is LivingEntity && (entity !is Player || entity.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
)
}
UndoMovementInvalidTeleportHandler(entity, sectionTransition.from, sectionTransition.to)
} else BedrockBlockingInvalidTeleportHandler(entity, sectionTransition.from, sectionTransition.to)
}

return TransitionTeleportHandler(teleportEntity, sectionTransition.from, sectionTransition.to)
return TransitionTeleportHandler(entity, sectionTransition.from, sectionTransition.to)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.mineinabyss.deeperworld.movement

import org.bukkit.entity.Entity

interface TeleportHandler {
val entity: Entity
fun handleTeleport()
fun isValidTeleport() : Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
import org.bukkit.event.player.PlayerTeleportEvent

class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location, val to: Location) : TeleportHandler {
class TransitionTeleportHandler(override val entity: Entity, val from: Location, val to: Location) : TeleportHandler {

override fun handleTeleport() {
val oldLeashedEntities = leashedEntities()
val spectators = spectatorEntities()
val oldVelocity = teleportEntity.velocity
val oldVelocity = entity.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.
Expand All @@ -26,23 +26,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()
teleportEntity.velocity = oldVelocity
entity.teleportAsync(to, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await()
oldLeashedEntities.forEach { (leashHolder, leashEntities) ->
leashEntities.forEach {
it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await()
it.teleportAsync(entity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await()
it.setLeashHolder(leashHolder)
}
}
spectators.forEach { (spectatorTarget, spectators) ->
spectators.forEach {
it.teleportAsync(teleportEntity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await()
it.teleportAsync(entity.location, PlayerTeleportEvent.TeleportCause.PLUGIN, *teleportFlags).asDeferred().await()
it.spectatorTarget = spectatorTarget
}
}

delay(10.ticks)
MovementHandler.teleportCooldown -= teleportEntity.uniqueId
entity.velocity = oldVelocity
MovementHandler.teleportCooldown -= entity.uniqueId
MovementHandler.teleportCooldown -= entity.passengers.map { it.uniqueId }.toSet()
}
}

Expand All @@ -51,29 +52,25 @@ class TransitionTeleportHandler(val teleportEntity: Entity, val from: Location,
}

private fun spectatorEntities(): Map<Entity, List<Player>> {
return when (teleportEntity) {
is Player -> mapOf(teleportEntity to teleportEntity.world.players.filter { it.spectatorTarget?.uniqueId == teleportEntity.uniqueId })
else -> teleportEntity.passengers.associateWith { p ->
return when (entity) {
is Player -> mapOf(entity to entity.world.players.filter { it.spectatorTarget?.uniqueId == entity.uniqueId })
else -> entity.passengers.associateWith { p ->
p.world.players.filter { it.spectatorTarget?.uniqueId == p.uniqueId }
}
}
}

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
return when (entity) {
is Player -> mapOf(entity to entity.location
.getNearbyEntitiesByType(LivingEntity::class.java, 20.0)
.filter { it.isLeashed && it.leashHolder.uniqueId == teleportEntity.uniqueId })
.filter { it.isLeashed && it.leashHolder.uniqueId == entity.uniqueId })

else -> teleportEntity.passengers.filterIsInstance<LivingEntity>().associateWith {
else -> entity.passengers.filterIsInstance<LivingEntity>().associateWith {
it.location.getNearbyEntitiesByType(LivingEntity::class.java, 20.0)
.filter { it.isLeashed && it.leashHolder.uniqueId == teleportEntity.uniqueId }
.filter { it.isLeashed && it.leashHolder.uniqueId == entity.uniqueId }
}
}
}

private fun Entity.recursiveLeashEntities(): List<LivingEntity> {
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,11 +1,12 @@
package com.mineinabyss.deeperworld.movement

import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.Player

class UndoMovementInvalidTeleportHandler(player: Player, from: Location, to: Location) :
InvalidTeleportHandler(player, from, to) {
class UndoMovementInvalidTeleportHandler(override val entity: Entity, from: Location, to: Location) :
InvalidTeleportHandler(from, to) {
override fun handleInvalidTeleport() {
player.teleport(from)
entity.teleport(from)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import com.mineinabyss.deeperworld.world.section.correspondingLocation
import com.mineinabyss.deeperworld.world.section.inSectionTransition
import com.mineinabyss.deeperworld.world.section.section
import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.Player

object ConfigSectionChecker : SectionChecker {
override fun inSection(player: Player): Boolean {
return player.location.section != null
override fun inSection(entity: Entity): Boolean {
return entity.location.section != null
}

override fun checkForTransition(
player: Player,
entity: Entity,
from: Location,
to: Location
): SectionTransition? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.mineinabyss.deeperworld.movement.transition

import org.bukkit.Location
import org.bukkit.entity.Entity
import org.bukkit.entity.Player

interface SectionChecker {

fun inSection(player: Player) : Boolean
fun inSection(entity: Entity) : Boolean

fun checkForTransition(
player: Player,
entity: Entity,
from: Location,
to: Location
): SectionTransition?
Expand Down

0 comments on commit 1423829

Please sign in to comment.