diff --git a/build.gradle.kts b/build.gradle.kts index f90ce9c9..111d7a37 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,6 @@ plugins { alias(libs.plugins.loom) apply false alias(libs.plugins.spotless) alias(libs.plugins.indra.spotlessLicenser) apply false - alias(libs.plugins.javaEcosystemCapabilities) apply false } allprojects { @@ -18,6 +17,7 @@ allprojects { // - https://maven.enginehub.org/repo/ // - https://maven.terraformersmc.com/releases/ // - https://maven.minecraftforge.net/ + // - https://maven.neoforged.net/ // - https://maven.parchmentmc.org/ // - https://repo.viaversion.com/ maven(url = "https://repo.stellardrift.ca/repository/stable/") { @@ -38,7 +38,6 @@ subprojects { apply(plugin = "java") apply(plugin = "com.diffplug.spotless") apply(plugin = "net.kyori.indra.licenser.spotless") - apply(plugin = "org.gradlex.java-ecosystem-capabilities") val targetJavaVersion: String by project val targetVersion = targetJavaVersion.toInt() @@ -60,8 +59,10 @@ subprojects { tasks.named("processResources", ProcessResources::class).configure { inputs.property("version", project.version) - filesMatching("fabric.mod.json") { - expand("version" to project.version) + sequenceOf("fabric.mod.json", "META-INF/neoforge.mods.toml").forEach { + filesMatching(it) { + expand("version" to project.version) + } } } @@ -69,7 +70,6 @@ subprojects { licenseHeaderFile(rootProject.file("HEADER")) } - plugins.withId("dev.architectury.loom") { val loom = extensions.getByType(LoomGradleExtensionAPI::class) loom.run { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cf9b24ea..32c16214 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,6 +16,7 @@ parchment = { module = "org.parchmentmc.data:parchment-1.20.6", version = "2024. fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabricLoader" } fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabricApi" } modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" } +neoforge = { module = "net.neoforged:neoforge", version = "20.6.119"} viafabricplus-api = { module = "de.florianmichael:ViaFabricPlus", version.ref = "viafabricplus" } viaversion = { module = "com.viaversion:viaversion-common", version = "5.0.0-SNAPSHOT" } vineflower = { module = "org.vineflower:vineflower", version.ref = "vineflower" } diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java index 078a3960..c7343acb 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java @@ -38,8 +38,6 @@ */ public class WorldEditCUI { - public static final int PROTOCOL_VERSION = 4; - private final Map regions = new LinkedHashMap<>(); private Region selection, activeRegion; private CUIDebug debugger; diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java index 85f31633..c06ba5a4 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java @@ -11,7 +11,7 @@ import org.enginehub.worldeditcui.WorldEditCUI; import org.enginehub.worldeditcui.event.CUIEventArgs; -import org.enginehub.worldeditcui.protocol.CUIEventPayload; +import org.enginehub.worldeditcui.protocol.CUIPacket; /** * Listener class for incoming plugin channel messages @@ -29,7 +29,7 @@ public CUIListenerChannel(WorldEditCUI controller) this.controller = controller; } - public void onMessage(final CUIEventPayload message) + public void onMessage(final CUIPacket message) { this.controller.getDebugger().debug("Received CUI event from server: " + message); diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java index 81b91baa..bc26b987 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java @@ -11,7 +11,10 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.loader.api.FabricLoader; -import org.enginehub.worldeditcui.protocol.CUIEventPayload; +import org.enginehub.worldeditcui.protocol.CUIPacket; +import org.enginehub.worldeditcui.protocol.CUIPacketHandler; + +import java.util.function.BiConsumer; /** * Networking wrappers to integrate nicely with MultiConnect. @@ -27,12 +30,12 @@ final class CUINetworking { private CUINetworking() { } - public static void send(final CUIEventPayload pkt) { + public static void send(final CUIPacket pkt) { ClientPlayNetworking.send(pkt); } - public static void subscribeToCuiPacket(final ClientPlayNetworking.PlayPayloadHandler handler) { - ClientPlayNetworking.registerGlobalReceiver(CUIEventPayload.TYPE, handler); + public static void subscribeToCuiPacket(final BiConsumer handler) { + CUIPacketHandler.instance().registerClientboundHandler(handler); if (VIAFABRICPLUS_AVAILABLE) { ViaFabricPlusHook.enable(); } diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java index e72ee59c..b23e7529 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java @@ -16,7 +16,6 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.networking.v1.PacketSender; @@ -30,7 +29,8 @@ import org.enginehub.worldeditcui.event.listeners.CUIListenerChannel; import org.enginehub.worldeditcui.event.listeners.CUIListenerWorldRender; import org.enginehub.worldeditcui.fabric.mixins.MinecraftAccess; -import org.enginehub.worldeditcui.protocol.CUIEventPayload; +import org.enginehub.worldeditcui.protocol.CUIPacket; +import org.enginehub.worldeditcui.protocol.CUIPacketHandler; import org.enginehub.worldeditcui.render.OptifinePipelineProvider; import org.enginehub.worldeditcui.render.PipelineProvider; import org.enginehub.worldeditcui.render.VanillaPipelineProvider; @@ -172,9 +172,9 @@ private void onTick(final Minecraft mc) { } } - private void onPluginMessage(final CUIEventPayload payload, final ClientPlayNetworking.Context ctx) { + private void onPluginMessage(final CUIPacket payload, final CUIPacketHandler.PacketContext ctx) { try { - ctx.client().execute(() -> this.channelListener.onMessage(payload)); + ctx.workExecutor().execute(() -> this.channelListener.onMessage(payload)); } catch (final Exception ex) { this.getController().getDebugger().info("Error decoding payload from server", ex); } @@ -200,7 +200,7 @@ public void onPostRenderEntities(final WorldRenderContext ctx) { } private void helo(final ClientPacketListener handler) { - CUINetworking.send(new CUIEventPayload("v", String.valueOf(WorldEditCUI.PROTOCOL_VERSION))); + CUINetworking.send(new CUIPacket("v", CUIPacket.protocolVersion())); } public WorldEditCUI getController() diff --git a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java index 2a7a6398..06f27d2f 100644 --- a/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java @@ -10,10 +10,10 @@ package org.enginehub.worldeditcui.fabric; import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13; -import org.enginehub.worldeditcui.protocol.CUIEventPayload; +import org.enginehub.worldeditcui.protocol.CUIPacket; public class ViaFabricPlusHook { public static void enable() { - Protocol1_12_2To1_13.MAPPINGS.getChannelMappings().put(CUINetworking.CHANNEL_LEGACY, CUIEventPayload.TYPE.id().toString()); + Protocol1_12_2To1_13.MAPPINGS.getChannelMappings().put(CUINetworking.CHANNEL_LEGACY, CUIPacket.TYPE.id().toString()); } } diff --git a/worldeditcui-fabric/src/main/resources/fabric.mod.json b/worldeditcui-fabric/src/main/resources/fabric.mod.json index 20e83b0a..569bd100 100644 --- a/worldeditcui-fabric/src/main/resources/fabric.mod.json +++ b/worldeditcui-fabric/src/main/resources/fabric.mod.json @@ -37,6 +37,7 @@ "worldeditcui.mixins.json" ], "depends": { + "worldeditcui-protocol": "*", "fabric-api-base": "*", "fabric-key-binding-api-v1": "^1.0.0", "fabric-networking-api-v1": "*", diff --git a/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIEventPayload.java b/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacket.java similarity index 77% rename from worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIEventPayload.java rename to worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacket.java index d7cdc247..9ff9b48a 100644 --- a/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIEventPayload.java +++ b/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacket.java @@ -27,20 +27,25 @@ import java.util.Arrays; import java.util.List; -public record CUIEventPayload(boolean multi, String eventType, List args) implements CustomPacketPayload { +public record CUIPacket(boolean multi, String eventType, List args) implements CustomPacketPayload { + private static final String PROTOCOL_VERSION = "4"; private static final Logger LOGGER = LogUtils.getLogger(); - public static final CustomPacketPayload.Type TYPE = new Type<>(new ResourceLocation("worldedit", "cui")); - public static final StreamCodec CODEC = CustomPacketPayload.codec(CUIEventPayload::encode, CUIEventPayload::decode); + public static final CustomPacketPayload.Type TYPE = new Type<>(new ResourceLocation("worldedit", "cui")); + public static final StreamCodec CODEC = CustomPacketPayload.codec(CUIPacket::encode, CUIPacket::decode); - public CUIEventPayload { + public CUIPacket { args = List.copyOf(args); } - public CUIEventPayload(final String eventType, final String... args) { + public CUIPacket(final String eventType, final String... args) { this(false, eventType, List.of(args)); } - public static CUIEventPayload decode(final FriendlyByteBuf buf) { + public static String protocolVersion() { + return PROTOCOL_VERSION; + } + + private static CUIPacket decode(final FriendlyByteBuf buf) { final int readableBytes = buf.readableBytes(); if (readableBytes <= 0) { throw new IllegalStateException("Warning, invalid (zero length) payload received"); @@ -53,12 +58,12 @@ public static CUIEventPayload decode(final FriendlyByteBuf buf) { String type = split[0].substring(multi ? 1 : 0); List args = split.length > 1 ? List.of(Arrays.copyOfRange(split, 1, split.length)) : List.of(); - final CUIEventPayload pkt = new CUIEventPayload(multi, type, args); + final CUIPacket pkt = new CUIPacket(multi, type, args); LOGGER.debug("Received CUI event from server: {}", pkt); return pkt; } - public void encode(final FriendlyByteBuf buf) { + private void encode(final FriendlyByteBuf buf) { final StringBuilder builder = new StringBuilder(); if (this.multi()) { builder.append('+'); diff --git a/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacketHandler.java b/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacketHandler.java new file mode 100644 index 00000000..1b59020f --- /dev/null +++ b/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacketHandler.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set forth + * in the Eclipse Public License, v. 2.0 are satisfied: + * GNU General Public License version 3 or later + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.protocol; + +import com.mojang.logging.LogUtils; +import net.minecraft.world.entity.player.Player; +import org.slf4j.Logger; + +import java.util.HashSet; +import java.util.List; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.function.BiConsumer; + +/** + * Utilities for receiving CUI packets. + */ +public interface CUIPacketHandler { + /** + * Get a handler instance to register with. + * + * @return the handler instance + */ + static CUIPacketHandler instance() { + return CUIPacketHandlers0.HANDLER_IMPL; + } + + /** + * Contextual info for the packet. + * + * @param player the player receiving the packet + * @param workExecutor a work executor for the client/server main thread + */ + record PacketContext(Player player, Executor workExecutor) {} + + /** + * Register a handler that will receive packets on the logical client. + * + * @param clientbound the clientbound handler + */ + void registerClientboundHandler(final BiConsumer clientbound); + /** + * Register a handler that will receive packets on the logical server. + * + * @param serverbound the serverbound handler + */ + void registerServerboundHandler(final BiConsumer serverbound); +} +class CUIPacketHandlers0 { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final ServiceLoader HANDLER_DISCOVERY = ServiceLoader.load(CUIPacketHandler.class); + public static final CUIPacketHandler HANDLER_IMPL; + + static { + final Set knownProviders = new HashSet<>(); + try { + final List handlers = HANDLER_DISCOVERY.stream() + .peek(prov -> knownProviders.add(prov.type().getCanonicalName())) + .map(ServiceLoader.Provider::get) + .toList(); + + if (handlers.isEmpty()) { + throw new IllegalStateException("No CUI protocol providers available"); + } else { + HANDLER_IMPL = handlers.getFirst(); + } + } catch (final ServiceConfigurationError ex) { + LOGGER.error("Failed to discover a CUI protocol handler, from known providers {}:", knownProviders, ex); + throw new IllegalStateException("Failed to configure CUI protocol handlers", ex); + } + } +} + diff --git a/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketHandler.java b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketHandler.java new file mode 100644 index 00000000..f40fab74 --- /dev/null +++ b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketHandler.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set forth + * in the Eclipse Public License, v. 2.0 are satisfied: + * GNU General Public License version 3 or later + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.fabric.network; + +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import org.enginehub.worldeditcui.protocol.CUIPacket; +import org.enginehub.worldeditcui.protocol.CUIPacketHandler; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; + +import static java.util.Objects.requireNonNull; + +public class FabricCUIPacketHandler implements CUIPacketHandler { + private static final Set> CLIENTBOUND_HANDLERS = ConcurrentHashMap.newKeySet(); + private static final Set> SERVERBOUND_HANDLERS = ConcurrentHashMap.newKeySet(); + + static void register() { + ServerPlayNetworking.registerGlobalReceiver(CUIPacket.TYPE, (pkt, ctx) -> { + final PacketContext cuiCtx = new PacketContext(ctx.player(), ctx.player().getServer()); + for (BiConsumer handler : SERVERBOUND_HANDLERS) { + handler.accept(pkt, cuiCtx); + } + }); + } + + static void registerClient() { + ClientPlayNetworking.registerGlobalReceiver(CUIPacket.TYPE, (pkt, ctx) -> { + final PacketContext cuiCtx = new PacketContext(ctx.player(), ctx.client()); + for (BiConsumer handler : SERVERBOUND_HANDLERS) { + handler.accept(pkt, cuiCtx); + } + }); + } + + @Override + public void registerClientboundHandler(BiConsumer clientbound) { + CLIENTBOUND_HANDLERS.add(requireNonNull(clientbound, "clientbound")); + } + + @Override + public void registerServerboundHandler(BiConsumer serverbound) { + SERVERBOUND_HANDLERS.add(requireNonNull(serverbound, "clientbound")); + } +} diff --git a/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/CUIPacketRegistration.java b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketRegistration.java similarity index 69% rename from worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/CUIPacketRegistration.java rename to worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketRegistration.java index 43607acf..77b971b7 100644 --- a/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/CUIPacketRegistration.java +++ b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketRegistration.java @@ -16,12 +16,13 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; -import org.enginehub.worldeditcui.protocol.CUIEventPayload; +import org.enginehub.worldeditcui.protocol.CUIPacket; -public class CUIPacketRegistration implements ModInitializer { +public class FabricCUIPacketRegistration implements ModInitializer { @Override public void onInitialize() { - PayloadTypeRegistry.playS2C().register(CUIEventPayload.TYPE, CUIEventPayload.CODEC); - PayloadTypeRegistry.playC2S().register(CUIEventPayload.TYPE, CUIEventPayload.CODEC); + FabricCUIPacketHandler.register(); + PayloadTypeRegistry.playS2C().register(CUIPacket.TYPE, CUIPacket.CODEC); + PayloadTypeRegistry.playC2S().register(CUIPacket.TYPE, CUIPacket.CODEC); } } diff --git a/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricClientCUIPacketRegistration.java b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricClientCUIPacketRegistration.java new file mode 100644 index 00000000..10875930 --- /dev/null +++ b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricClientCUIPacketRegistration.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set forth + * in the Eclipse Public License, v. 2.0 are satisfied: + * GNU General Public License version 3 or later + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.fabric.network; + +import net.fabricmc.api.ClientModInitializer; + +public class FabricClientCUIPacketRegistration implements ClientModInitializer { + @Override + public void onInitializeClient() { + FabricCUIPacketHandler.registerClient(); + } +} diff --git a/worldeditcui-protocol-fabric/src/main/resources/META-INF/services/org.enginehub.worldeditcui.protocol.CUIPacketHandler b/worldeditcui-protocol-fabric/src/main/resources/META-INF/services/org.enginehub.worldeditcui.protocol.CUIPacketHandler new file mode 100644 index 00000000..2063b667 --- /dev/null +++ b/worldeditcui-protocol-fabric/src/main/resources/META-INF/services/org.enginehub.worldeditcui.protocol.CUIPacketHandler @@ -0,0 +1 @@ +org.enginehub.worldeditcui.fabric.network.FabricCUIPacketHandler \ No newline at end of file diff --git a/worldeditcui-protocol-fabric/src/main/resources/fabric.mod.json b/worldeditcui-protocol-fabric/src/main/resources/fabric.mod.json index e0c4249c..492ae581 100644 --- a/worldeditcui-protocol-fabric/src/main/resources/fabric.mod.json +++ b/worldeditcui-protocol-fabric/src/main/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "worldeditcui-protocol-fabric", + "id": "worldeditcui-protocol", "version": "${version}", "name": "WorldEditCUI Protocol (Fabric)", "description": "Protocol implementation for the client-side user interface for WorldEdit", @@ -24,10 +24,12 @@ } }, "license": "EPL-2.0", - "environment": "client", "entrypoints": { "main": [ - "org.enginehub.worldeditcui.fabric.network.CUIPacketRegistration" + "org.enginehub.worldeditcui.fabric.network.FabricCUIPacketRegistration" + ], + "client": [ + "org.enginehub.worldeditcui.fabric.network.FabricClientCUIPacketRegistration" ] }, "depends": { diff --git a/worldeditcui-protocol-neoforge/build.gradle.kts b/worldeditcui-protocol-neoforge/build.gradle.kts index 13e5c241..3f5d741d 100644 --- a/worldeditcui-protocol-neoforge/build.gradle.kts +++ b/worldeditcui-protocol-neoforge/build.gradle.kts @@ -1,3 +1,33 @@ +plugins { + alias(libs.plugins.architecturyPlugin) + alias(libs.plugins.loom) +} + +architectury { + neoForge() +} + +configurations { + val common = dependencyScope("common") + compileClasspath { extendsFrom(common.get()) } + runtimeClasspath { extendsFrom(common.get()) } + "developmentNeoForge" { extendsFrom(common.get()) } + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding + val shadowBundle = dependencyScope("shadowBundle") + val shadowBundleClasspath = resolvable("shadowBundleClasspath") { + extendsFrom(shadowBundle.get()) + } +} + +dependencies { + neoForge(libs.neoforge) + + "common"(project(":worldeditcui-protocol-common", configuration = "namedElements")) { isTransitive = false } + "shadowBundle"(project(":worldeditcui-protocol-common", configuration = "transformProductionNeoForge")) +} + indraSpotlessLicenser { licenseHeaderFile(rootProject.file("HEADER-PROTOCOL")) } diff --git a/worldeditcui-protocol-neoforge/gradle.properties b/worldeditcui-protocol-neoforge/gradle.properties new file mode 100644 index 00000000..2914393d --- /dev/null +++ b/worldeditcui-protocol-neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge \ No newline at end of file diff --git a/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeCUIPacketHandler.java b/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeCUIPacketHandler.java new file mode 100644 index 00000000..8ca3deb7 --- /dev/null +++ b/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeCUIPacketHandler.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set forth + * in the Eclipse Public License, v. 2.0 are satisfied: + * GNU General Public License version 3 or later + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.neoforge.protocol; + +import net.neoforged.neoforge.network.handling.IPayloadHandler; +import org.enginehub.worldeditcui.protocol.CUIPacket; +import org.enginehub.worldeditcui.protocol.CUIPacketHandler; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; + +import static java.util.Objects.requireNonNull; + +public class NeoForgeCUIPacketHandler implements CUIPacketHandler { + private static final Set> CLIENTBOUND_HANDLERS = ConcurrentHashMap.newKeySet(); + private static final Set> SERVERBOUND_HANDLERS = ConcurrentHashMap.newKeySet(); + + static IPayloadHandler asHandler() { + return (pkt, ctx) -> { + final Set> handlers; + if (ctx.flow().isClientbound()) { + handlers = CLIENTBOUND_HANDLERS; + } else { + handlers = SERVERBOUND_HANDLERS; + } + + final PacketContext cuiCtx = new PacketContext(ctx.player(), ctx::enqueueWork); + for (BiConsumer handler : handlers) { + handler.accept(pkt, cuiCtx); + } + }; + } + + @Override + public void registerClientboundHandler(BiConsumer clientbound) { + CLIENTBOUND_HANDLERS.add(requireNonNull(clientbound, "clientbound")); + } + + @Override + public void registerServerboundHandler(BiConsumer serverbound) { + SERVERBOUND_HANDLERS.add(requireNonNull(serverbound, "clientbound")); + } + +} diff --git a/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeProtocolMod.java b/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeProtocolMod.java new file mode 100644 index 00000000..8c2ef65a --- /dev/null +++ b/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeProtocolMod.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011-2024 WorldEditCUI team and contributors + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set forth + * in the Eclipse Public License, v. 2.0 are satisfied: + * GNU General Public License version 3 or later + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.enginehub.worldeditcui.neoforge.protocol; + +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; +import org.enginehub.worldeditcui.protocol.CUIPacket; + +@Mod("worldeditcui-protocol") +public class NeoForgeProtocolMod { + @SubscribeEvent + public static void registerPacket(final RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar(CUIPacket.protocolVersion()); + registrar.playBidirectional(CUIPacket.TYPE, CUIPacket.CODEC, NeoForgeCUIPacketHandler.asHandler()); + } +} diff --git a/worldeditcui-protocol-neoforge/src/main/resources/META-INF/neoforge.mods.toml b/worldeditcui-protocol-neoforge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 00000000..57855a07 --- /dev/null +++ b/worldeditcui-protocol-neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,27 @@ +modLoader = "javafml" +loaderVersion = "[2,)" +issueTrackerURL = "https://github.com/EngineHub/WorldEditCUI/issues" +license = "EPL-2.0" + +[[mods]] +modId = "worldeditcui-protocol" +version = "${version}" +displayName = "WorldEditCUI Protocol (NeoForge)" +authors = "lahwran, yetanotherx, Mumfrey, TomyLobo, mikroskeem" +description = ''' +Protocol implementation for the client-side user interface for WorldEdit +''' + +[[dependencies.worldeditcui-protocol]] +modId = "neoforge" +type = "required" +versionRange = "[20.6,)" +ordering = "NONE" +side = "BOTH" + +[[dependencies.worldeditcui-protocol]] +modId = "minecraft" +type = "required" +versionRange = "[1.20.6,)" +ordering = "NONE" +side = "BOTH" diff --git a/worldeditcui-protocol-neoforge/src/main/resources/META-INF/services/org.enginehub.worldeditcui.protocol.CUIPacketHandler b/worldeditcui-protocol-neoforge/src/main/resources/META-INF/services/org.enginehub.worldeditcui.protocol.CUIPacketHandler new file mode 100644 index 00000000..8b6115de --- /dev/null +++ b/worldeditcui-protocol-neoforge/src/main/resources/META-INF/services/org.enginehub.worldeditcui.protocol.CUIPacketHandler @@ -0,0 +1 @@ +org.enginehub.worldeditcui.neoforge.protocol.NeoForgeCUIPacketHandler \ No newline at end of file