Skip to content

Commit

Permalink
Update, fix and add more sync stuff (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy0000 authored Jul 22, 2022
1 parent 5d7bcca commit 8b5b801
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.mineinabyss.deeperworld.config.DeeperConfig
import com.mineinabyss.deeperworld.services.WorldManager
import com.mineinabyss.deeperworld.services.canMoveSections
import com.mineinabyss.deeperworld.synchronization.sync
import com.mineinabyss.deeperworld.world.section.correspondingLocation
import com.mineinabyss.deeperworld.world.section.correspondingSection
import com.mineinabyss.deeperworld.world.section.getCorrespondingLocation
import com.mineinabyss.deeperworld.world.section.section
Expand Down Expand Up @@ -43,6 +44,11 @@ class DeeperCommandExecutor : IdofrontCommandExecutor(), TabCompleter {
sender.success("Automatic TP ${if (state) "enabled" else "disabled"} for ${player.name}")
}
}
"tpcorr" {
playerAction {
player.teleport(player.location.correspondingLocation ?: return@playerAction)
}
}
("layerinfo" / "linfo" / "info")(desc = "Gets information about a players section") {
playerAction {
val section = WorldManager.getSectionFor(player.location)
Expand Down Expand Up @@ -106,7 +112,7 @@ class DeeperCommandExecutor : IdofrontCommandExecutor(), TabCompleter {

val region = CuboidRegion(pos1, pos2)
val clipboard = BlockArrayClipboard(region)
val wep = WorldEditPlugin.getInstance().bukkitImplAdapter;
val wep = WorldEditPlugin.getInstance().bukkitImplAdapter
val weWorld: World = wep.adapt(player.world)
val editSession: EditSession = WorldEdit.getInstance().newEditSessionBuilder()
.world(weWorld)
Expand All @@ -121,7 +127,7 @@ class DeeperCommandExecutor : IdofrontCommandExecutor(), TabCompleter {
?: error("Corresponding Location not found")

val offset = if (pos2.y < 0) pos2.y else 0
TaskManager.IMP.taskNowAsync {
TaskManager.taskManager().taskNowAsync {
player.success("Blocks syncing...")
editSession.use { editSession ->
// Copy
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/mineinabyss/deeperworld/Permissions.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.mineinabyss.deeperworld

object Permissions {
const val CHANGE_SECTION_PERMISSION = "deeperworld.changesection"
const val ADMIN_PERMISSION = "deeperworld.admin"
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ object MovementListener : Listener {

@EventHandler(ignoreCancelled = true, priority = EventPriority.LOW)
fun PlayerMoveEvent.move() {
if (player.hasPermission(Permissions.CHANGE_SECTION_PERMISSION) && player.canMoveSections) {
if (player.hasPermission(Permissions.ADMIN_PERMISSION) && player.canMoveSections) {
MovementHandler.handleMovement(player, from, to)
}
}
Expand All @@ -27,7 +27,7 @@ object MovementListener : Listener {
fun VehicleMoveEvent.move() {
val players = vehicle.getPassengersRecursive().filterIsInstance<Player>()

players.firstOrNull { it.hasPermission(Permissions.CHANGE_SECTION_PERMISSION) && it.canMoveSections }?.let {
players.firstOrNull { it.hasPermission(Permissions.ADMIN_PERMISSION) && it.canMoveSections }?.let {
MovementHandler.handleMovement(it, from, to)
}
}
Expand All @@ -36,7 +36,7 @@ object MovementListener : Listener {
fun EntityMoveEvent.entityMove() {
if (entity.getPassengersRecursive().isEmpty()) return
entity.getPassengersRecursive().filterIsInstance<Player>()
.filter { rider -> rider.hasPermission(Permissions.CHANGE_SECTION_PERMISSION) && rider.canMoveSections }
.filter { rider -> rider.hasPermission(Permissions.ADMIN_PERMISSION) && rider.canMoveSections }
.forEach { MovementHandler.handleMovement(it, from, to) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,21 @@ object MovementHandler {
}
} ?: return
} else {
applyOutOfBoundsDamage(player)
player.applyOutOfBoundsDamage()
}
}

//TODO abstract this away. Should instead do out of bounds action if out of bounds.
private fun applyOutOfBoundsDamage(player: Player) {
private fun Player.applyOutOfBoundsDamage() {
if (DeeperConfig.data.damageOutsideSections > 0.0
&& player.location.world !in DeeperConfig.data.damageExcludedWorlds
&& (player.gameMode == GameMode.SURVIVAL || player.gameMode == GameMode.ADVENTURE)
&& player.location.world in (DeeperConfig.data.worlds)
&& location.world !in DeeperConfig.data.damageExcludedWorlds
&& (gameMode == GameMode.SURVIVAL || gameMode == GameMode.ADVENTURE)
&& location.world in (DeeperConfig.data.worlds)
) {
player.damage(0.01) //give a damage effect
player.health = (player.health - DeeperConfig.data.damageOutsideSections / 10)
.coerceIn(
0.0,
player.getAttribute(Attribute.GENERIC_MAX_HEALTH)?.value
) //ignores armor
player.showTitle(
damage(0.01) //give a damage effect
health = (health - DeeperConfig.data.damageOutsideSections / 10)
.coerceIn(0.0, getAttribute(Attribute.GENERIC_MAX_HEALTH)?.value) //ignores armor
showTitle(
Title.title(
"<red>You are not in a managed section".miniMsg(),
"<gray>You will take damage upon moving!".miniMsg(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,13 @@ 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 getNearbyEntities(20.0, 20.0, 20.0)
.filterIsInstance<LivingEntity>()
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 = getNearbyEntities(5.0, 5.0, 5.0)
.filterIsInstance<Player>()
val nearbySpectators =
location.getNearbyEntitiesByType(Player::class.java, 5.0)
.filter { it.spectatorTarget == this }

nearbySpectators.forEach {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,44 @@
package com.mineinabyss.deeperworld.synchronization

import com.mineinabyss.deeperworld.world.section.correspondingSection
import com.mineinabyss.deeperworld.world.section.correspondingLocation
import com.mineinabyss.deeperworld.world.section.inSectionOverlap
import io.papermc.paper.event.block.BlockBreakBlockEvent
import org.bukkit.Material
import org.bukkit.block.Block
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.block.BlockPistonExtendEvent
import org.bukkit.event.block.BlockPistonRetractEvent

object ExploitPreventionListener : Listener {
/** Disables pistons extending if they are in the overlap of two sections */
@EventHandler
fun onPistonExtendEvent(event: BlockPistonExtendEvent) {
//TODO handle pistons properly instead of just cancelling the event
if (event.blocks.any { it.location.correspondingSection != null })
event.isCancelled = true

@EventHandler(ignoreCancelled = true)
fun BlockPistonExtendEvent.onPistonExtendEvent() {
val corrBlock = block.location.correspondingLocation?.block ?: return
val corrBlocks = mutableListOf<Block>()

if (blocks.all { b -> !b.location.inSectionOverlap }) return
if (!corrBlock.location.isChunkLoaded) corrBlock.chunk.load()
corrBlocks.addAll(blocks.map { b -> b.location.correspondingLocation?.block ?: return@map null }.filterNotNull())
BlockPistonExtendEvent(corrBlock, corrBlocks, direction).callEvent()
}

@EventHandler(ignoreCancelled = true)
fun BlockPistonRetractEvent.onPistonRetractEvent() {
val corrBlock = block.location.correspondingLocation?.block ?: return
val corrBlocks = mutableListOf<Block>()

if (blocks.all { b -> !b.location.inSectionOverlap }) return
if (!corrBlock.location.isChunkLoaded) corrBlock.chunk.load()

corrBlocks.addAll(blocks.map { b -> b.location.correspondingLocation?.block ?: return@map null }.filterNotNull())
BlockPistonRetractEvent(corrBlock, corrBlocks, direction).callEvent()
}

/** Disables pistons retracting if they are in the overlap of two sections */
@EventHandler
fun onPistonRetractEvent(event: BlockPistonRetractEvent) {
if (event.blocks.any { it.location.correspondingSection != null })
event.isCancelled = true
fun BlockBreakBlockEvent.onPistonBreakBlock() {
val corrBlock = block.location.correspondingLocation?.block ?: return
source.location.correspondingLocation?.block ?: return
corrBlock.setType(Material.AIR, false)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package com.mineinabyss.deeperworld.synchronization

import com.github.shynixn.mccoroutine.bukkit.launch
import com.mineinabyss.deeperworld.DeeperContext
import com.mineinabyss.deeperworld.deeperWorld
import com.mineinabyss.deeperworld.event.BlockSyncEvent
import com.mineinabyss.deeperworld.event.SyncType
import com.mineinabyss.deeperworld.world.section.correspondingSection
import com.mineinabyss.deeperworld.world.section.correspondingLocation
import com.mineinabyss.deeperworld.world.section.inSectionOverlap
import com.mineinabyss.deeperworld.world.section.section
import com.mineinabyss.idofront.events.call
import com.mineinabyss.idofront.messaging.error
import com.mineinabyss.idofront.time.ticks
import kotlinx.coroutines.delay
import net.kyori.adventure.text.Component
import nl.rutgerkok.blocklocker.SearchMode
import org.bukkit.Material
import org.bukkit.block.Block
import org.bukkit.block.Container
import org.bukkit.block.ShulkerBox
import org.bukkit.block.Sign
import org.bukkit.block.data.Ageable
import org.bukkit.block.data.Bisected
import org.bukkit.block.data.Levelled
import org.bukkit.block.data.Waterlogged
import org.bukkit.block.data.type.Bed
import org.bukkit.block.data.type.Sapling
import org.bukkit.block.data.type.Stairs
import org.bukkit.block.data.type.TrapDoor
import org.bukkit.entity.EntityType
Expand All @@ -29,6 +33,9 @@ import org.bukkit.event.entity.EntityExplodeEvent
import org.bukkit.event.entity.EntitySpawnEvent
import org.bukkit.event.player.PlayerBucketEmptyEvent
import org.bukkit.event.player.PlayerBucketFillEvent
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.event.world.StructureGrowEvent
import org.bukkit.inventory.EquipmentSlot

private fun syncBlockLocker(corr: Block) {
blockLocker.protectionFinder.findProtection(corr, SearchMode.ALL).ifPresent {
Expand Down Expand Up @@ -61,12 +68,12 @@ object SectionSyncListener : Listener {
}

//sync any changes to BlockLocker's signs`
if (DeeperContext.isBlockLockerLoaded && state is Sign && state.lines[0] == "[Private]") {
if (DeeperContext.isBlockLockerLoaded && state is Sign &&
state.lines().first() == Component.text("[Private]")) {
syncBlockLocker(corr)
}

val blockData = block.blockData

if (blockData is Bed) {
corr.setType(Material.STONE, false)
when (blockData.part) {
Expand Down Expand Up @@ -94,52 +101,52 @@ object SectionSyncListener : Listener {
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
fun BlockPlaceEvent.syncBlockPlace() {
BlockSyncEvent(block, SyncType.PLACE).call {
block.sync { original, corr ->
if (original.type.name.contains("SHULKER")) {
isCancelled = true
player.error("Shulkers are disabled near section changes due to item loss bugs.")
return@sync
}
corr.blockData = original.blockData.clone()
}
block.sync(updateBlockData(block.blockData))
}
}

//handles fertilized crops as well
//disabled for now as it causes significant lag.
/*@EventHandler
fun syncBlockGrow(blockEvent: BlockGrowEvent) {
blockEvent.newState.location.sync()
}*/

@EventHandler
fun BlockGrowEvent.syncBlockGrow() {
if (!block.location.inSectionOverlap) return
deeperWorld.launch {
delay(1.ticks)
block.sync(updateBlockData(block.blockData))
}
}

// Since [BlockGrowEvent] doesn't get called for bonemeal-growth
@EventHandler
fun BlockPhysicsEvent.sync() {
val section = block.location.section ?: return
val section2 = block.location.correspondingSection ?: return
fun PlayerInteractEvent.syncBlockGrowFromBoneMeal() {
val block = clickedBlock ?: return
val corrBlock = block.location.correspondingLocation?.block ?: return

if (action != Action.RIGHT_CLICK_BLOCK || hand != EquipmentSlot.HAND) return
if (player.inventory.getItem(EquipmentSlot.HAND).type != Material.BONE_MEAL) return
if (block.blockData !is Ageable || block is Sapling) return
if (!block.location.inSectionOverlap || corrBlock.type != block.type) return

deeperWorld.launch {
delay(1.ticks)
block.sync(updateBlockData(block.blockData))
}
}

if (
block.location.inSectionOverlap
// && section.isOnTopOf(section2)
&& block.blockData !is Levelled // Water / Lava
) isCancelled = true

// if(!section.isOnTopOf(section2)) {
// block.sync()
// }
// Copies structure onto another section
@EventHandler
fun StructureGrowEvent.syncStructureGrowth() {
if (blocks.all { (it.block.type == it.block.location.correspondingLocation?.block?.type) })
blocks.forEach { it.block.sync(updateBlockData(it.blockData)) }
else isCancelled = true
}

@EventHandler
fun BlockMultiPlaceEvent.syncMultiBlockPlace() {
if(
(block.blockData is Bisected || block.blockData is Bed)
&& block.blockData !is TrapDoor
&& block.blockData !is Stairs
) {
for (blockState in replacedBlockStates) {
blockState.block.sync()
}
}
val data = block.blockData
if (
(data is Bisected || data is Bed)
&& data !is TrapDoor
&& data !is Stairs
) replacedBlockStates.forEach { it.block.sync() }
}

@EventHandler
Expand All @@ -150,7 +157,7 @@ object SectionSyncListener : Listener {
if (data is Waterlogged) {
data.isWaterlogged = true
// Trigger block update for water
if(corr.state !is Container) corr.type = material
if (corr.state !is Container) corr.type = material
corr.type = orig.type
corr.blockData = data
} else
Expand All @@ -169,28 +176,30 @@ object SectionSyncListener : Listener {
}

/** Synchronize explosions */
@EventHandler
@EventHandler(ignoreCancelled = true)
fun EntityExplodeEvent.syncExplosions() {
if (!isCancelled)
blockList().forEach { explodedBlock ->
explodedBlock.location.sync(updateMaterial(Material.AIR))
}
blockList().forEach { explodedBlock ->
explodedBlock.location.sync(updateMaterial(Material.AIR))
}
}

@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
fun SignChangeEvent.syncSignText() {
block.sync(signUpdater(lines))
block.sync(signUpdater(lines()))
}

/** Disables Iron Golem and Wither summons in section transitions due to duping **/
/** Removes Iron Golem and Wither summons in corresponding section location due to duping **/
@EventHandler
fun EntitySpawnEvent.onEntitySummon() {
if (entity.location.inSectionOverlap &&
(entityType == EntityType.WITHER || entityType == EntityType.IRON_GOLEM)) {
isCancelled = true
entity.location.getNearbyPlayers(5.0).forEach {
it.error("Spawning of $entityType is disabled in section overlaps.")
}
(entityType == EntityType.WITHER || entityType == EntityType.IRON_GOLEM)
) {
entity.world.getNearbyEntitiesByType(
entityType.entityClass,
entity.location.correspondingLocation ?: return,
1.0
).firstOrNull()?.remove() ?: return
}

}
}
Loading

0 comments on commit 8b5b801

Please sign in to comment.