aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/events
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-08-28 19:04:24 +0200
committerLinnea Gräf <nea@nea.moe>2024-08-28 19:04:24 +0200
commitd2f240ff0ca0d27f417f837e706c781a98c31311 (patch)
tree0db7aff6cc14deaf36eed83889d59fd6b3a6f599 /src/main/kotlin/events
parenta6906308163aa3b2d18fa1dc1aa71ac9bbcc83ab (diff)
downloadFirmament-d2f240ff0ca0d27f417f837e706c781a98c31311.tar.gz
Firmament-d2f240ff0ca0d27f417f837e706c781a98c31311.tar.bz2
Firmament-d2f240ff0ca0d27f417f837e706c781a98c31311.zip
Refactor source layout
Introduce compat source sets and move all kotlin sources to the main directory [no changelog]
Diffstat (limited to 'src/main/kotlin/events')
-rw-r--r--src/main/kotlin/events/AllowChatEvent.kt16
-rw-r--r--src/main/kotlin/events/AttackBlockEvent.kt18
-rw-r--r--src/main/kotlin/events/BakeExtraModelsEvent.kt21
-rw-r--r--src/main/kotlin/events/ClientStartedEvent.kt6
-rw-r--r--src/main/kotlin/events/CommandEvent.kt45
-rw-r--r--src/main/kotlin/events/CustomItemModelEvent.kt43
-rw-r--r--src/main/kotlin/events/EarlyResourceReloadEvent.kt10
-rw-r--r--src/main/kotlin/events/EntityDespawnEvent.kt11
-rw-r--r--src/main/kotlin/events/EntityInteractionEvent.kt29
-rw-r--r--src/main/kotlin/events/EntityUpdateEvent.kt31
-rw-r--r--src/main/kotlin/events/FeaturesInitializedEvent.kt8
-rw-r--r--src/main/kotlin/events/FinalizeResourceManagerEvent.kt10
-rw-r--r--src/main/kotlin/events/FirmamentEvent.kt38
-rw-r--r--src/main/kotlin/events/FirmamentEventBus.kt52
-rw-r--r--src/main/kotlin/events/HandledScreenClickEvent.kt10
-rw-r--r--src/main/kotlin/events/HandledScreenForegroundEvent.kt16
-rw-r--r--src/main/kotlin/events/HandledScreenKeyPressedEvent.kt24
-rw-r--r--src/main/kotlin/events/HandledScreenPushREIEvent.kt18
-rw-r--r--src/main/kotlin/events/HotbarItemRenderEvent.kt17
-rw-r--r--src/main/kotlin/events/HudRenderEvent.kt13
-rw-r--r--src/main/kotlin/events/IsSlotProtectedEvent.kt46
-rw-r--r--src/main/kotlin/events/ItemTooltipEvent.kt14
-rw-r--r--src/main/kotlin/events/MaskCommands.kt13
-rw-r--r--src/main/kotlin/events/ModifyChatEvent.kt21
-rw-r--r--src/main/kotlin/events/OutgoingPacketEvent.kt9
-rw-r--r--src/main/kotlin/events/ParticleSpawnEvent.kt18
-rw-r--r--src/main/kotlin/events/PlayerInventoryUpdate.kt11
-rw-r--r--src/main/kotlin/events/ProcessChatEvent.kt28
-rw-r--r--src/main/kotlin/events/ReloadRegistrationEvent.kt7
-rw-r--r--src/main/kotlin/events/ScreenChangeEvent.kt10
-rw-r--r--src/main/kotlin/events/ScreenRenderPostEvent.kt16
-rw-r--r--src/main/kotlin/events/ServerConnectedEvent.kt18
-rw-r--r--src/main/kotlin/events/SkyblockServerUpdateEvent.kt15
-rw-r--r--src/main/kotlin/events/SlotClickEvent.kt15
-rw-r--r--src/main/kotlin/events/SlotRenderEvents.kt34
-rw-r--r--src/main/kotlin/events/SoundReceiveEvent.kt18
-rw-r--r--src/main/kotlin/events/TickEvent.kt7
-rw-r--r--src/main/kotlin/events/TooltipEvent.kt17
-rw-r--r--src/main/kotlin/events/UseBlockEvent.kt11
-rw-r--r--src/main/kotlin/events/WorldKeyboardEvent.kt18
-rw-r--r--src/main/kotlin/events/WorldReadyEvent.kt7
-rw-r--r--src/main/kotlin/events/WorldRenderLastEvent.kt27
-rw-r--r--src/main/kotlin/events/registration/ChatEvents.kt54
-rw-r--r--src/main/kotlin/events/subscription/Subscription.kt16
44 files changed, 886 insertions, 0 deletions
diff --git a/src/main/kotlin/events/AllowChatEvent.kt b/src/main/kotlin/events/AllowChatEvent.kt
new file mode 100644
index 0000000..3069843
--- /dev/null
+++ b/src/main/kotlin/events/AllowChatEvent.kt
@@ -0,0 +1,16 @@
+
+
+package moe.nea.firmament.events
+
+import moe.nea.firmament.util.unformattedString
+import net.minecraft.text.Text
+
+/**
+ * Filter whether the user should see a chat message altogether. May or may not be called for every chat packet sent by
+ * the server. When that quality is desired, consider [ProcessChatEvent] instead.
+ */
+data class AllowChatEvent(val text: Text) : FirmamentEvent.Cancellable() {
+ val unformattedString = text.unformattedString
+
+ companion object : FirmamentEventBus<AllowChatEvent>()
+}
diff --git a/src/main/kotlin/events/AttackBlockEvent.kt b/src/main/kotlin/events/AttackBlockEvent.kt
new file mode 100644
index 0000000..bbaa81d
--- /dev/null
+++ b/src/main/kotlin/events/AttackBlockEvent.kt
@@ -0,0 +1,18 @@
+
+package moe.nea.firmament.events
+
+import net.minecraft.entity.player.PlayerEntity
+import net.minecraft.util.Hand
+import net.minecraft.util.math.BlockPos
+import net.minecraft.util.math.Direction
+import net.minecraft.world.World
+
+data class AttackBlockEvent(
+ val player: PlayerEntity,
+ val world: World,
+ val hand: Hand,
+ val blockPos: BlockPos,
+ val direction: Direction
+) : FirmamentEvent.Cancellable() {
+ companion object : FirmamentEventBus<AttackBlockEvent>()
+}
diff --git a/src/main/kotlin/events/BakeExtraModelsEvent.kt b/src/main/kotlin/events/BakeExtraModelsEvent.kt
new file mode 100644
index 0000000..f75bedc
--- /dev/null
+++ b/src/main/kotlin/events/BakeExtraModelsEvent.kt
@@ -0,0 +1,21 @@
+
+package moe.nea.firmament.events
+
+import java.util.function.Consumer
+import net.minecraft.client.util.ModelIdentifier
+
+class BakeExtraModelsEvent(
+ private val addItemModel: Consumer<ModelIdentifier>,
+ private val addAnyModel: Consumer<ModelIdentifier>,
+) : FirmamentEvent() {
+
+ fun addNonItemModel(modelIdentifier: ModelIdentifier) {
+ this.addAnyModel.accept(modelIdentifier)
+ }
+
+ fun addItemModel(modelIdentifier: ModelIdentifier) {
+ this.addItemModel.accept(modelIdentifier)
+ }
+
+ companion object : FirmamentEventBus<BakeExtraModelsEvent>()
+}
diff --git a/src/main/kotlin/events/ClientStartedEvent.kt b/src/main/kotlin/events/ClientStartedEvent.kt
new file mode 100644
index 0000000..637916d
--- /dev/null
+++ b/src/main/kotlin/events/ClientStartedEvent.kt
@@ -0,0 +1,6 @@
+
+package moe.nea.firmament.events
+
+class ClientStartedEvent : FirmamentEvent() {
+ companion object : FirmamentEventBus<ClientStartedEvent>()
+}
diff --git a/src/main/kotlin/events/CommandEvent.kt b/src/main/kotlin/events/CommandEvent.kt
new file mode 100644
index 0000000..cc9cf45
--- /dev/null
+++ b/src/main/kotlin/events/CommandEvent.kt
@@ -0,0 +1,45 @@
+
+
+package moe.nea.firmament.events
+
+import com.mojang.brigadier.CommandDispatcher
+import com.mojang.brigadier.tree.LiteralCommandNode
+import net.minecraft.command.CommandRegistryAccess
+import moe.nea.firmament.commands.CaseInsensitiveLiteralCommandNode
+import moe.nea.firmament.commands.DefaultSource
+import moe.nea.firmament.commands.literal
+import moe.nea.firmament.commands.thenLiteral
+
+data class CommandEvent(
+ val dispatcher: CommandDispatcher<DefaultSource>,
+ val ctx: CommandRegistryAccess,
+ val serverCommands: CommandDispatcher<*>?,
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<CommandEvent>()
+
+ /**
+ * Register subcommands to `/firm`. For new top level commands use [CommandEvent]. Cannot be used to register
+ * subcommands to other commands.
+ */
+ data class SubCommand(
+ val builder: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>,
+ ) : FirmamentEvent() {
+ companion object : FirmamentEventBus<SubCommand>()
+
+ fun subcommand(name: String, block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit) {
+ builder.thenLiteral(name, block)
+ }
+ }
+
+ fun deleteCommand(name: String) {
+ dispatcher.root.children.removeIf { it.name.equals(name, ignoreCase = false) }
+ serverCommands?.root?.children?.removeIf { it.name.equals(name, ignoreCase = false) }
+ }
+
+ fun register(
+ name: String,
+ block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
+ ): LiteralCommandNode<DefaultSource> {
+ return dispatcher.register(literal(name, block))
+ }
+}
diff --git a/src/main/kotlin/events/CustomItemModelEvent.kt b/src/main/kotlin/events/CustomItemModelEvent.kt
new file mode 100644
index 0000000..27524a9
--- /dev/null
+++ b/src/main/kotlin/events/CustomItemModelEvent.kt
@@ -0,0 +1,43 @@
+
+
+package moe.nea.firmament.events
+
+import java.util.*
+import net.minecraft.client.render.model.BakedModel
+import net.minecraft.client.render.model.BakedModelManager
+import net.minecraft.client.util.ModelIdentifier
+import net.minecraft.item.ItemStack
+
+data class CustomItemModelEvent(
+ val itemStack: ItemStack,
+ var overrideModel: ModelIdentifier? = null,
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<CustomItemModelEvent>() {
+ private val cache = IdentityHashMap<ItemStack?, Any>()
+ private val sentinelNull = Object()
+
+ fun clearCache() {
+ cache.clear()
+ }
+
+ @JvmStatic
+ fun getModelIdentifier(itemStack: ItemStack?): ModelIdentifier? {
+ if (itemStack == null) return null
+ return publish(CustomItemModelEvent(itemStack)).overrideModel
+ }
+
+ @JvmStatic
+ fun getModel(itemStack: ItemStack?, thing: BakedModelManager): BakedModel? {
+ if (itemStack == null) return null
+ val cachedValue = cache.getOrPut(itemStack) {
+ val modelId = getModelIdentifier(itemStack) ?: return@getOrPut sentinelNull
+ val bakedModel = thing.getModel(modelId)
+ if (bakedModel === thing.missingModel) return@getOrPut sentinelNull
+ bakedModel
+ }
+ if (cachedValue === sentinelNull)
+ return null
+ return cachedValue as BakedModel
+ }
+ }
+}
diff --git a/src/main/kotlin/events/EarlyResourceReloadEvent.kt b/src/main/kotlin/events/EarlyResourceReloadEvent.kt
new file mode 100644
index 0000000..ec8377a
--- /dev/null
+++ b/src/main/kotlin/events/EarlyResourceReloadEvent.kt
@@ -0,0 +1,10 @@
+
+package moe.nea.firmament.events
+
+import java.util.concurrent.Executor
+import net.minecraft.resource.ResourceManager
+
+data class EarlyResourceReloadEvent(val resourceManager: ResourceManager, val preparationExecutor: Executor) :
+ FirmamentEvent() {
+ companion object : FirmamentEventBus<EarlyResourceReloadEvent>()
+}
diff --git a/src/main/kotlin/events/EntityDespawnEvent.kt b/src/main/kotlin/events/EntityDespawnEvent.kt
new file mode 100644
index 0000000..93dc477
--- /dev/null
+++ b/src/main/kotlin/events/EntityDespawnEvent.kt
@@ -0,0 +1,11 @@
+
+package moe.nea.firmament.events
+
+import net.minecraft.entity.Entity
+
+data class EntityDespawnEvent(
+ val entity: Entity?, val entityId: Int,
+ val reason: Entity.RemovalReason,
+) : FirmamentEvent() {
+ companion object: FirmamentEventBus<EntityDespawnEvent>()
+}
diff --git a/src/main/kotlin/events/EntityInteractionEvent.kt b/src/main/kotlin/events/EntityInteractionEvent.kt
new file mode 100644
index 0000000..123ea39
--- /dev/null
+++ b/src/main/kotlin/events/EntityInteractionEvent.kt
@@ -0,0 +1,29 @@
+
+package moe.nea.firmament.events
+
+import net.minecraft.entity.Entity
+import net.minecraft.util.Hand
+
+data class EntityInteractionEvent(
+ val kind: InteractionKind,
+ val entity: Entity,
+ val hand: Hand,
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<EntityInteractionEvent>()
+ enum class InteractionKind {
+ /**
+ * Is sent when left-clicking an entity
+ */
+ ATTACK,
+
+ /**
+ * Is a fallback when [INTERACT_AT_LOCATION] fails
+ */
+ INTERACT,
+
+ /**
+ * Is tried first on right click
+ */
+ INTERACT_AT_LOCATION,
+ }
+}
diff --git a/src/main/kotlin/events/EntityUpdateEvent.kt b/src/main/kotlin/events/EntityUpdateEvent.kt
new file mode 100644
index 0000000..d091984
--- /dev/null
+++ b/src/main/kotlin/events/EntityUpdateEvent.kt
@@ -0,0 +1,31 @@
+
+package moe.nea.firmament.events
+
+import net.minecraft.entity.Entity
+import net.minecraft.entity.LivingEntity
+import net.minecraft.entity.data.DataTracker
+import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket
+
+/**
+ * This event is fired when some entity properties are updated.
+ * It is not fired for common changes like position, but is for less common ones,
+ * like health, tracked data, names, equipment. It is always fired
+ * *after* the values have been applied to the entity.
+ */
+sealed class EntityUpdateEvent : FirmamentEvent() {
+ companion object : FirmamentEventBus<EntityUpdateEvent>()
+
+ abstract val entity: Entity
+
+ data class AttributeUpdate(
+ override val entity: LivingEntity,
+ val attributes: List<EntityAttributesS2CPacket.Entry>,
+ ) : EntityUpdateEvent()
+
+ data class TrackedDataUpdate(
+ override val entity: Entity,
+ val trackedValues: List<DataTracker.SerializedEntry<*>>,
+ ) : EntityUpdateEvent()
+
+// TODO: onEntityPassengersSet, onEntityAttach?, onEntityEquipmentUpdate, onEntityStatusEffect
+}
diff --git a/src/main/kotlin/events/FeaturesInitializedEvent.kt b/src/main/kotlin/events/FeaturesInitializedEvent.kt
new file mode 100644
index 0000000..ad2ad8a
--- /dev/null
+++ b/src/main/kotlin/events/FeaturesInitializedEvent.kt
@@ -0,0 +1,8 @@
+
+package moe.nea.firmament.events
+
+import moe.nea.firmament.features.FirmamentFeature
+
+data class FeaturesInitializedEvent(val features: List<FirmamentFeature>) : FirmamentEvent() {
+ companion object : FirmamentEventBus<FeaturesInitializedEvent>()
+}
diff --git a/src/main/kotlin/events/FinalizeResourceManagerEvent.kt b/src/main/kotlin/events/FinalizeResourceManagerEvent.kt
new file mode 100644
index 0000000..c43ad3b
--- /dev/null
+++ b/src/main/kotlin/events/FinalizeResourceManagerEvent.kt
@@ -0,0 +1,10 @@
+
+package moe.nea.firmament.events
+
+import net.minecraft.resource.ReloadableResourceManagerImpl
+
+data class FinalizeResourceManagerEvent(
+ val resourceManager: ReloadableResourceManagerImpl,
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<FinalizeResourceManagerEvent>()
+}
diff --git a/src/main/kotlin/events/FirmamentEvent.kt b/src/main/kotlin/events/FirmamentEvent.kt
new file mode 100644
index 0000000..1a93ef5
--- /dev/null
+++ b/src/main/kotlin/events/FirmamentEvent.kt
@@ -0,0 +1,38 @@
+
+
+package moe.nea.firmament.events
+
+/**
+ * An event that can be fired by a [FirmamentEventBus].
+ *
+ * Typically, that event bus is implemented as a companion object
+ *
+ * ```
+ * class SomeEvent : FirmamentEvent() {
+ * companion object : FirmamentEventBus<SomeEvent>()
+ * }
+ * ```
+ */
+abstract class FirmamentEvent {
+ /**
+ * A [FirmamentEvent] that can be [cancelled]
+ */
+ abstract class Cancellable : FirmamentEvent() {
+ /**
+ * Cancels this is event.
+ *
+ * @see cancelled
+ */
+ fun cancel() {
+ cancelled = true
+ }
+
+ /**
+ * Whether this event is cancelled.
+ *
+ * Cancelled events will bypass handlers unless otherwise specified and will prevent the action that this
+ * event was originally fired for.
+ */
+ var cancelled: Boolean = false
+ }
+}
diff --git a/src/main/kotlin/events/FirmamentEventBus.kt b/src/main/kotlin/events/FirmamentEventBus.kt
new file mode 100644
index 0000000..ee9e6c8
--- /dev/null
+++ b/src/main/kotlin/events/FirmamentEventBus.kt
@@ -0,0 +1,52 @@
+
+
+package moe.nea.firmament.events
+
+import java.util.concurrent.CopyOnWriteArrayList
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.util.MC
+
+/**
+ * A pubsub event bus.
+ *
+ * [subscribe] to events [publish]ed on this event bus.
+ * Subscriptions may not necessarily be delivered in the order of registering.
+ */
+open class FirmamentEventBus<T : FirmamentEvent> {
+ data class Handler<T>(
+ val invocation: (T) -> Unit, val receivesCancelled: Boolean,
+ var knownErrors: MutableSet<Class<*>> = mutableSetOf(),
+ )
+
+ private val toHandle: MutableList<Handler<T>> = CopyOnWriteArrayList()
+ fun subscribe(handle: (T) -> Unit) {
+ subscribe(false, handle)
+ }
+
+ fun subscribe(receivesCancelled: Boolean, handle: (T) -> Unit) {
+ toHandle.add(Handler(handle, receivesCancelled))
+ }
+
+ fun publish(event: T): T {
+ for (function in toHandle) {
+ if (function.receivesCancelled || event !is FirmamentEvent.Cancellable || !event.cancelled) {
+ try {
+ function.invocation(event)
+ } catch (e: Exception) {
+ val klass = e.javaClass
+ if (!function.knownErrors.contains(klass) || Firmament.DEBUG) {
+ function.knownErrors.add(klass)
+ Firmament.logger.error("Caught exception during processing event $event by $function", e)
+ }
+ }
+ }
+ }
+ return event
+ }
+
+ fun publishSync(event: T) {
+ MC.onMainThread {
+ publish(event)
+ }
+ }
+}
diff --git a/src/main/kotlin/events/HandledScreenClickEvent.kt b/src/main/kotlin/events/HandledScreenClickEvent.kt
new file mode 100644
index 0000000..4c3003c
--- /dev/null
+++ b/src/main/kotlin/events/HandledScreenClickEvent.kt
@@ -0,0 +1,10 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.client.gui.screen.ingame.HandledScreen
+
+data class HandledScreenClickEvent(val screen: HandledScreen<*>, val mouseX: Double, val mouseY: Double, val button: Int) :
+ FirmamentEvent.Cancellable() {
+ companion object : FirmamentEventBus<HandledScreenClickEvent>()
+}
diff --git a/src/main/kotlin/events/HandledScreenForegroundEvent.kt b/src/main/kotlin/events/HandledScreenForegroundEvent.kt
new file mode 100644
index 0000000..f16d30e
--- /dev/null
+++ b/src/main/kotlin/events/HandledScreenForegroundEvent.kt
@@ -0,0 +1,16 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.client.gui.DrawContext
+import net.minecraft.client.gui.screen.ingame.HandledScreen
+
+data class HandledScreenForegroundEvent(
+ val screen: HandledScreen<*>,
+ val context: DrawContext,
+ val mouseX: Int,
+ val mouseY: Int,
+ val delta: Float
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<HandledScreenForegroundEvent>()
+}
diff --git a/src/main/kotlin/events/HandledScreenKeyPressedEvent.kt b/src/main/kotlin/events/HandledScreenKeyPressedEvent.kt
new file mode 100644
index 0000000..7ec2abb
--- /dev/null
+++ b/src/main/kotlin/events/HandledScreenKeyPressedEvent.kt
@@ -0,0 +1,24 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.client.gui.screen.ingame.HandledScreen
+import net.minecraft.client.option.KeyBinding
+import moe.nea.firmament.keybindings.IKeyBinding
+
+data class HandledScreenKeyPressedEvent(
+ val screen: HandledScreen<*>,
+ val keyCode: Int,
+ val scanCode: Int,
+ val modifiers: Int
+) : FirmamentEvent.Cancellable() {
+ companion object : FirmamentEventBus<HandledScreenKeyPressedEvent>()
+
+ fun matches(keyBinding: KeyBinding): Boolean {
+ return matches(IKeyBinding.minecraft(keyBinding))
+ }
+
+ fun matches(keyBinding: IKeyBinding): Boolean {
+ return keyBinding.matches(keyCode, scanCode, modifiers)
+ }
+}
diff --git a/src/main/kotlin/events/HandledScreenPushREIEvent.kt b/src/main/kotlin/events/HandledScreenPushREIEvent.kt
new file mode 100644
index 0000000..1bb495a
--- /dev/null
+++ b/src/main/kotlin/events/HandledScreenPushREIEvent.kt
@@ -0,0 +1,18 @@
+
+
+package moe.nea.firmament.events
+
+import me.shedaniel.math.Rectangle
+import net.minecraft.client.gui.screen.ingame.HandledScreen
+
+data class HandledScreenPushREIEvent(
+ val screen: HandledScreen<*>,
+ val rectangles: MutableList<Rectangle> = mutableListOf()
+) : FirmamentEvent() {
+
+ fun block(rectangle: Rectangle) {
+ rectangles.add(rectangle)
+ }
+
+ companion object : FirmamentEventBus<HandledScreenPushREIEvent>()
+}
diff --git a/src/main/kotlin/events/HotbarItemRenderEvent.kt b/src/main/kotlin/events/HotbarItemRenderEvent.kt
new file mode 100644
index 0000000..a1940e6
--- /dev/null
+++ b/src/main/kotlin/events/HotbarItemRenderEvent.kt
@@ -0,0 +1,17 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.client.gui.DrawContext
+import net.minecraft.client.render.RenderTickCounter
+import net.minecraft.item.ItemStack
+
+data class HotbarItemRenderEvent(
+ val item: ItemStack,
+ val context: DrawContext,
+ val x: Int,
+ val y: Int,
+ val tickDelta: RenderTickCounter,
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<HotbarItemRenderEvent>()
+}
diff --git a/src/main/kotlin/events/HudRenderEvent.kt b/src/main/kotlin/events/HudRenderEvent.kt
new file mode 100644
index 0000000..555b3c8
--- /dev/null
+++ b/src/main/kotlin/events/HudRenderEvent.kt
@@ -0,0 +1,13 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.client.gui.DrawContext
+import net.minecraft.client.render.RenderTickCounter
+
+/**
+ * Called when hud elements should be rendered, before the screen, but after the world.
+ */
+data class HudRenderEvent(val context: DrawContext, val tickDelta: RenderTickCounter) : FirmamentEvent() {
+ companion object : FirmamentEventBus<HudRenderEvent>()
+}
diff --git a/src/main/kotlin/events/IsSlotProtectedEvent.kt b/src/main/kotlin/events/IsSlotProtectedEvent.kt
new file mode 100644
index 0000000..cd431f7
--- /dev/null
+++ b/src/main/kotlin/events/IsSlotProtectedEvent.kt
@@ -0,0 +1,46 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.item.ItemStack
+import net.minecraft.screen.slot.Slot
+import net.minecraft.screen.slot.SlotActionType
+import net.minecraft.text.Text
+import moe.nea.firmament.util.CommonSoundEffects
+import moe.nea.firmament.util.MC
+
+data class IsSlotProtectedEvent(
+ val slot: Slot?,
+ val actionType: SlotActionType,
+ var isProtected: Boolean,
+ val itemStackOverride: ItemStack?,
+ var silent: Boolean = false,
+) : FirmamentEvent() {
+ val itemStack get() = itemStackOverride ?: slot!!.stack
+
+ fun protect() {
+ isProtected = true
+ }
+
+ fun protectSilent() {
+ if (!isProtected) {
+ silent = true
+ }
+ isProtected = true
+ }
+
+ companion object : FirmamentEventBus<IsSlotProtectedEvent>() {
+ @JvmStatic
+ @JvmOverloads
+ fun shouldBlockInteraction(slot: Slot?, action: SlotActionType, itemStackOverride: ItemStack? = null): Boolean {
+ if (slot == null && itemStackOverride == null) return false
+ val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride)
+ publish(event)
+ if (event.isProtected && !event.silent) {
+ MC.player?.sendMessage(Text.translatable("firmament.protectitem").append(event.itemStack.name))
+ CommonSoundEffects.playFailure()
+ }
+ return event.isProtected
+ }
+ }
+}
diff --git a/src/main/kotlin/events/ItemTooltipEvent.kt b/src/main/kotlin/events/ItemTooltipEvent.kt
new file mode 100644
index 0000000..d86e06f
--- /dev/null
+++ b/src/main/kotlin/events/ItemTooltipEvent.kt
@@ -0,0 +1,14 @@
+
+
+package moe.nea.firmament.events
+
+import net.minecraft.item.Item.TooltipContext
+import net.minecraft.item.ItemStack
+import net.minecraft.item.tooltip.TooltipType
+import net.minecraft.text.Text
+
+data class ItemTooltipEvent(
+ val stack: ItemStack, val context: TooltipContext, val type: TooltipType, val lines: MutableList<Text>
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<ItemTooltipEvent>()
+}
diff --git a/src/main/kotlin/events/MaskCommands.kt b/src/main/kotlin/events/MaskCommands.kt
new file mode 100644
index 0000000..35aade0
--- /dev/null
+++ b/