diff --git a/src/main/kotlin/net/trueog/antipierayog/AntiPieRay.kt b/src/main/kotlin/net/trueog/antipierayog/AntiPieRay.kt index 9fe4ab8..aaf84f0 100644 --- a/src/main/kotlin/net/trueog/antipierayog/AntiPieRay.kt +++ b/src/main/kotlin/net/trueog/antipierayog/AntiPieRay.kt @@ -5,8 +5,8 @@ import com.github.retrooper.packetevents.event.PacketListenerPriority import com.github.retrooper.packetevents.protocol.world.states.type.StateType import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder -import java.util.Collections -import java.util.IdentityHashMap +import java.util.* +import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.plugin.java.JavaPlugin @@ -96,6 +96,9 @@ class AntiPieRay : JavaPlugin() { ) PacketEvents.getAPI().eventManager.registerListener(ChunkDataPacketListener(), PacketListenerPriority.NORMAL) PacketEvents.getAPI().eventManager.registerListener(BlockChangePacketListener(), PacketListenerPriority.NORMAL) + PacketEvents.getAPI() + .eventManager + .registerListener(PlayerPositionRotationPacketListener(), PacketListenerPriority.NORMAL) } override fun onEnable() { @@ -108,6 +111,7 @@ class AntiPieRay : JavaPlugin() { } override fun onDisable() { + Bukkit.getScheduler().cancelTasks(this) PacketEvents.getAPI().terminate() } } diff --git a/src/main/kotlin/net/trueog/antipierayog/BlockEntityHider.kt b/src/main/kotlin/net/trueog/antipierayog/BlockEntityHider.kt index 8a3645f..b6c2dcd 100644 --- a/src/main/kotlin/net/trueog/antipierayog/BlockEntityHider.kt +++ b/src/main/kotlin/net/trueog/antipierayog/BlockEntityHider.kt @@ -395,46 +395,52 @@ class BlockEntityHider { fun Location.toBlockPosition() = BlockPosition(blockX, blockY, blockZ) } - val hiddenBlocksForPlayer: MutableMap> = ConcurrentHashMap() - val blockHiddenForPlayers: MutableMap> = ConcurrentHashMap() + val hiddenBlocksByPlayer: MutableMap> = ConcurrentHashMap() + val playersByHiddenBlock: MutableMap> = ConcurrentHashMap() /** * Outer map key: A hidden block * * Inner map key: A block that is preventing the hidden block to be seen */ - val blockBlockedByForPlayer: MutableMap>> = + val blockingBlockForPlayersByHiddenBlock: MutableMap>> = ConcurrentHashMap() fun addPos(uuid: UUID, pos: BlockPosition, blockingPositions: Set) { - hiddenBlocksForPlayer.computeIfAbsent(uuid) { ConcurrentHashMap.newKeySet() }.add(pos) - blockHiddenForPlayers.computeIfAbsent(pos) { ConcurrentHashMap.newKeySet() }.add(uuid) - val entry = blockBlockedByForPlayer.computeIfAbsent(pos) { ConcurrentHashMap() } + hiddenBlocksByPlayer.computeIfAbsent(uuid) { ConcurrentHashMap.newKeySet() }.add(pos) + playersByHiddenBlock.computeIfAbsent(pos) { ConcurrentHashMap.newKeySet() }.add(uuid) + val entry = blockingBlockForPlayersByHiddenBlock.computeIfAbsent(pos) { ConcurrentHashMap() } blockingPositions.forEach { entry.computeIfAbsent(it) { ConcurrentHashMap.newKeySet() }.add(uuid) } } fun removePos(uuid: UUID, pos: BlockPosition, skipBlockBlockedByForPlayer: Boolean = false) { - hiddenBlocksForPlayer[uuid]?.remove(pos) - blockHiddenForPlayers[pos]?.remove(uuid) + hiddenBlocksByPlayer[uuid]?.remove(pos) + playersByHiddenBlock[pos]?.remove(uuid) if (!skipBlockBlockedByForPlayer) { - blockBlockedByForPlayer[pos]?.entries?.removeAll { (_, uuids) -> + blockingBlockForPlayersByHiddenBlock[pos]?.entries?.removeAll { (_, uuids) -> uuids.remove(uuid) uuids.isEmpty() } } - if (hiddenBlocksForPlayer[uuid]?.isEmpty() == true) hiddenBlocksForPlayer.remove(uuid) - if (blockHiddenForPlayers[pos]?.isEmpty() == true) blockHiddenForPlayers.remove(pos) + if (hiddenBlocksByPlayer[uuid]?.isEmpty() == true) hiddenBlocksByPlayer.remove(uuid) + if (playersByHiddenBlock[pos]?.isEmpty() == true) playersByHiddenBlock.remove(pos) if (!skipBlockBlockedByForPlayer) { - if (blockBlockedByForPlayer[pos]?.isEmpty() == true) blockBlockedByForPlayer.remove(pos) + if (blockingBlockForPlayersByHiddenBlock[pos]?.isEmpty() == true) + blockingBlockForPlayersByHiddenBlock.remove(pos) } } fun removeAllPos(uuid: UUID) { - val hiddenBlocks = hiddenBlocksForPlayer[uuid] ?: return - hiddenBlocks.forEach { blockHiddenForPlayers[it]?.remove(uuid) } - hiddenBlocksForPlayer.remove(uuid) - blockBlockedByForPlayer.entries.removeAll { + val hiddenBlocks = hiddenBlocksByPlayer[uuid] ?: return + hiddenBlocks.forEach { + playersByHiddenBlock.computeIfPresent(it) { _, uuids -> + uuids.remove(uuid) + if (uuids.isEmpty()) null else uuids + } + } + hiddenBlocksByPlayer.remove(uuid) + blockingBlockForPlayersByHiddenBlock.entries.removeAll { it.value.values.removeAll { uuids -> uuids.remove(uuid) uuids.isEmpty() @@ -447,14 +453,14 @@ class BlockEntityHider { val threshold = min(player.viewDistance, Bukkit.getViewDistance()) + 1 val chunkX = player.location.x.toInt() shr 4 val chunkZ = player.location.z.toInt() shr 4 - blockHiddenForPlayers + playersByHiddenBlock .filterKeys { abs(chunkX - (it.x shr 4)) > threshold || abs(chunkZ - (it.z shr 4)) > threshold } .forEach { (pos, uuids) -> uuids.forEach { uuid -> removePos(uuid, pos) } } } fun removeIfNeeded(pos: BlockPosition, world: World) { if (world.getBlockAt(pos.toLocation(world)).type !in AntiPieRay.hideMaterials) { - blockHiddenForPlayers + playersByHiddenBlock .filterKeys { pos == it } .values .forEach { uuids -> uuids.forEach { uuid -> removePos(uuid, pos) } } @@ -462,7 +468,7 @@ class BlockEntityHider { } fun updateBlockVisibility(player: Player) { - val blockList = hiddenBlocksForPlayer[player.uniqueId] ?: return + val blockList = hiddenBlocksByPlayer[player.uniqueId] ?: return blockList.forEach { val loc = it.toLocation(player.world) val blockingBlock = canSee(player.eyeLocation, loc) @@ -477,7 +483,7 @@ class BlockEntityHider { fun updateBlockVisibility(pos: BlockPosition, world: World) { removeIfNeeded(pos, world) - blockBlockedByForPlayer.entries.removeAll { (blockPos, entry) -> + blockingBlockForPlayersByHiddenBlock.entries.removeAll { (blockPos, entry) -> val blockLoc = blockPos.toLocation(world) val posEntry = entry[pos] posEntry?.removeAll { uuid -> diff --git a/src/main/kotlin/net/trueog/antipierayog/Events.kt b/src/main/kotlin/net/trueog/antipierayog/Events.kt index f7bbfc9..8385eb3 100644 --- a/src/main/kotlin/net/trueog/antipierayog/Events.kt +++ b/src/main/kotlin/net/trueog/antipierayog/Events.kt @@ -11,23 +11,9 @@ import org.bukkit.event.block.BlockBurnEvent import org.bukkit.event.block.BlockExplodeEvent import org.bukkit.event.entity.EntityExplodeEvent import org.bukkit.event.player.PlayerChangedWorldEvent -import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerQuitEvent class Events : Listener { - @EventHandler(priority = EventPriority.MONITOR) - fun onPlayerMove(event: PlayerMoveEvent) { - val worldName = event.player.world.name - if (worldName != "world" && worldName != "world_nether" && worldName != "world_the_end") return - - Bukkit.getScheduler() - .runTaskLaterAsynchronously( - AntiPieRay.plugin, - Runnable { AntiPieRay.blockEntityHider.updateBlockVisibility(event.player) }, - 1L, - ) - } - fun genericBlockBreakHandler(block: Block) { Bukkit.getScheduler() .runTaskLaterAsynchronously( @@ -76,11 +62,13 @@ class Events : Listener { val worldName = event.player.world.name if (worldName != "world" && worldName != "world_nether" && worldName != "world_the_end") return - AntiPieRay.blockEntityHider.removeAllPos(event.player.uniqueId) + Bukkit.getScheduler() + .runTaskAsynchronously(AntiPieRay.plugin, Runnable { AntiPieRay.blockEntityHider.removeAllPos(event.player.uniqueId) }) } @EventHandler(priority = EventPriority.MONITOR) fun onPlayerQuit(event: PlayerQuitEvent) { - AntiPieRay.blockEntityHider.removeAllPos(event.player.uniqueId) + Bukkit.getScheduler() + .runTaskAsynchronously(AntiPieRay.plugin, Runnable { AntiPieRay.blockEntityHider.removeAllPos(event.player.uniqueId) }) } } diff --git a/src/main/kotlin/net/trueog/antipierayog/PlayerPositionRotationPacketListener.kt b/src/main/kotlin/net/trueog/antipierayog/PlayerPositionRotationPacketListener.kt new file mode 100644 index 0000000..e9e36bf --- /dev/null +++ b/src/main/kotlin/net/trueog/antipierayog/PlayerPositionRotationPacketListener.kt @@ -0,0 +1,27 @@ +package net.trueog.antipierayog + +import com.github.retrooper.packetevents.event.PacketListener +import com.github.retrooper.packetevents.event.PacketReceiveEvent +import com.github.retrooper.packetevents.protocol.packettype.PacketType +import org.bukkit.Bukkit +import org.bukkit.entity.Player + +class PlayerPositionRotationPacketListener : PacketListener { + override fun onPacketReceive(event: PacketReceiveEvent) { + if (event.packetType != PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) { + return + } + + val player = event.getPlayer() + + val worldName = player.world.name + if (worldName != "world" && worldName != "world_nether" && worldName != "world_the_end") return + + Bukkit.getScheduler() + .runTaskLaterAsynchronously( + AntiPieRay.plugin, + Runnable { AntiPieRay.blockEntityHider.updateBlockVisibility(player) }, + 1, + ) + } +}