diff --git a/README.md b/README.md index b1a8559..267d7d3 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Maven gg.flyte twilight - 1.0.25 + 1.0.26 ``` @@ -29,14 +29,14 @@ maven { url "https://repo.flyte.gg/releases" } -implementation "gg.flyte:twilight:1.0.25" +implementation "gg.flyte:twilight:1.0.26" ``` Gradle (Kotlin DSL) ```kotlin maven("https://repo.flyte.gg/releases") -implementation("gg.flyte:twilight:1.0.25") +implementation("gg.flyte:twilight:1.0.26") ``` Certain features of Twilight require configuration, which can be done via the Twilight class. To setup a Twilight class instance, you can use the `twilight` method as shown below: diff --git a/build.gradle.kts b/build.gradle.kts index 51b46cd..f4d895e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } group = "gg.flyte" -version = "1.0.25" +version = "1.0.26" repositories { mavenCentral() diff --git a/src/main/kotlin/gg/flyte/twilight/event/Event.kt b/src/main/kotlin/gg/flyte/twilight/event/Event.kt index 317aa3b..051fa46 100644 --- a/src/main/kotlin/gg/flyte/twilight/event/Event.kt +++ b/src/main/kotlin/gg/flyte/twilight/event/Event.kt @@ -1,10 +1,12 @@ package gg.flyte.twilight.event import gg.flyte.twilight.Twilight +import gg.flyte.twilight.event.custom.admin.listener.OpEventListener import gg.flyte.twilight.event.custom.interact.listener.InteractEventListener import gg.flyte.twilight.extension.applyForEach import gg.flyte.twilight.inventory.GUIListener import org.bukkit.event.* +import org.bukkit.scheduler.BukkitTask import java.time.Instant /** @@ -47,8 +49,12 @@ open class CustomTwilightListener { * The list of events registered to this custom Twilight Event */ val events = mutableListOf() + val runnables = mutableListOf() - fun unregister() = events.applyForEach { unregister() } + fun unregister() { + events.applyForEach { unregister() } + runnables.applyForEach { cancel() } + } } /** @@ -113,6 +119,7 @@ open class TwilightEvent(async: Boolean = false) : Event(async), Cancellable { */ val customEvents = listOf( GUIListener, - InteractEventListener + InteractEventListener, + OpEventListener ) diff --git a/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerDeopEvent.kt b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerDeopEvent.kt new file mode 100644 index 0000000..1f5eb2d --- /dev/null +++ b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerDeopEvent.kt @@ -0,0 +1,32 @@ +package gg.flyte.twilight.event.custom.admin + +import gg.flyte.twilight.event.TwilightEvent +import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.entity.Player +import org.bukkit.event.block.Action +import org.bukkit.inventory.ItemStack +import org.bukkit.util.Vector +import java.util.* + +/** + * Represents an event that occurs when a player is de-op'd (de-promoted from operator status). + * This event contains information about the affected player's UUID and name. + */ +class PlayerDeopEvent( + val uuid: UUID, // The UUID of the player being de-op'd. + val name: String // The name of the player being de-op'd. +) : TwilightEvent() { + /** + * Represents the offline player associated with this event. + */ + val offlinePlayer: OfflinePlayer = Bukkit.getOfflinePlayer(uuid) + + /** + * Represents the online player associated with this event, if available. + * This property will be null if the player is not currently online. + */ + val player: Player? = if (offlinePlayer.isOnline) offlinePlayer.player else null +} \ No newline at end of file diff --git a/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerOpChangeEvent.kt b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerOpChangeEvent.kt new file mode 100644 index 0000000..3cb4b7c --- /dev/null +++ b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerOpChangeEvent.kt @@ -0,0 +1,32 @@ +package gg.flyte.twilight.event.custom.admin + +import gg.flyte.twilight.event.TwilightEvent +import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.entity.Player +import org.bukkit.event.block.Action +import org.bukkit.inventory.ItemStack +import org.bukkit.util.Vector +import java.util.* + +/** + * Represents an event that occurs when a player's operator status changes. + * This event contains information about the affected player's UUID and name. + */ +class PlayerOpChangeEvent( + val uuid: UUID, // The UUID of the player whose operator status changed. + val name: String // The name of the player whose operator status changed. +) : TwilightEvent() { + /** + * Represents the offline player associated with this event. + */ + val offlinePlayer: OfflinePlayer = Bukkit.getOfflinePlayer(uuid) + + /** + * Represents the online player associated with this event, if available. + * This property will be null if the player is not currently online. + */ + val player: Player? = if (offlinePlayer.isOnline) offlinePlayer.player else null +} diff --git a/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerOpEvent.kt b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerOpEvent.kt new file mode 100644 index 0000000..3354a17 --- /dev/null +++ b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/PlayerOpEvent.kt @@ -0,0 +1,32 @@ +package gg.flyte.twilight.event.custom.admin + +import gg.flyte.twilight.event.TwilightEvent +import org.bukkit.Bukkit +import org.bukkit.OfflinePlayer +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.entity.Player +import org.bukkit.event.block.Action +import org.bukkit.inventory.ItemStack +import org.bukkit.util.Vector +import java.util.* + +/** + * Represents an event that occurs when a player is op'd (promoted to operator status). + * This event contains information about the affected player's UUID and name. + */ +class PlayerOpEvent( + val uuid: UUID, // The UUID of the player being op'd. + val name: String // The name of the player being op'd. +) : TwilightEvent() { + /** + * Represents the offline player associated with this event. + */ + val offlinePlayer: OfflinePlayer = Bukkit.getOfflinePlayer(uuid) + + /** + * Represents the online player associated with this event, if available. + * This property will be null if the player is not currently online. + */ + val player: Player? = if (offlinePlayer.isOnline) offlinePlayer.player else null +} diff --git a/src/main/kotlin/gg/flyte/twilight/event/custom/admin/listener/OpEventListener.kt b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/listener/OpEventListener.kt new file mode 100644 index 0000000..57f621d --- /dev/null +++ b/src/main/kotlin/gg/flyte/twilight/event/custom/admin/listener/OpEventListener.kt @@ -0,0 +1,58 @@ +package gg.flyte.twilight.event.custom.admin.listener + +import gg.flyte.twilight.Twilight +import gg.flyte.twilight.event.CustomTwilightListener +import gg.flyte.twilight.event.custom.admin.PlayerDeopEvent +import gg.flyte.twilight.event.custom.admin.PlayerOpChangeEvent +import gg.flyte.twilight.event.custom.admin.PlayerOpEvent +import gg.flyte.twilight.extension.applyForEach +import gg.flyte.twilight.gson.GSON +import gg.flyte.twilight.scheduler.repeat +import java.io.File +import java.util.* + +object OpEventListener : CustomTwilightListener() { + private val opsFile = File("${Twilight.plugin.dataFolder}/../../ops.json") + private var opsData = mutableSetOf() + private var opsLastChanged: Long? = null + + init { + if (opsFile.exists()) { + opsLastChanged = opsFile.lastModified() + opsData += getOpsData() + } + + runnables += repeat(async = true) { + if (!opsFile.exists()) return@repeat cancel() + if (!hasOpsChanged()) return@repeat + + val newOpsData = getOpsData() + + // Removed ops + opsData.subtract(newOpsData).toSet().applyForEach { + opsData -= this + Twilight.plugin.server.pluginManager.callEvent(PlayerDeopEvent(uuid, name)) + Twilight.plugin.server.pluginManager.callEvent(PlayerOpChangeEvent(uuid, name)) + } + + // Added ops + newOpsData.subtract(opsData).toSet().applyForEach { + opsData += this + Twilight.plugin.server.pluginManager.callEvent(PlayerOpEvent(uuid, name)) + Twilight.plugin.server.pluginManager.callEvent(PlayerOpChangeEvent(uuid, name)) + } + } + } + + data class OpData( + val uuid: UUID, + val name: String, + val level: Int, + val bypassPlayerLimit: Boolean + ) + + private fun getOpsData(): Set = GSON.fromJson(opsFile.reader(), Array::class.java).toSet() + + private fun hasOpsChanged(): Boolean = (opsLastChanged ?: 0) < opsFile.lastModified() + +}