diff options
| author | Linnea Gräf <nea@nea.moe> | 2024-08-28 19:04:24 +0200 |
|---|---|---|
| committer | Linnea Gräf <nea@nea.moe> | 2024-08-28 19:04:24 +0200 |
| commit | d2f240ff0ca0d27f417f837e706c781a98c31311 (patch) | |
| tree | 0db7aff6cc14deaf36eed83889d59fd6b3a6f599 /src/main/kotlin/events | |
| parent | a6906308163aa3b2d18fa1dc1aa71ac9bbcc83ab (diff) | |
| download | Firmament-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')
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>() +} |
