Skip to content

Commit

Permalink
feat(custom-events): revamp events system, introduce custom events (h…
Browse files Browse the repository at this point in the history
…and interactions)

Bump version to 1.0.19
Add CustomTwilightListener for custom event listeners and ease of unregistering on Twilight termination
Added optional use said termination for plugin shutdown or other use-case to handle Twilight clean-up
  • Loading branch information
joshbker committed Nov 5, 2023
1 parent 9639249 commit ce1fc07
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 144 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Maven
<dependency>
<groupId>gg.flyte</groupId>
<artifactId>twilight</artifactId>
<version>1.0.18</version>
<version>1.0.19</version>
</dependency>
```

Expand All @@ -29,14 +29,14 @@ maven {
url "https://repo.flyte.gg/releases"
}
implementation "gg.flyte:twilight:1.0.18"
implementation "gg.flyte:twilight:1.0.19"
```

Gradle (Kotlin DSL)
```kotlin
maven("https://repo.flyte.gg/releases")

implementation("gg.flyte:twilight:1.0.18")
implementation("gg.flyte:twilight:1.0.19")
```

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:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = "gg.flyte"
version = "1.0.18"
version = "1.0.19"

repositories {
mavenCentral()
Expand Down
11 changes: 5 additions & 6 deletions src/main/kotlin/gg/flyte/twilight/Twilight.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package gg.flyte.twilight
import gg.flyte.twilight.data.MongoDB
import gg.flyte.twilight.data.service.NameCacheService
import gg.flyte.twilight.environment.Environment
import gg.flyte.twilight.event.EventListener
import gg.flyte.twilight.event.custom.interact.listener.InteractEventListener
import gg.flyte.twilight.event.customEvents
import gg.flyte.twilight.extension.applyForEach
import gg.flyte.twilight.inventory.GUIListener
import org.bukkit.Bukkit
import org.bukkit.plugin.java.JavaPlugin
Expand All @@ -12,11 +14,6 @@ class Twilight(javaPlugin: JavaPlugin) {

init {
plugin = javaPlugin

listOf(
GUIListener(),
EventListener()
).forEach { Bukkit.getPluginManager().registerEvents(it, plugin) }
}

companion object {
Expand All @@ -33,6 +30,8 @@ class Twilight(javaPlugin: JavaPlugin) {

fun nameCache(init: NameCacheService.Settings.() -> Unit) = NameCacheService.nameCache(NameCacheService.Settings().apply(init))

fun terminate() = customEvents.applyForEach { unregister() }

}

fun twilight(plugin: JavaPlugin, init: Twilight.() -> Unit): Twilight = Twilight(plugin).apply(init)
113 changes: 95 additions & 18 deletions src/main/kotlin/gg/flyte/twilight/event/Event.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package gg.flyte.twilight.event

import gg.flyte.twilight.Twilight
import org.bukkit.event.Event
import org.bukkit.event.EventPriority
import org.bukkit.event.HandlerList
import org.bukkit.event.Listener
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 java.time.Instant

/**
* Creates a Bukkit event listener and registers it to listen for a specific type of event.
Expand All @@ -13,29 +14,105 @@ import org.bukkit.event.Listener
*
* @param T The type of event to listen for, specified as a reified type parameter.
* @param priority The priority at which the listener should be called, default is EventPriority.NORMAL.
* @param ignoreCancelled Whether to ignore if the event was cancellled or not, default is false.
* @param callback A lambda function to be executed when the specified event occurs.
* @return A `TwilightListener` instance, which can be used to later unregister the listener.
*/
inline fun <reified T : Event> event(
priority: EventPriority = EventPriority.NORMAL,
ignoreCancelled: Boolean = false,
crossinline callback: T.() -> Unit,
): TwilightListener =
TwilightListener().apply {
Twilight.plugin.server.pluginManager.registerEvent(
T::class.java, // tell bukkit what event we're listening to
this, // the listener but we don't need it
priority, // the event priority, can be changed in the code but by default its 'normal'
{ _, event -> // the 'opening' of the event executor
if (event is T) callback(event) // event executor body
},
Twilight.plugin, // pass the instance to bukkit, so it knows what plugin should listen to the event
true
)
}
): TwilightListener = TwilightListener().apply {
Twilight.plugin.server.pluginManager.registerEvent(
T::class.java,
this,
priority,
{ _, event ->
if (event is T) callback(event)
},
Twilight.plugin,
ignoreCancelled
)
}

/**
* Layer on top of Bukkit's Listener to allow for easy unregistering. Returned by the above function.
*/
class TwilightListener : Listener {
fun unregister() = HandlerList.unregisterAll(this)
}
}

open class CustomTwilightListener {
/**
* The list of events registered to this custom Twilight Event
*/
val events = mutableListOf<TwilightListener>()

fun unregister() = events.applyForEach { unregister() }
}

/**
* Base class for custom events in the Twilight plugin.
*
* @param async Specifies if the event should be handled asynchronously (default: false).
*/
open class TwilightEvent(async: Boolean = false) : Event(async), Cancellable {

/**
* The timestamp when the event occurred.
*/
val timestamp: Instant = Instant.now()

/**
* A flag indicating whether the event is cancelled.
*/
var cancelled = false

/**
* Checks if the event is cancelled.
*
* @return True if the event is cancelled, otherwise false.
*/
override fun isCancelled(): Boolean = cancelled

/**
* Sets the cancellation status of the event.
*
* @param cancel True to cancel the event, false to allow it to proceed.
*/
override fun setCancelled(cancel: Boolean) {
cancelled = cancel
}

companion object {
val HANDLERS = HandlerList()

/**
* Retrieves the HandlerList for this event.
*
* @return The HandlerList for this event.
*/
@JvmStatic
fun getHandlerList(): HandlerList {
return HANDLERS
}
}

/**
* Gets the HandlerList for this event.
*
* @return The HandlerList for this event.
*/
override fun getHandlers(): HandlerList {
return HANDLERS
}
}

/**
* List of custom Twilight Event Listeners
*/
val customEvents = listOf<CustomTwilightListener>(
GUIListener,
InteractEventListener
)

29 changes: 0 additions & 29 deletions src/main/kotlin/gg/flyte/twilight/event/EventListener.kt

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package gg.flyte.twilight.event.custom.interact

import gg.flyte.twilight.event.TwilightEvent
import org.bukkit.block.Block
import org.bukkit.block.BlockFace
import org.bukkit.entity.Player
import org.bukkit.event.block.Action
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.util.Vector

/**
* Represents an event where a player interacts with an item in their main-hand.
*
* @param player The Player who triggered the event.
* @param action The action performed by the player (e.g., LEFT_CLICK_AIR, RIGHT_CLICK_BLOCK).
* @param item The ItemStack in the player's off-hand.
* @param clickedBlock The Block that was clicked, if applicable.
* @param clickedFace The face of the clicked block, if applicable.
* @param clickedPosition The position where the player clicked, if applicable.
*/
class PlayerMainHandInteractEvent(
val player: Player,
val action: Action,
val item: ItemStack?,
val clickedBlock: Block?,
val clickedFace: BlockFace,
val clickedPosition: Vector?
) : TwilightEvent()
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package gg.flyte.twilight.event.custom.interact

import gg.flyte.twilight.event.TwilightEvent
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

/**
* Represents an event where a player interacts with an item in their off-hand.
*
* @param player The Player who triggered the event.
* @param action The action performed by the player (e.g., LEFT_CLICK_AIR, RIGHT_CLICK_BLOCK).
* @param item The ItemStack in the player's off-hand.
* @param clickedBlock The Block that was clicked, if applicable.
* @param clickedFace The face of the clicked block, if applicable.
* @param clickedPosition The position where the player clicked, if applicable.
*/
class PlayerOffHandInteractEvent(
val player: Player,
val action: Action,
val item: ItemStack?,
val clickedBlock: Block?,
val clickedFace: BlockFace,
val clickedPosition: Vector?
) : TwilightEvent()
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package gg.flyte.twilight.event.custom.interact.listener

import gg.flyte.twilight.Twilight
import gg.flyte.twilight.event.CustomTwilightListener
import gg.flyte.twilight.event.custom.interact.PlayerMainHandInteractEvent
import gg.flyte.twilight.event.custom.interact.PlayerOffHandInteractEvent
import gg.flyte.twilight.event.event
import org.bukkit.event.player.PlayerInteractEvent
import org.bukkit.inventory.EquipmentSlot

object InteractEventListener : CustomTwilightListener() {

init {
events += event<PlayerInteractEvent>(ignoreCancelled = true) {
Twilight.plugin.server.pluginManager.callEvent(
if (hand == EquipmentSlot.HAND)
PlayerMainHandInteractEvent(player, action, item, clickedBlock, blockFace, clickedPosition)
else
PlayerOffHandInteractEvent(player, action, item, clickedBlock, blockFace, clickedPosition)
)
}
}

}
Loading

0 comments on commit ce1fc07

Please sign in to comment.