diff --git a/.gitignore b/.gitignore index e90cc860..85f7154b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ build .idea -!.idea/icon.svg \ No newline at end of file +!.idea/icon.svg diff --git a/base-common/src/main/java/band/kessoku/lib/base/ModUtils.java b/base-common/src/main/java/band/kessoku/lib/base/ModUtils.java index a4202e08..19b05aae 100644 --- a/base-common/src/main/java/band/kessoku/lib/base/ModUtils.java +++ b/base-common/src/main/java/band/kessoku/lib/base/ModUtils.java @@ -3,7 +3,7 @@ import java.util.ServiceLoader; public class ModUtils { - public static T load(Class clazz) { + public static T loadService(Class clazz) { return ServiceLoader.load(clazz).findFirst().orElseThrow(() -> new AssertionError("No impl found for " + clazz.getName())); } } diff --git a/event-base-neo/src/main/java/band/kessoku/lib/event/KessokuEventBaseEntrypoint.java b/event-base-neo/src/main/java/band/kessoku/lib/event/KessokuEventBaseEntrypoint.java new file mode 100644 index 00000000..b206d012 --- /dev/null +++ b/event-base-neo/src/main/java/band/kessoku/lib/event/KessokuEventBaseEntrypoint.java @@ -0,0 +1,4 @@ +package band.kessoku.lib.event; + +public class KessokuEventBaseEntrypoint { +} diff --git a/event-base-neo/src/main/java/band/kessoku/lib/event/util/NeoEventUtils.java b/event-base-neo/src/main/java/band/kessoku/lib/event/util/NeoEventUtils.java new file mode 100644 index 00000000..52dac82c --- /dev/null +++ b/event-base-neo/src/main/java/band/kessoku/lib/event/util/NeoEventUtils.java @@ -0,0 +1,13 @@ +package band.kessoku.lib.event.util; + +import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; + +import java.util.function.Consumer; + +public class NeoEventUtils { + public static void registerEvent(IEventBus eventBus, Class eventClass, Consumer consumer) { + eventBus.addListener(EventPriority.HIGHEST, eventClass, consumer); + } +} diff --git a/lifecycle-events-common/build.gradle b/lifecycle-events-common/build.gradle new file mode 100644 index 00000000..41bdcad9 --- /dev/null +++ b/lifecycle-events-common/build.gradle @@ -0,0 +1,16 @@ +group = "band.kessoku.lib.event" +version = libs.versions.mod.get() + "+common." + libs.versions.minecraft.get() + +base { + archivesName = rootProject.name + "-lifecycle-events" +} + +architectury { + common(["fabric", "neoforge"]) +} + +dependencies { + modImplementation libs.fabric.loader + implementation(project(":base-common")) + implementation(project(":event-base-common")) +} \ No newline at end of file diff --git a/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEvents.java b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEvents.java new file mode 100644 index 00000000..28fcd3b9 --- /dev/null +++ b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEvents.java @@ -0,0 +1,5 @@ +package band.kessoku.lib.events.lifecycle; + +public class KessokuLifecycleEvents { + public static final String MOD_ID = "kessoku_lifecycle_events"; +} diff --git a/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/LifecycleEvents.java b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/LifecycleEvents.java new file mode 100644 index 00000000..89bde575 --- /dev/null +++ b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/LifecycleEvents.java @@ -0,0 +1,24 @@ +package band.kessoku.lib.events.lifecycle.api; + +import band.kessoku.lib.event.api.Event; +import net.minecraft.registry.DynamicRegistryManager; + +public final class LifecycleEvents { + + /** + * Called when tags are loaded or updated. + */ + public static final Event TAG_LOADED = Event.of(tagLoadeds -> (registries, client) -> { + for (TagLoaded tagLoaded : tagLoadeds) { + tagLoaded.onTagsLoaded(registries, client); + } + }); + + public interface TagLoaded { + /** + * @param registries Up-to-date registries from which the tags can be retrieved. + * @param client True if the client just received a sync packet, false if the server just (re)loaded the tags. + */ + void onTagsLoaded(DynamicRegistryManager registries, boolean client); + } +} diff --git a/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerLifecycleEvents.java b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerLifecycleEvents.java new file mode 100644 index 00000000..6cc953be --- /dev/null +++ b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerLifecycleEvents.java @@ -0,0 +1,192 @@ +package band.kessoku.lib.events.lifecycle.api.server; + +import band.kessoku.lib.event.api.Event; +import net.minecraft.resource.LifecycledResourceManager; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; + +public class ServerLifecycleEvents { + + /** + * Called when a Minecraft server is starting. + * + *

This occurs before the {@link net.minecraft.server.PlayerManager player manager} and any worlds are loaded. + */ + public static final Event STARTING = Event.of(startings -> server -> { + for (Server.Starting serverStarting : startings) { + serverStarting.onServerStarting(server); + } + }); + + /** + * Called when a Minecraft server has started and is about to tick for the first time. + * + *

At this stage, all worlds are live. + */ + public static final Event STARTED = Event.of(starteds -> server -> { + for (Server.Started serverStarted : starteds) { + serverStarted.onServerStarted(server); + } + }); + + /** + * Called when a Minecraft server has started shutting down. + * This occurs before the server's network channel is closed and before any players are disconnected. + * + *

For example, an integrated server will begin stopping, but its client may continue to run. + * + *

All worlds are still present and can be modified. + */ + public static final Event STOPPING = Event.of(stoppings -> server -> { + for (Server.Stopping serverStopping : stoppings) { + serverStopping.onServerStopping(server); + } + }); + + /** + * Called when a Minecraft server has stopped. + * All worlds have been closed and all (block)entities and players have been unloaded. + * + *

For example, an {@link net.fabricmc.api.EnvType#CLIENT integrated server} will begin stopping, but its client may continue to run. + * Meanwhile, for a {@link net.fabricmc.api.EnvType#SERVER dedicated server}, this will be the last event called. + */ + public static final Event STOPPED = Event.of(stoppeds -> server -> { + for (Server.Stopped serverStopped : stoppeds) { + serverStopped.onServerStopped(server); + } + }); + + /** + * Called when a Minecraft server is about to send tag and recipe data to a player. + * @see Datapack.SyncContents + */ + public static final Event SYNC_DATA_PACK_CONTENTS = Event.of(syncContents -> (player, joined) -> { + for (Datapack.SyncContents syncDataPackContents : syncContents) { + syncDataPackContents.onSyncDataPackContents(player, joined); + } + }); + + /** + * Called before a Minecraft server reloads data packs. + */ + public static final Event START_DATA_PACK_RELOAD = Event.of(startReloads -> (server, serverResourceManager) -> { + for (Datapack.StartReload startDataPackReload : startReloads) { + startDataPackReload.startDataPackReload(server, serverResourceManager); + } + }); + + /** + * Called after a Minecraft server has reloaded data packs. + * + *

If reloading data packs was unsuccessful, the current data packs will be kept. + */ + public static final Event END_DATA_PACK_RELOAD = Event.of(endReloads -> (server, serverResourceManager, success) -> { + for (Datapack.EndReload endDataPackReload : endReloads) { + endDataPackReload.endDataPackReload(server, serverResourceManager, success); + } + }); + + /** + * Called before a Minecraft server begins saving data. + */ + public static final Event BEFORE_SAVE = Event.of(befores -> (server, flush, force) -> { + for (SaveData.Before beforeSaveData : befores) { + beforeSaveData.onBeforeSaveData(server, flush, force); + } + }); + + /** + * Called after a Minecraft server finishes saving data. + */ + public static final Event AFTER_SAVE = Event.of(afters -> (server, flush, force) -> { + for (SaveData.After afterSaveData : afters) { + afterSaveData.onAfterSaveData(server, flush, force); + } + }); + + public interface Server { + @FunctionalInterface + interface Starting { + void onServerStarting(MinecraftServer server); + } + + @FunctionalInterface + interface Started { + void onServerStarted(MinecraftServer server); + } + + @FunctionalInterface + interface Stopping { + void onServerStopping(MinecraftServer server); + } + + @FunctionalInterface + interface Stopped { + void onServerStopped(MinecraftServer server); + } + } + + public interface Datapack { + @FunctionalInterface + interface SyncContents { + /** + * Called right before tags and recipes are sent to a player, + * either because the player joined, or because the server reloaded resources. + * The {@linkplain MinecraftServer#getResourceManager() server resource manager} is up-to-date when this is called. + * + *

For example, this event can be used to sync data loaded with custom resource reloaders. + * + * @param player Player to which the data is being sent. + * @param joined True if the player is joining the server, false if the server finished a successful resource reload. + */ + void onSyncDataPackContents(ServerPlayerEntity player, boolean joined); + } + + @FunctionalInterface + interface StartReload { + void startDataPackReload(MinecraftServer server, LifecycledResourceManager resourceManager); + } + + @FunctionalInterface + interface EndReload { + /** + * Called after data packs on a Minecraft server have been reloaded. + * + *

If the reload was not successful, the old data packs will be kept. + * + * @param server the server + * @param resourceManager the resource manager + * @param success if the reload was successful + */ + void endDataPackReload(MinecraftServer server, LifecycledResourceManager resourceManager, boolean success); + } + } + + public interface SaveData { + @FunctionalInterface + interface Before { + /** + * Called before a Minecraft server begins saving data. + * + * @param server the server + * @param flush is true when all chunks are being written to disk, server will likely freeze during this time + * @param force whether servers that have save-off set should save + */ + void onBeforeSaveData(MinecraftServer server, boolean flush, boolean force); + } + + @FunctionalInterface + interface After { + /** + * Called after a Minecraft server begins saving data. + * + * @param server the server + * @param flush is true when all chunks are being written to disk, server will likely freeze during this time + * @param force whether servers that have save-off set should save + */ + void onAfterSaveData(MinecraftServer server, boolean flush, boolean force); + } + } + + +} diff --git a/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerTickEvents.java b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerTickEvents.java new file mode 100644 index 00000000..b1ffa9e6 --- /dev/null +++ b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerTickEvents.java @@ -0,0 +1,70 @@ +package band.kessoku.lib.events.lifecycle.api.server; + +import band.kessoku.lib.event.api.Event; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; + +public final class ServerTickEvents { + + /** + * Called at the start of the server tick. + */ + public static final Event START_SERVER_TICK = Event.of(starts -> server -> { + for (ServerTick.Start start : starts) { + start.onStartTick(server); + } + }); + + /** + * Called at the end of the server tick. + */ + public static final Event END_SERVER_TICK = Event.of(ends -> server -> { + for (ServerTick.End end : ends) { + end.onEndTick(server); + } + }); + + /** + * Called at the start of a ServerWorld's tick. + */ + public static final Event START_WORLD_TICK = Event.of(starts -> world -> { + for (WorldTick.Start start : starts) { + start.onStartTick(world); + } + }); + + /** + * Called at the end of a ServerWorld's tick. + * + *

End of world tick may be used to start async computations for the next tick. + */ + public static final Event END_WORLD_TICK = Event.of(ends -> world -> { + for (WorldTick.End callback : ends) { + callback.onEndTick(world); + } + }); + + public interface ServerTick { + @FunctionalInterface + interface Start { + void onStartTick(MinecraftServer server); + } + + @FunctionalInterface + interface End { + void onEndTick(MinecraftServer server); + } + } + + public interface WorldTick { + @FunctionalInterface + interface Start { + void onStartTick(ServerWorld world); + } + + @FunctionalInterface + interface End { + void onEndTick(ServerWorld world); + } + } +} diff --git a/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerWorldEvents.java b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerWorldEvents.java new file mode 100644 index 00000000..784ff429 --- /dev/null +++ b/lifecycle-events-common/src/main/java/band/kessoku/lib/events/lifecycle/api/server/ServerWorldEvents.java @@ -0,0 +1,41 @@ +package band.kessoku.lib.events.lifecycle.api.server; + +import band.kessoku.lib.event.api.Event; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; + +public class ServerWorldEvents { + + /** + * Called just after a world is loaded by a Minecraft server. + * + *

This can be used to load world specific metadata or initialize a {@link net.minecraft.world.PersistentState} on a server world. + */ + public static final Event LOADED = Event.of(loadeds -> (server, world) -> { + for (Loaded loaded : loadeds) { + loaded.onWorldLoaded(server, world); + } + }); + + /** + * Called before a world is unloaded by a Minecraft server. + * + *

This typically occurs after a server has {@link ServerLifecycleEvents#STOPPING started shutting down}. + * Mods which allow dynamic world (un)registration should call this event so mods can let go of world handles when a world is removed. + */ + public static final Event UNLOADED = Event.of(unloadeds -> (server, world) -> { + for (Unloaded unloaded : unloadeds) { + unloaded.onWorldUnloaded(server, world); + } + }); + + @FunctionalInterface + public interface Loaded { + void onWorldLoaded(MinecraftServer server, ServerWorld world); + } + + @FunctionalInterface + public interface Unloaded { + void onWorldUnloaded(MinecraftServer server, ServerWorld world); + } +} diff --git a/lifecycle-events-fabric/build.gradle b/lifecycle-events-fabric/build.gradle new file mode 100644 index 00000000..a6d3402d --- /dev/null +++ b/lifecycle-events-fabric/build.gradle @@ -0,0 +1,56 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +group = "band.kessoku.lib.event" +version = libs.versions.mod.get() + "+fabric." + libs.versions.minecraft.get() + +base { + archivesName = rootProject.name + "-lifecycle-events" +} + +architectury { + platformSetupLoomIde() + fabric() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentFabric.extendsFrom common + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + modImplementation libs.fabric.loader + modImplementation libs.fabric.api + + implementation(project(":event-base-common")) + + common(project(path: ':lifecycle-events-common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':lifecycle-events-common', configuration: 'transformProductionFabric') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('fabric.mod.json') { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} \ No newline at end of file diff --git a/lifecycle-events-fabric/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEventsEntrypoints.java b/lifecycle-events-fabric/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEventsEntrypoints.java new file mode 100644 index 00000000..5348c0de --- /dev/null +++ b/lifecycle-events-fabric/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEventsEntrypoints.java @@ -0,0 +1,11 @@ +package band.kessoku.lib.events.lifecycle; + +import band.kessoku.lib.events.lifecycle.impl.KessokuLifecycleEventsImpl; +import net.fabricmc.api.ModInitializer; + +public class KessokuLifecycleEventsEntrypoints implements ModInitializer { + @Override + public void onInitialize() { + KessokuLifecycleEventsImpl.registerCommonEvents(); + } +} diff --git a/lifecycle-events-fabric/src/main/java/band/kessoku/lib/events/lifecycle/impl/KessokuLifecycleEventsImpl.java b/lifecycle-events-fabric/src/main/java/band/kessoku/lib/events/lifecycle/impl/KessokuLifecycleEventsImpl.java new file mode 100644 index 00000000..3ef1cc9d --- /dev/null +++ b/lifecycle-events-fabric/src/main/java/band/kessoku/lib/events/lifecycle/impl/KessokuLifecycleEventsImpl.java @@ -0,0 +1,28 @@ +package band.kessoku.lib.events.lifecycle.impl; + +import band.kessoku.lib.events.lifecycle.api.LifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.CommonLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; + +public class KessokuLifecycleEventsImpl { + public static void registerCommonEvents() { + CommonLifecycleEvents.TAGS_LOADED.register((registries, client) -> LifecycleEvents.TAG_LOADED.invoker().onTagsLoaded(registries, client)); + + ServerLifecycleEvents.SERVER_STARTING.register(server -> band.kessoku.lib.events.lifecycle.api.server.ServerLifecycleEvents.STARTING.invoker().onServerStarting(server)); + ServerLifecycleEvents.SERVER_STARTED.register(server -> band.kessoku.lib.events.lifecycle.api.server.ServerLifecycleEvents.STARTED.invoker().onServerStarted(server)); + ServerLifecycleEvents.SERVER_STOPPING.register(server -> band.kessoku.lib.events.lifecycle.api.server.ServerLifecycleEvents.STOPPING.invoker().onServerStopping(server)); + ServerLifecycleEvents.SERVER_STOPPED.register(server -> band.kessoku.lib.events.lifecycle.api.server.ServerLifecycleEvents.STOPPED.invoker().onServerStopped(server)); + + ServerTickEvents.START_SERVER_TICK.register(server -> band.kessoku.lib.events.lifecycle.api.server.ServerTickEvents.START_SERVER_TICK.invoker().onStartTick(server)); + ServerTickEvents.END_SERVER_TICK.register(server -> band.kessoku.lib.events.lifecycle.api.server.ServerTickEvents.END_SERVER_TICK.invoker().onEndTick(server)); + ServerTickEvents.START_WORLD_TICK.register(world -> band.kessoku.lib.events.lifecycle.api.server.ServerTickEvents.START_WORLD_TICK.invoker().onStartTick(world)); + ServerTickEvents.END_WORLD_TICK.register(world -> band.kessoku.lib.events.lifecycle.api.server.ServerTickEvents.END_WORLD_TICK.invoker().onEndTick(world)); + + ServerWorldEvents.LOAD.register((server, world) -> band.kessoku.lib.events.lifecycle.api.server.ServerWorldEvents.LOADED.invoker().onWorldLoaded(server, world)); + ServerWorldEvents.UNLOAD.register((server, world) -> band.kessoku.lib.events.lifecycle.api.server.ServerWorldEvents.UNLOADED.invoker().onWorldUnloaded(server, world)); + + ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.register((player, joined) -> band.kessoku.lib.events.lifecycle.api.server.ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.invoker().onSyncDataPackContents(player, joined)); + } +} diff --git a/lifecycle-events-neo/build.gradle b/lifecycle-events-neo/build.gradle new file mode 100644 index 00000000..a47865b0 --- /dev/null +++ b/lifecycle-events-neo/build.gradle @@ -0,0 +1,60 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +group = "band.kessoku.lib.event" +version = libs.versions.mod.get() + "+neoforge." + libs.versions.minecraft.get() + +base { + archivesName = rootProject.name + "-lifecycle-events" +} + +architectury { + platformSetupLoomIde() + neoForge() +} + +repositories { + maven { url "https://maven.neoforged.net/releases/" } +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentNeoForge.extendsFrom common + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + neoForge libs.neo + + implementation(project(":event-base-common")) + implementation(project(":event-base-neo")) + + common(project(path: ':lifecycle-events-common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':lifecycle-events-common', configuration: 'transformProductionNeoForge') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/neoforge.mods.toml') { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} \ No newline at end of file diff --git a/lifecycle-events-neo/gradle.properties b/lifecycle-events-neo/gradle.properties new file mode 100644 index 00000000..2914393d --- /dev/null +++ b/lifecycle-events-neo/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/lifecycle-events-neo/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEventsEntrypoint.java b/lifecycle-events-neo/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEventsEntrypoint.java new file mode 100644 index 00000000..05c36477 --- /dev/null +++ b/lifecycle-events-neo/src/main/java/band/kessoku/lib/events/lifecycle/KessokuLifecycleEventsEntrypoint.java @@ -0,0 +1,16 @@ +package band.kessoku.lib.events.lifecycle; + +import band.kessoku.lib.events.lifecycle.impl.KessokuLifecycleEventsImpl; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.common.NeoForge; + +@Mod(KessokuLifecycleEvents.MOD_ID) +public class KessokuLifecycleEventsEntrypoint { + public KessokuLifecycleEventsEntrypoint(IEventBus modEventBus, ModContainer modContainer) { + var forgeEventBus = NeoForge.EVENT_BUS; + + KessokuLifecycleEventsImpl.registerCommonEvents(modEventBus, forgeEventBus); + } +} diff --git a/lifecycle-events-neo/src/main/java/band/kessoku/lib/events/lifecycle/impl/KessokuLifecycleEventsImpl.java b/lifecycle-events-neo/src/main/java/band/kessoku/lib/events/lifecycle/impl/KessokuLifecycleEventsImpl.java new file mode 100644 index 00000000..e168fe4c --- /dev/null +++ b/lifecycle-events-neo/src/main/java/band/kessoku/lib/events/lifecycle/impl/KessokuLifecycleEventsImpl.java @@ -0,0 +1,82 @@ +package band.kessoku.lib.events.lifecycle.impl; + +import band.kessoku.lib.event.util.NeoEventUtils; +import band.kessoku.lib.events.lifecycle.api.LifecycleEvents; +import band.kessoku.lib.events.lifecycle.api.server.ServerLifecycleEvents; +import band.kessoku.lib.events.lifecycle.api.server.ServerTickEvents; +import band.kessoku.lib.events.lifecycle.api.server.ServerWorldEvents; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.server.world.ServerWorld; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.event.OnDatapackSyncEvent; +import net.neoforged.neoforge.event.TagsUpdatedEvent; +import net.neoforged.neoforge.event.level.LevelEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppedEvent; +import net.neoforged.neoforge.event.server.ServerStoppingEvent; +import net.neoforged.neoforge.event.tick.LevelTickEvent; +import net.neoforged.neoforge.event.tick.ServerTickEvent; + +public class KessokuLifecycleEventsImpl { + public static void registerClientEvents(IEventBus modEventBus, IEventBus forgeEventBus) { + + } + + public static void registerCommonEvents(IEventBus modEventBus, IEventBus forgeEventBus) { + NeoEventUtils.registerEvent(forgeEventBus, TagsUpdatedEvent.class, event -> { + LifecycleEvents.TAG_LOADED.invoker().onTagsLoaded(event.getRegistryAccess(), event.getUpdateCause() == TagsUpdatedEvent.UpdateCause.CLIENT_PACKET_RECEIVED); + }); + + NeoEventUtils.registerEvent(forgeEventBus, ServerStartingEvent.class, event -> { + ServerLifecycleEvents.STARTING.invoker().onServerStarting(event.getServer()); + }); + NeoEventUtils.registerEvent(forgeEventBus, ServerStartedEvent.class, event -> { + ServerLifecycleEvents.STARTED.invoker().onServerStarted(event.getServer()); + }); + NeoEventUtils.registerEvent(forgeEventBus, ServerStoppingEvent.class, event -> { + ServerLifecycleEvents.STOPPING.invoker().onServerStopping(event.getServer()); + }); + NeoEventUtils.registerEvent(forgeEventBus, ServerStoppedEvent.class, event -> { + ServerLifecycleEvents.STOPPED.invoker().onServerStopped(event.getServer()); + }); + + NeoEventUtils.registerEvent(forgeEventBus, ServerTickEvent.Pre.class, event -> { + ServerTickEvents.START_SERVER_TICK.invoker().onStartTick(event.getServer()); + }); + NeoEventUtils.registerEvent(forgeEventBus, ServerTickEvent.Post.class, event -> { + ServerTickEvents.END_SERVER_TICK.invoker().onEndTick(event.getServer()); + }); + NeoEventUtils.registerEvent(forgeEventBus, LevelTickEvent.Pre.class, event -> { + if (event.getLevel() instanceof ServerWorld world) { + ServerTickEvents.START_WORLD_TICK.invoker().onStartTick(world); + } + }); + NeoEventUtils.registerEvent(forgeEventBus, LevelTickEvent.Post.class, event -> { + if (event.getLevel() instanceof ServerWorld world) { + ServerTickEvents.END_WORLD_TICK.invoker().onEndTick(world); + } + }); + + NeoEventUtils.registerEvent(forgeEventBus, LevelEvent.Load.class, event -> { + if (event.getLevel() instanceof ServerWorld world) { + ServerWorldEvents.LOADED.invoker().onWorldLoaded(world.getServer(), world); + } + }); + NeoEventUtils.registerEvent(forgeEventBus, LevelEvent.Unload.class, event -> { + if (event.getLevel() instanceof ServerWorld world) { + ServerWorldEvents.UNLOADED.invoker().onWorldUnloaded(world.getServer(), world); + } + }); + + NeoEventUtils.registerEvent(forgeEventBus, OnDatapackSyncEvent.class, event -> { + if (event.getPlayer() != null) { + ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.invoker().onSyncDataPackContents(event.getPlayer(), true); + } else { + for (ServerPlayerEntity player : event.getPlayerList().getPlayerList()) { + ServerLifecycleEvents.SYNC_DATA_PACK_CONTENTS.invoker().onSyncDataPackContents(player, false); + } + } + }); + } +} diff --git a/platform-common/src/main/java/band/kessoku/lib/platform/impl/KessokuPlatformServices.java b/platform-common/src/main/java/band/kessoku/lib/platform/impl/KessokuPlatformServices.java index 5a56e710..25657d25 100644 --- a/platform-common/src/main/java/band/kessoku/lib/platform/impl/KessokuPlatformServices.java +++ b/platform-common/src/main/java/band/kessoku/lib/platform/impl/KessokuPlatformServices.java @@ -4,7 +4,7 @@ import band.kessoku.lib.platform.api.ModLoader; public class KessokuPlatformServices { - private static final ModLoader modLoader = ModUtils.load(ModLoader.class); + private static final ModLoader modLoader = ModUtils.loadService(ModLoader.class); public static ModLoader getModLoader() { return modLoader; diff --git a/settings.gradle b/settings.gradle index 15d3ff7d..f92acb38 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,4 +13,5 @@ include("fabric", "neo") // Bundle modules include("base-common", "base-fabric", "base-neo") // Base include("event-base-common", "event-base-fabric", "event-base-neo") // Event Base include("platform-common", "platform-fabric", "platform-neo") // Platform +include("lifecycle-events-common", "lifecycle-events-fabric", "lifecycle-events-neo") // Lifecycle Events include("command-api-common", "command-api-fabric", "command-api-neo") // Command API