diff --git a/cloud-fabric/build.gradle.kts b/cloud-fabric/build.gradle.kts index 25a06889..a80d901b 100644 --- a/cloud-fabric/build.gradle.kts +++ b/cloud-fabric/build.gradle.kts @@ -38,7 +38,6 @@ dependencies { api(libs.cloud.brigadier) compileOnly(libs.cloud.minecraft.signed.arguments) - modCompileOnly(libs.adventureFabric) offlineLinkedJavadoc(project(":cloud-minecraft-modded-common")) localRuntime(project(":cloud-minecraft-modded-common", configuration = "namedElements")) @@ -92,9 +91,16 @@ val testmod: SourceSet by sourceSets.creating { dependencies.add(implementationConfigurationName, main.output) } +loom { + createRemapConfigurations(testmod) +} + dependencies { localRuntime(libs.cloud.minecraft.signed.arguments) modLocalRuntime(libs.adventureFabric) + "modTestmodImplementation"(libs.adventureFabric) + "testmodImplementation"(libs.cloud.minecraft.extras) + localRuntime(libs.cloud.minecraft.extras) } val testmodJar by tasks.registering(Jar::class) { diff --git a/cloud-fabric/src/main/java/org/incendo/cloud/fabric/internal/CloudFabricEntrypoint.java b/cloud-fabric/src/main/java/org/incendo/cloud/fabric/internal/CloudFabricEntrypoint.java new file mode 100644 index 00000000..507f8c84 --- /dev/null +++ b/cloud-fabric/src/main/java/org/incendo/cloud/fabric/internal/CloudFabricEntrypoint.java @@ -0,0 +1,58 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.fabric.internal; + +import java.util.Objects; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.loader.api.FabricLoader; +import org.apiguardian.api.API; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.incendo.cloud.minecraft.modded.internal.AdventureSupport; + +@API(status = API.Status.INTERNAL) +@DefaultQualifier(NonNull.class) +public final class CloudFabricEntrypoint implements ModInitializer { + + @SuppressWarnings("EmptyCatch") + @Override + public void onInitialize() { + if (FabricLoader.getInstance().isModLoaded("adventure-platform-fabric")) { + try { + Objects.requireNonNull( + Class.forName("net.kyori.adventure.platform.modcommon.MinecraftAudiences").getName() + ); + + ServerLifecycleEvents.SERVER_STARTING.register(AdventureSupport.get()::setupServer); + ServerLifecycleEvents.SERVER_STOPPED.register(AdventureSupport.get()::removeServer); + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + AdventureSupport.get().setupClient(); + } + } catch (final ClassNotFoundException ignored) { + } + } + } +} diff --git a/cloud-fabric/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory b/cloud-fabric/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory deleted file mode 100644 index 399dc361..00000000 --- a/cloud-fabric/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory +++ /dev/null @@ -1 +0,0 @@ -org.incendo.cloud.fabric.internal.FabricSignedStringFactory diff --git a/cloud-fabric/src/main/resources/fabric.mod.json b/cloud-fabric/src/main/resources/fabric.mod.json index 66bd62b2..0570c049 100644 --- a/cloud-fabric/src/main/resources/fabric.mod.json +++ b/cloud-fabric/src/main/resources/fabric.mod.json @@ -15,7 +15,8 @@ "entrypoints": { "main": [ - "org.incendo.cloud.fabric.internal.LateRegistrationCatcher" + "org.incendo.cloud.fabric.internal.LateRegistrationCatcher", + "org.incendo.cloud.fabric.internal.CloudFabricEntrypoint" ] }, diff --git a/cloud-fabric/src/testmod/java/org/incendo/cloud/fabric/testmod/FabricExample.java b/cloud-fabric/src/testmod/java/org/incendo/cloud/fabric/testmod/FabricExample.java index 27cbfcca..856be9f5 100644 --- a/cloud-fabric/src/testmod/java/org/incendo/cloud/fabric/testmod/FabricExample.java +++ b/cloud-fabric/src/testmod/java/org/incendo/cloud/fabric/testmod/FabricExample.java @@ -27,16 +27,18 @@ import java.util.Collection; import java.util.Comparator; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.metadata.ModMetadata; import net.fabricmc.loader.api.metadata.Person; import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.identity.Identity; -import net.kyori.adventure.platform.fabric.AdventureCommandSourceStack; -import net.kyori.adventure.platform.fabric.FabricServerAudiences; +import net.kyori.adventure.platform.modcommon.AdventureCommandSourceStack; +import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences; import net.kyori.adventure.text.minimessage.MiniMessage; import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; @@ -61,9 +63,9 @@ import org.incendo.cloud.fabric.FabricServerCommandManager; import org.incendo.cloud.fabric.testmod.mixin.GiveCommandAccess; import org.incendo.cloud.key.CloudKey; +import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler; import org.incendo.cloud.minecraft.modded.data.Coordinates; import org.incendo.cloud.minecraft.modded.data.Coordinates.ColumnCoordinates; -import org.incendo.cloud.minecraft.modded.data.MultipleEntitySelector; import org.incendo.cloud.minecraft.modded.data.MultiplePlayerSelector; import org.incendo.cloud.minecraft.modded.parser.NamedColorParser; import org.incendo.cloud.minecraft.modded.parser.RegistryEntryParser; @@ -89,6 +91,11 @@ public void onInitialize() { final FabricServerCommandManager manager = FabricServerCommandManager.createNative(ExecutionCoordinator.simpleCoordinator()); + AtomicReference audiences = new AtomicReference<>(); + ServerLifecycleEvents.SERVER_STARTING.register((server) -> audiences.set(MinecraftServerAudiences.of(server))); + MinecraftExceptionHandler.create(stack -> audiences.get().audience(stack)) + .registerTo(manager); + final Command.Builder base = manager.commandBuilder("cloudtest"); final CloudKey name = CloudKey.of("name", String.class); @@ -224,7 +231,8 @@ public void onInitialize() { .map(Suggestion::suggestion) .collect(Collectors.toList()))) .parser((commandContext, commandInput) -> { - final ModMetadata meta = FabricLoader.getInstance().getModContainer(commandInput.readString()) + final String s = commandInput.readString(); + final ModMetadata meta = FabricLoader.getInstance().getModContainer(s) .map(ModContainer::getMetadata) .orElse(null); if (meta != null) { @@ -232,7 +240,7 @@ public void onInitialize() { } return ArgumentParseResult.failure(new IllegalArgumentException(String.format( "No mod with id '%s'", - commandInput.peek() + s ))); }) .build(); @@ -269,7 +277,7 @@ public void onInitialize() { .required("targets", multiplePlayerSelectorParser()) .required("location", vec3Parser(false)) .handler(ctx -> { - final MultipleEntitySelector selector = ctx.get("targets"); + final MultiplePlayerSelector selector = ctx.get("targets"); final Vec3 location = ctx.get("location").position(); selector.values().forEach(target -> { target.placePortalTicket(new BlockPos(Mth.floor(location.x()), Mth.floor(location.y()), Mth.floor(location.z()))); @@ -281,7 +289,7 @@ public void onInitialize() { .required("message", signedGreedyStringParser()) .handler(ctx -> { final AdventureCommandSourceStack audience = - FabricServerAudiences.of(ctx.sender().getServer()).audience(ctx.sender()); + MinecraftServerAudiences.of(ctx.sender().getServer()).audience(ctx.sender()); final SignedString message = ctx.get("message"); diff --git a/cloud-minecraft-modded-common/build.gradle.kts b/cloud-minecraft-modded-common/build.gradle.kts index 6b5248ee..e693c82c 100644 --- a/cloud-minecraft-modded-common/build.gradle.kts +++ b/cloud-minecraft-modded-common/build.gradle.kts @@ -11,6 +11,9 @@ dependencies { minecraft(libs.minecraft) mappings(loom.officialMojangMappings()) compileOnly(libs.fabricLoader) + + compileOnly(libs.adventureMod) + compileOnly(libs.cloud.minecraft.extras) } tasks.withType(AbstractRemapJarTask::class).configureEach { diff --git a/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/AdventureSupport.java b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/AdventureSupport.java new file mode 100644 index 00000000..efcc1209 --- /dev/null +++ b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/AdventureSupport.java @@ -0,0 +1,108 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.minecraft.modded.internal; + +import java.util.Objects; +import net.kyori.adventure.platform.modcommon.MinecraftAudiences; +import net.kyori.adventure.platform.modcommon.MinecraftClientAudiences; +import net.kyori.adventure.platform.modcommon.MinecraftServerAudiences; +import net.minecraft.server.MinecraftServer; +import org.apiguardian.api.API; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; + +@API(status = API.Status.INTERNAL) +@DefaultQualifier(NonNull.class) +public final class AdventureSupport { + private static final AdventureSupport INSTANCE; + + static { + INSTANCE = new AdventureSupport(); + INSTANCE.setupConverter(); + } + + private @Nullable MinecraftAudiences client; + private @Nullable MinecraftAudiences server; + + private AdventureSupport() { + } + + @SuppressWarnings("EmptyCatch") + private void setupConverter() { + try { + ComponentMessageThrowableConverter.setup(this); + } catch (final LinkageError ignored) { + // cloud-minecraft-extras not present + } + } + + /** + * Set up the client audience. + */ + public void setupClient() { + this.client = MinecraftClientAudiences.of(); + } + + /** + * Set up the server audience. + * + * @param server server + */ + public void setupServer(final MinecraftServer server) { + this.server = MinecraftServerAudiences.of(server); + } + + /** + * Shutdown the server audience. + * + * @param server server + */ + @SuppressWarnings("unused") + public void removeServer(final MinecraftServer server) { + this.server = null; + } + + /** + * Get the MinecraftAudiences instance. + * + * @return audiences + */ + public MinecraftAudiences audiences() { + final @Nullable MinecraftAudiences server = this.server; + if (server == null) { + return Objects.requireNonNull(this.client, "No audiences present"); + } + return server; + } + + /** + * Returns the AdventureSupport instance. + * + * @return the instance + */ + public static AdventureSupport get() { + return INSTANCE; + } +} diff --git a/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ComponentMessageThrowableConverter.java b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ComponentMessageThrowableConverter.java new file mode 100644 index 00000000..9a45df80 --- /dev/null +++ b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ComponentMessageThrowableConverter.java @@ -0,0 +1,55 @@ +// +// MIT License +// +// Copyright (c) 2024 Incendo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package org.incendo.cloud.minecraft.modded.internal; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.apiguardian.api.API; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler; + +@API(status = API.Status.INTERNAL) +@DefaultQualifier(NonNull.class) +final class ComponentMessageThrowableConverter implements MinecraftExceptionHandler.ComponentMessageThrowableConverter { + + private final AdventureSupport adventureSupport; + + ComponentMessageThrowableConverter(final AdventureSupport adventureSupport) { + this.adventureSupport = adventureSupport; + } + + static void setup(final AdventureSupport adventureSupport) { + MinecraftExceptionHandler.ComponentMessageThrowableConverterHolder.converter( + new ComponentMessageThrowableConverter(adventureSupport) + ); + } + + @Override + public Throwable maybeConvert(final Throwable thr) { + if (thr instanceof CommandSyntaxException cse) { + return (Exception) this.adventureSupport.audiences().asComponentThrowable(cse); + } + return thr; + } +} diff --git a/cloud-fabric/src/main/java/org/incendo/cloud/fabric/internal/FabricSignedStringFactory.java b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringFactory.java similarity index 82% rename from cloud-fabric/src/main/java/org/incendo/cloud/fabric/internal/FabricSignedStringFactory.java rename to cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringFactory.java index 53376a00..b81f1397 100644 --- a/cloud-fabric/src/main/java/org/incendo/cloud/fabric/internal/FabricSignedStringFactory.java +++ b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringFactory.java @@ -21,21 +21,30 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // -package org.incendo.cloud.fabric.internal; +package org.incendo.cloud.minecraft.modded.internal; +import java.util.Objects; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.chat.ChatType; import net.kyori.adventure.chat.SignedMessage; -import net.kyori.adventure.platform.fabric.impl.NonWrappingComponentSerializer; +import net.kyori.adventure.platform.modcommon.MinecraftAudiences; import net.kyori.adventure.text.Component; import net.minecraft.network.chat.PlayerChatMessage; import org.apiguardian.api.API; import org.checkerframework.checker.nullness.qual.Nullable; -import org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper; import org.incendo.cloud.minecraft.signed.SignedString; @API(status = API.Status.INTERNAL) -public final class FabricSignedStringFactory implements ModdedSignedStringMapper.SignedStringFactory { +public final class ModdedSignedStringFactory implements ModdedSignedStringMapper.SignedStringFactory { + + /** + * Creates a new {@link ModdedSignedStringFactory}. + */ + public ModdedSignedStringFactory() { + // Trigger service load failure when this isn't present + Objects.requireNonNull(MinecraftAudiences.class.getName()); + } + @Override public SignedString create(final String str, final PlayerChatMessage signedMessage) { return new SignedStringImpl(str, signedMessage); @@ -55,7 +64,8 @@ private static SignedMessage cast(final PlayerChatMessage message) { @Override public void sendMessage(final Audience audience, final ChatType.Bound chatType, final Component unsigned) { - final net.minecraft.network.chat.Component nativeComponent = NonWrappingComponentSerializer.INSTANCE.serialize(unsigned); + final net.minecraft.network.chat.Component nativeComponent = + AdventureSupport.get().audiences().asNative(unsigned); final PlayerChatMessage playerChatMessage = this.rawSignedMessage.withUnsignedContent(nativeComponent); audience.sendMessage(cast(playerChatMessage), chatType); } diff --git a/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringMapper.java b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringMapper.java index 8c781c37..ecb57229 100644 --- a/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringMapper.java +++ b/cloud-minecraft-modded-common/src/main/java/org/incendo/cloud/minecraft/modded/internal/ModdedSignedStringMapper.java @@ -49,7 +49,7 @@ public final class ModdedSignedStringMapper implements SignedStringMapper { * Creates a new mapper. */ public ModdedSignedStringMapper() { - this.factory = Services.service(SignedStringFactory.class) + this.factory = Services.serviceWithFallback(SignedStringFactory.class) .orElseThrow(() -> new IllegalStateException("Could not locate " + SignedStringFactory.class)); } @@ -103,4 +103,12 @@ public interface SignedStringFactory { */ SignedString create(String str, PlayerChatMessage signedMessage); } + + public static final class FallbackSignedStringFactory implements SignedStringFactory, Services.Fallback { + + @Override + public SignedString create(final String str, final PlayerChatMessage signedMessage) { + return SignedString.unsigned(str); + } + } } diff --git a/cloud-minecraft-modded-common/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory b/cloud-minecraft-modded-common/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory new file mode 100644 index 00000000..452dc236 --- /dev/null +++ b/cloud-minecraft-modded-common/src/main/resources/META-INF/services/org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$SignedStringFactory @@ -0,0 +1,2 @@ +org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringFactory +org.incendo.cloud.minecraft.modded.internal.ModdedSignedStringMapper$FallbackSignedStringFactory diff --git a/cloud-neoforge/src/main/java/org/incendo/cloud/neoforge/CloudNeoForgeEntrypoint.java b/cloud-neoforge/src/main/java/org/incendo/cloud/neoforge/CloudNeoForgeEntrypoint.java index 932ec196..ecd750f3 100644 --- a/cloud-neoforge/src/main/java/org/incendo/cloud/neoforge/CloudNeoForgeEntrypoint.java +++ b/cloud-neoforge/src/main/java/org/incendo/cloud/neoforge/CloudNeoForgeEntrypoint.java @@ -31,9 +31,13 @@ import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModList; import net.neoforged.fml.common.Mod; +import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.server.permission.events.PermissionGatherEvent; import net.neoforged.neoforge.server.permission.nodes.PermissionDynamicContext; import net.neoforged.neoforge.server.permission.nodes.PermissionNode; @@ -43,6 +47,7 @@ import org.incendo.cloud.Command; import org.incendo.cloud.execution.ExecutionCoordinator; import org.incendo.cloud.internal.CommandNode; +import org.incendo.cloud.minecraft.modded.internal.AdventureSupport; import org.incendo.cloud.permission.AndPermission; import org.incendo.cloud.permission.OrPermission; import org.incendo.cloud.permission.Permission; @@ -58,8 +63,22 @@ public final class CloudNeoForgeEntrypoint { /** * Creates a {@link CloudNeoForgeEntrypoint}. + * + * @param modBus mod event bus */ - public CloudNeoForgeEntrypoint() { + public CloudNeoForgeEntrypoint(final IEventBus modBus) { + if (ModList.get().isLoaded("adventure_platform_neoforge")) { + NeoForge.EVENT_BUS.addListener((ServerStartingEvent event) -> { + AdventureSupport.get().setupServer(event.getServer()); + }); + NeoForge.EVENT_BUS.addListener((ServerStoppedEvent event) -> { + AdventureSupport.get().removeServer(event.getServer()); + }); + modBus.addListener(FMLClientSetupEvent.class, event -> { + AdventureSupport.get().setupClient(); + }); + } + NeoForge.EVENT_BUS.addListener(EventPriority.HIGHEST, (ServerStartingEvent event) -> serverStartingCalled = true); NeoForge.EVENT_BUS.addListener(EventPriority.LOW, CloudNeoForgeEntrypoint::registerPermissions); diff --git a/cloud-neoforge/src/main/resources/META-INF/neoforge.mods.toml b/cloud-neoforge/src/main/resources/META-INF/neoforge.mods.toml index 82a733f7..cb280aca 100644 --- a/cloud-neoforge/src/main/resources/META-INF/neoforge.mods.toml +++ b/cloud-neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -27,5 +27,11 @@ versionRange = "[1.20.5,)" ordering = "NONE" side = "BOTH" +[[dependencies.cloud]] +modId = "adventure_platform_neoforge" +type = "optional" +ordering = "AFTER" +side = "BOTH" + [[mixins]] config = "cloud.mixins.json" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b93fbdaf..dc8afbf4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,6 +14,7 @@ minecraft = "1.21.3" fabricLoader = "0.16.9" fabricApi = "0.110.0+1.21.3" fabricPermissionsApi = "0.3.3" +adventureMod = "6.1.0" [libraries] cloud-build-logic = { module = "org.incendo:cloud-build-logic", version.ref = "cloud-build-logic" } @@ -25,8 +26,10 @@ cloud-minecraft-bom = { module = "org.incendo:cloud-minecraft-bom", version.ref cloud-core = { module = "org.incendo:cloud-core", version.ref = "cloud" } cloud-brigadier = { module = "org.incendo:cloud-brigadier", version.ref = "cloudMinecraft" } cloud-minecraft-signed-arguments = { module = "org.incendo:cloud-minecraft-signed-arguments", version.ref = "cloudMinecraft" } -adventureApi = { group = "net.kyori", name = "adventure-api", version = "4.15.0" } -adventureFabric = "net.kyori:adventure-platform-fabric:5.13.0" +cloud-minecraft-extras = { module = "org.incendo:cloud-minecraft-extras", version.ref = "cloudMinecraft" } +adventureApi = { group = "net.kyori", name = "adventure-api", version = "4.17.0" } +adventureMod = { module = "net.kyori:adventure-platform-mod-shared", version.ref = "adventureMod" } +adventureFabric = { module = "net.kyori:adventure-platform-fabric", version.ref = "adventureMod" } immutables = { group = "org.immutables", name = "value", version.ref = "immutables" } immutablesAnnotate = { group = "org.immutables", name = "annotate", version.ref = "immutables" }