diff --git a/.gitignore b/.gitignore index 647a6149..06e717a8 100644 --- a/.gitignore +++ b/.gitignore @@ -26,10 +26,11 @@ dependency-reduced-pom.xml !gradle-wrapper.jar .gradle/ /build/ -*/build/ +/*/build/ +/.architectury-transformer/ # Fabric stuff -/run/ +/*/run/ # OS X quirks .DS_Store diff --git a/HEADER-PROTOCOL b/HEADER-PROTOCOL new file mode 100644 index 00000000..a060c916 --- /dev/null +++ b/HEADER-PROTOCOL @@ -0,0 +1,12 @@ +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 diff --git a/build.gradle.kts b/build.gradle.kts index 975dab51..e366760e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,343 +1,113 @@ -import net.darkhax.curseforgegradle.Constants -import net.darkhax.curseforgegradle.TaskPublishCurseForge -import net.fabricmc.loom.LoomGradleExtension +import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.kyori.indra.licenser.spotless.IndraSpotlessLicenserExtension plugins { - java - alias(libs.plugins.indra.git) - alias(libs.plugins.indra.spotlessLicenser) - alias(libs.plugins.loom) - alias(libs.plugins.versions) - alias(libs.plugins.javaEcosystemCapabilities) - alias(libs.plugins.curseForgeGradle) - alias(libs.plugins.minotaur) - alias(libs.plugins.publishGithubRelease) + base + alias(libs.plugins.loom) apply false alias(libs.plugins.spotless) + alias(libs.plugins.indra.spotlessLicenser) apply false } -group = "org.enginehub.worldeditcui" -version = "${libs.versions.minecraft.get()}+01-SNAPSHOT" - -repositories { - // mirrors: - // - https://maven.enginehub.org/repo/ - // - https://maven.terraformersmc.com/releases/ - // - https://maven.minecraftforge.net/ - // - https://maven.parchmentmc.org/ - // - https://repo.viaversion.com/ - maven(url = "https://repo.stellardrift.ca/repository/stable/") { - name = "stellardriftReleases" - mavenContent { releasesOnly() } - } - maven(url = "https://repo.stellardrift.ca/repository/snapshots/") { - name = "stellardriftSnapshots" - mavenContent { snapshotsOnly() } - } -} - -val targetVersion = 21 -java { - sourceCompatibility = JavaVersion.toVersion(targetVersion) - targetCompatibility = sourceCompatibility - if (JavaVersion.current() < JavaVersion.toVersion(targetVersion)) { - toolchain.languageVersion = JavaLanguageVersion.of(targetVersion) - } -} - -tasks.withType(JavaCompile::class).configureEach { - options.release = targetVersion - options.encoding = "UTF-8" - options.compilerArgs.addAll(listOf("-Xlint:all", "-Xlint:-processing")) -} - -indraSpotlessLicenser { - licenseHeaderFile(rootProject.file("HEADER")) -} - -loom { - runs { - named("client") { - // Mixin debug options - vmArgs( - // "-Dmixin.debug.verbose=true", - // "-Dmixin.debug.export=true", - // "-Dmixin.debug.export.decompile.async=false", // to get decompiled sources when mixins straight up fail to apply - "-Dmixin.dumpTargetOnFailure=true", - "-Dmixin.checks.interfaces=true", - "-Dwecui.debug.mixinaudit=true", - "-Doptifabric.extract=true" - ) - } - } - decompilerOptions.named("vineflower") { - options.put("win", "0") - } -} - -// Ugly hack for easy genSourcening -afterEvaluate { - tasks.matching { it.name == "genSources" }.configureEach { - setDependsOn(setOf("genSourcesWithVineflower")) - } -} - -val fabricApi by configurations.creating -dependencies { - minecraft(libs.minecraft) - mappings(loom.layered { - officialMojangMappings { - nameSyntheticMembers = false - } - parchment(variantOf(libs.parchment) { artifactType("zip") }) - }) - vineflowerDecompilerClasspath(libs.vineflower) - modImplementation(libs.fabric.loader) - modImplementation(libs.modmenu) - modCompileOnly(libs.viafabricplus.api) { - isTransitive = false - } - modCompileOnly(libs.viaversion) - - // [1] declare fabric-api dependency... - fabricApi(libs.fabric.api) - - // [2] Load the API dependencies from the fabric mod json... - @Suppress("UNCHECKED_CAST") - val fabricModJson = file("src/main/resources/fabric.mod.json").bufferedReader().use { - groovy.json.JsonSlurper().parse(it) as Map> - } - val wantedDependencies = (fabricModJson["depends"] ?: error("no depends in fabric.mod.json")).keys - .filter { it == "fabric-api-base" || it.contains(Regex("v\\d$")) } - .map { "net.fabricmc.fabric-api:$it" } - .toSet() - logger.lifecycle("Looking for these dependencies:") - for (wantedDependency in wantedDependencies) { - logger.lifecycle(wantedDependency) - } - // [3] and now we resolve it to pick out what we want :D - val fabricApiDependencies = fabricApi.incoming.resolutionResult.allDependencies - .onEach { - if (it is UnresolvedDependencyResult) { - throw kotlin.IllegalStateException("Failed to resolve Fabric API", it.failure) +allprojects { + group = "org.enginehub.worldeditcui" + version = "${rootProject.libs.versions.minecraft.get()}+01-SNAPSHOT" + + repositories { + // mirrors: + // - 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/") { + name = "stellardriftReleases" + mavenContent { + releasesOnly() + excludeGroup("org.lwjgl") // workaround for lwjgl-freetype } } - .filterIsInstance() - // pick out transitive dependencies - .flatMap { - it.selected.dependencies + maven(url = "https://repo.stellardrift.ca/repository/snapshots/") { + name = "stellardriftSnapshots" + mavenContent { snapshotsOnly() } } - // grab the requested versions - .map { it.requested } - .filterIsInstance() - // map to standard notation - .associateByTo( - mutableMapOf(), - keySelector = { "${it.group}:${it.module}" }, - valueTransform = { "${it.group}:${it.module}:${it.version}" } - ) - fabricApiDependencies.keys.retainAll(wantedDependencies) - // sanity check - for (wantedDep in wantedDependencies) { - check(wantedDep in fabricApiDependencies) { "Fabric API library $wantedDep is missing!" } - } - - fabricApiDependencies.values.forEach { - "include"(it) - "modImplementation"(it) } - - // for development - /*modLocalRuntime(libs.worldedit) { - exclude("com.google.guava", "guava") - exclude("com.google.code.gson", "gson") - exclude("com.google.code.gson", "gson") - exclude("it.unimi.dsi", "fastutil") - exclude("org.apache.logging.log4j", "log4j-api") - }*/ -} - -configurations.modLocalRuntime { - shouldResolveConsistentlyWith(configurations.modImplementation.get()) } -tasks { - register("generateStandaloneRun") { - description = "Generate a script that will run WorldEdit CUI, for graphics debugging" - val scriptDest = project.layout.buildDirectory.file(if (System.getProperty("os.name").contains("windows", ignoreCase = true)) { - "run-dev.bat" - } else { - "run-dev" - }) - val argsDest = project.layout.buildDirectory.file("run-dev-args.txt") - val taskClasspath = project.files(jar.map { it.outputs }, configurations.runtimeClasspath) - val toolchain = project.javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(targetVersion) } - inputs.files(taskClasspath) - .ignoreEmptyDirectories() - .withPropertyName("runClasspath") - // inputs.property("javaLauncher", toolchain) - outputs.file(scriptDest) - outputs.file(argsDest) - doLast { - val clientRun = loom.runConfigs.getByName("client") - - // technically uses internal API, but it's non-essential - argsDest.get().asFile.writeText(""" - -Dfabric.dli.config=${(loom as LoomGradleExtension).files.devLauncherConfig.absolutePath} - -Dfabric.dli.env=client - -Dfabric.dli.main=${clientRun.defaultMainClass} - ${clientRun.vmArgs.joinToString(System.lineSeparator())} - -cp ${taskClasspath.asPath} - net.fabricmc.devlaunchinjector.Main - ${clientRun.programArgs.joinToString(System.lineSeparator())} - """.trimIndent(), Charsets.UTF_8) - scriptDest.get().asFile.writeText(""" - ${toolchain.get().executablePath.asFile.absolutePath} "@${argsDest.get().asFile.absolutePath}" - """.trimIndent(), Charsets.UTF_8) +subprojects { + apply(plugin = "java") + apply(plugin = "com.diffplug.spotless") + apply(plugin = "net.kyori.indra.licenser.spotless") + apply(plugin = "maven-publish") + + val targetJavaVersion: String by project + val targetVersion = targetJavaVersion.toInt() + extensions.configure(JavaPluginExtension::class) { + sourceCompatibility = JavaVersion.toVersion(targetVersion) + targetCompatibility = sourceCompatibility + if (JavaVersion.current() < JavaVersion.toVersion(targetVersion)) { + toolchain.languageVersion = JavaLanguageVersion.of(targetVersion) } + withSourcesJar() } - withType(net.fabricmc.loom.task.AbstractRunTask::class).configureEach { - // Configure mixin agent - // Resolve the Mixin configuration - val mixinSource = configurations.runtimeClasspath.get().incoming - .artifactView { componentFilter { it is ModuleComponentIdentifier && it.module == "sponge-mixin" && it.group == "net.fabricmc" } } - .files - inputs.files(mixinSource).withPropertyName("mixinAgent") - - jvmArgumentProviders += CommandLineArgumentProvider { - // Java agent: the jar file for mixin - if (!mixinSource.isEmpty) { - listOf("-javaagent:${mixinSource.singleFile}") - } else { - emptyList() - } - } + tasks.withType(JavaCompile::class).configureEach { + options.release = targetVersion + options.encoding = "UTF-8" + options.compilerArgs.addAll(listOf("-Xlint:all", "-Xlint:-processing")) } - processResources.configure { + 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) + } } } -} - -// Releasing -val changelogContents = objects.property(String::class) -changelogContents.set(providers.gradleProperty("changelog") - .map { file(it) } - .filter { it.exists() } - .map { it.readText(Charsets.UTF_8) }) -changelogContents.finalizeValueOnRead() -val versionName = project.provider { project.version } - -val cfApiToken = providers.gradleProperty("cfApiToken") -val modrinthToken = providers.gradleProperty("modrinthToken") - .orElse(providers.environmentVariable("MODRINTH_TOKEN")) -val githubToken = providers.gradleProperty("githubToken") - .orElse(providers.environmentVariable("GITHUB_TOKEN")) - -tasks { - val validateRelease by registering { - inputs.property("changelog", changelogContents).optional(true) - inputs.property("version", versionName) - doLast { - val problems = mutableListOf() - // General release-readiness - if (indraGit.headTag() == null) { - problems.add("Tried to perform a release without being checked out to a tag") - } - if (versionName.get().toString().contains("SNAPSHOT")) { - problems.add("SNAPSHOT versions of WorldEditCUI cannot be published") - } - if (!changelogContents.isPresent) { - problems.add("A file with changelog text must be provided using the 'changelog' Gradle property") - } - - // CF - if (!cfApiToken.isPresent) { - problems.add("No CurseForge API token was set with the 'cfApiToken' Gradle property") - } + extensions.configure(IndraSpotlessLicenserExtension::class) { + licenseHeaderFile(rootProject.file("HEADER")) + } - // MR - if (!modrinthToken.isPresent) { - problems.add("No Modrinth access token was set with either the 'modrinthToken' Gradle property, or 'MODRINTH_TOKEN' environment variable") + plugins.withId("dev.architectury.loom") { + val loom = extensions.getByType(LoomGradleExtensionAPI::class) + loom.run { + decompilerOptions.named("vineflower") { + options.put("win", "0") } + silentMojangMappingsLicense() + } - // GH - if (!githubToken.isPresent) { - problems.add("No GitHub access token was set with either the 'githubToken' Gradle property, or 'GITHUB_TOKEN' environment variable") + // Ugly hack for easy genSourcening + afterEvaluate { + tasks.matching { it.name == "genSources" }.configureEach { + setDependsOn(setOf("genSourcesWithVineflower")) } + } - when (problems.size) { - 0 -> return@doLast - 1 -> { - throw InvalidUserDataException(problems[0]) + dependencies { + "minecraft"(libs.minecraft) + "mappings"(loom.layered { + officialMojangMappings { + nameSyntheticMembers = false } - else -> throw InvalidUserDataException( - "WorldEditCUI detected the following problems when trying to perform a release:\n\n" - + problems.joinToString("\n - ", prefix = " - ") - ) - } + parchment(variantOf(libs.parchment) { artifactType("zip") }) + }) + "vineflowerDecompilerClasspath"(libs.vineflower) } - } - - val publishToCurseForge by registering(TaskPublishCurseForge::class) { - val cfProjectId = providers.gradleProperty("cfProjectId") - - apiToken = cfApiToken.get() - with(upload(cfProjectId.get(), remapJar)) { - displayName = project.version - releaseType = Constants.RELEASE_TYPE_RELEASE - changelog = changelogContents.getOrElse("") - // Rendering plugins - addOptional("canvas-renderer", "sodium", "irisshaders") - // Config screens, version compatibility - addOptional("modmenu", "viafabricplus", "worldedit") - addJavaVersion("Java $targetVersion") - addGameVersion(libs.versions.minecraft.get()) + configurations.named("modLocalRuntime") { + shouldResolveConsistentlyWith(configurations.getByName("modImplementation")) } } - val releaseTasks = listOf(publishToCurseForge, publishToGitHub, modrinth) - releaseTasks.forEach { - it.configure { dependsOn(validateRelease) } - } - - register("publishRelease") { - group = PublishingPlugin.PUBLISH_TASK_GROUP - dependsOn(releaseTasks) - } -} - -modrinth { - token = modrinthToken - projectId = "worldedit-cui" - syncBodyFrom = providers.provider { file("README.md").readText(Charsets.UTF_8) } - uploadFile.set(tasks.remapJar) - gameVersions.add(libs.versions.minecraft.get()) - changelog = changelogContents - dependencies { - optional.project("canvas") - optional.project("sodium") - optional.project("iris") - // Config screens, version compatibility - optional.project("modmenu") - optional.project("viafabricplus") - optional.project("worldedit") - } -} - -githubRelease { - apiToken = githubToken - tagName = project.provider { - indraGit.headTag()?.run { org.eclipse.jgit.lib.Repository.shortenRefName(name) } + extensions.configure(PublishingExtension::class) { + publications { + register("maven", MavenPublication::class) { + from(components.getByName("java")) + } + } } - repository = "EngineHub/WorldEditCUI" - releaseName = "WorldEditCUI v$version" - releaseBody = changelogContents - artifacts.from(tasks.remapJar) -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 7c8aa48e..5a0b9224 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,8 @@ cfProjectId=402098 +# Project configuration +targetJavaVersion=21 +enabledPlatforms=fabric,neoforge + # Gradle -org.gradle.jvmargs=-Xmx1G -systemProp.org.gradle.unsafe.kotlin.assignment=true \ No newline at end of file +org.gradle.jvmargs=-Xmx1G \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dc54a608..ce44ab35 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,19 +15,24 @@ minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } parchment = { module = "org.parchmentmc.data:parchment-1.20.6", version = "2024.05.01" } fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabricLoader" } fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabricApi" } +fabric-api-bom = { module = "net.fabricmc.fabric-api:fabric-api-bom", version.ref = "fabricApi" } +fabric-api-networking = { module = "net.fabricmc.fabric-api:fabric-networking-api-v1" } 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" } worldedit = { module = "com.sk89q.worldedit:worldedit-fabric-mc1.20.6", version = "7.3.1" } [plugins] +architecturyPlugin = { id = "architectury-plugin", version = "3.4.155" } curseForgeGradle = { id = "net.darkhax.curseforgegradle", version = "1.1.18" } indra-git = { id = "net.kyori.indra.git", version.ref = "indra" } indra-spotlessLicenser = { id = "net.kyori.indra.licenser.spotless", version.ref = "indra" } javaEcosystemCapabilities = { id = "org.gradlex.java-ecosystem-capabilities", version = "1.5.2" } -loom = { id = "fabric-loom", version = "1.6.11" } +loom = { id = "dev.architectury.loom", version = "1.6.397" } minotaur = { id = "com.modrinth.minotaur", version = "2.8.7" } publishGithubRelease = { id = "ca.stellardrift.publish-github-release", version = "0.1.0" } +shadow = { id = "io.github.goooler.shadow", version = "8.1.7" } spotless = { id = "com.diffplug.spotless", version = "6.25.0" } versions = { id = "com.github.ben-manes.versions", version = "0.51.0" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 62a9b5fa..8203ebc1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,7 +3,7 @@ rootProject.name = "WorldEditCUI" pluginManagement { repositories { // mirrors: - // - https://server.bbkr.space/artifactory/libs-release/ + // - https://maven.architectury.dev/ // - https://maven.fabricmc.net/ // - gradlePluginPortal maven(url = "https://repo.stellardrift.ca/repository/stable/") { @@ -18,3 +18,12 @@ pluginManagement { // gradlePluginPortal() } } + +sequenceOf( + "fabric", + "protocol-common", + "protocol-fabric", + "protocol-neoforge", +).forEach { + include("worldeditcui-$it") +} diff --git a/worldeditcui-fabric/build.gradle.kts b/worldeditcui-fabric/build.gradle.kts new file mode 100644 index 00000000..7462d01c --- /dev/null +++ b/worldeditcui-fabric/build.gradle.kts @@ -0,0 +1,280 @@ +import net.darkhax.curseforgegradle.Constants +import net.darkhax.curseforgegradle.TaskPublishCurseForge +import net.fabricmc.loom.LoomGradleExtension + +plugins { + java + alias(libs.plugins.indra.git) + alias(libs.plugins.indra.spotlessLicenser) + alias(libs.plugins.loom) + alias(libs.plugins.versions) + alias(libs.plugins.curseForgeGradle) + alias(libs.plugins.minotaur) + alias(libs.plugins.publishGithubRelease) +} + +base { + archivesName = "WorldEditCUI" +} +loom { + runs { + named("client") { + // Mixin debug options + vmArgs( + // "-Dmixin.debug.verbose=true", + // "-Dmixin.debug.export=true", + // "-Dmixin.debug.export.decompile.async=false", // to get decompiled sources when mixins straight up fail to apply + "-Dmixin.dumpTargetOnFailure=true", + "-Dmixin.checks.interfaces=true", + "-Dwecui.debug.mixinaudit=true", + "-Doptifabric.extract=true" + ) + } + } +} + +val fabricApi by configurations.creating +dependencies { + implementation(project(":worldeditcui-protocol-fabric", configuration = "namedElements")) { isTransitive = false } + implementation(project(":worldeditcui-protocol-common", configuration = "namedElements")) { isTransitive = false } + include(project(":worldeditcui-protocol-fabric")) + modImplementation(libs.fabric.loader) + modImplementation(libs.modmenu) + modCompileOnly(libs.viafabricplus.api) { + isTransitive = false + } + modCompileOnly(libs.viaversion) + + // [1] declare fabric-api dependency... + fabricApi(libs.fabric.api) + + // [2] Load the API dependencies from the fabric mod json... + @Suppress("UNCHECKED_CAST") + val fabricModJson = file("src/main/resources/fabric.mod.json").bufferedReader().use { + groovy.json.JsonSlurper().parse(it) as Map> + } + val wantedDependencies = (fabricModJson["depends"] ?: error("no depends in fabric.mod.json")).keys + .filter { it == "fabric-api-base" || it.contains(Regex("v\\d$")) } + .map { "net.fabricmc.fabric-api:$it" } + .toSet() + logger.lifecycle("Looking for these dependencies:") + for (wantedDependency in wantedDependencies) { + logger.lifecycle(wantedDependency) + } + // [3] and now we resolve it to pick out what we want :D + val fabricApiDependencies = fabricApi.incoming.resolutionResult.allDependencies + .onEach { + if (it is UnresolvedDependencyResult) { + throw kotlin.IllegalStateException("Failed to resolve Fabric API", it.failure) + } + } + .filterIsInstance() + // pick out transitive dependencies + .flatMap { + it.selected.dependencies + } + // grab the requested versions + .map { it.requested } + .filterIsInstance() + // map to standard notation + .associateByTo( + mutableMapOf(), + keySelector = { "${it.group}:${it.module}" }, + valueTransform = { "${it.group}:${it.module}:${it.version}" } + ) + fabricApiDependencies.keys.retainAll(wantedDependencies) + // sanity check + for (wantedDep in wantedDependencies) { + check(wantedDep in fabricApiDependencies) { "Fabric API library $wantedDep is missing!" } + } + + fabricApiDependencies.values.forEach { + "include"(it) + "modImplementation"(it) + } + + // for development + /*modLocalRuntime(libs.worldedit) { + exclude("com.google.guava", "guava") + exclude("com.google.code.gson", "gson") + exclude("com.google.code.gson", "gson") + exclude("it.unimi.dsi", "fastutil") + exclude("org.apache.logging.log4j", "log4j-api") + }*/ +} + +val targetJavaVersion: String by project +tasks { + register("generateStandaloneRun") { + description = "Generate a script that will run WorldEdit CUI, for graphics debugging" + val scriptDest = project.layout.buildDirectory.file(if (System.getProperty("os.name").contains("windows", ignoreCase = true)) { + "run-dev.bat" + } else { + "run-dev" + }) + val argsDest = project.layout.buildDirectory.file("run-dev-args.txt") + val taskClasspath = project.files(jar.map { it.outputs }, configurations.runtimeClasspath) + val toolchain = project.javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(targetJavaVersion) } + inputs.files(taskClasspath) + .ignoreEmptyDirectories() + .withPropertyName("runClasspath") + // inputs.property("javaLauncher", toolchain) + outputs.file(scriptDest) + outputs.file(argsDest) + doLast { + val clientRun = loom.runConfigs.getByName("client") + + // technically uses internal API, but it's non-essential + argsDest.get().asFile.writeText(""" + -Dfabric.dli.config=${(loom as LoomGradleExtension).files.devLauncherConfig.absolutePath} + -Dfabric.dli.env=client + -Dfabric.dli.main=${clientRun.defaultMainClass} + ${clientRun.vmArgs.joinToString(System.lineSeparator())} + -cp ${taskClasspath.asPath} + net.fabricmc.devlaunchinjector.Main + ${clientRun.programArgs.joinToString(System.lineSeparator())} + """.trimIndent(), Charsets.UTF_8) + scriptDest.get().asFile.writeText(""" + ${toolchain.get().executablePath.asFile.absolutePath} "@${argsDest.get().asFile.absolutePath}" + """.trimIndent(), Charsets.UTF_8) + } + } + + withType(net.fabricmc.loom.task.AbstractRunTask::class).configureEach { + // Configure mixin agent + // Resolve the Mixin configuration + val mixinSource = configurations.runtimeClasspath.get().incoming + .artifactView { componentFilter { it is ModuleComponentIdentifier && it.module == "sponge-mixin" && it.group == "net.fabricmc" } } + .files + inputs.files(mixinSource).withPropertyName("mixinAgent") + + jvmArgumentProviders += CommandLineArgumentProvider { + // Java agent: the jar file for mixin + if (!mixinSource.isEmpty) { + listOf("-javaagent:${mixinSource.singleFile}") + } else { + emptyList() + } + } + } + +} + +// Releasing +val changelogContents = objects.property(String::class) +changelogContents.set(providers.gradleProperty("changelog") + .map { file(it) } + .filter { it.exists() } + .map { it.readText(Charsets.UTF_8) }) +changelogContents.finalizeValueOnRead() +val versionName = project.provider { project.version } + +val cfApiToken = providers.gradleProperty("cfApiToken") +val modrinthToken = providers.gradleProperty("modrinthToken") + .orElse(providers.environmentVariable("MODRINTH_TOKEN")) +val githubToken = providers.gradleProperty("githubToken") + .orElse(providers.environmentVariable("GITHUB_TOKEN")) + +tasks { + val validateRelease by registering { + inputs.property("changelog", changelogContents).optional(true) + inputs.property("version", versionName) + + doLast { + val problems = mutableListOf() + // General release-readiness + if (indraGit.headTag() == null) { + problems.add("Tried to perform a release without being checked out to a tag") + } + if (versionName.get().toString().contains("SNAPSHOT")) { + problems.add("SNAPSHOT versions of WorldEditCUI cannot be published") + } + if (!changelogContents.isPresent) { + problems.add("A file with changelog text must be provided using the 'changelog' Gradle property") + } + + // CF + if (!cfApiToken.isPresent) { + problems.add("No CurseForge API token was set with the 'cfApiToken' Gradle property") + } + + // MR + if (!modrinthToken.isPresent) { + problems.add("No Modrinth access token was set with either the 'modrinthToken' Gradle property, or 'MODRINTH_TOKEN' environment variable") + } + + // GH + if (!githubToken.isPresent) { + problems.add("No GitHub access token was set with either the 'githubToken' Gradle property, or 'GITHUB_TOKEN' environment variable") + } + + when (problems.size) { + 0 -> return@doLast + 1 -> { + throw InvalidUserDataException(problems[0]) + } + else -> throw InvalidUserDataException( + "WorldEditCUI detected the following problems when trying to perform a release:\n\n" + + problems.joinToString("\n - ", prefix = " - ") + ) + } + } + } + + val publishToCurseForge by registering(TaskPublishCurseForge::class) { + val cfProjectId = providers.gradleProperty("cfProjectId") + + apiToken = cfApiToken.get() + + with(upload(cfProjectId.get(), remapJar)) { + displayName = project.version + releaseType = Constants.RELEASE_TYPE_RELEASE + changelog = changelogContents.getOrElse("") + // Rendering plugins + addOptional("canvas-renderer", "sodium", "irisshaders") + // Config screens, version compatibility + addOptional("modmenu", "viafabricplus", "worldedit") + addJavaVersion("Java $targetJavaVersion") + addGameVersion(libs.versions.minecraft.get()) + } + } + + val releaseTasks = listOf(publishToCurseForge, publishToGitHub, modrinth) + releaseTasks.forEach { + it.configure { dependsOn(validateRelease) } + } + + register("publishRelease") { + group = PublishingPlugin.PUBLISH_TASK_GROUP + dependsOn(releaseTasks) + } +} + +modrinth { + token = modrinthToken + projectId = "worldedit-cui" + syncBodyFrom = providers.provider { file("README.md").readText(Charsets.UTF_8) } + uploadFile.set(tasks.remapJar) + gameVersions.add(libs.versions.minecraft.get()) + changelog = changelogContents + dependencies { + optional.project("canvas") + optional.project("sodium") + optional.project("iris") + // Config screens, version compatibility + optional.project("modmenu") + optional.project("viafabricplus") + optional.project("worldedit") + } +} + +githubRelease { + apiToken = githubToken + tagName = project.provider { + indraGit.headTag()?.run { org.eclipse.jgit.lib.Repository.shortenRefName(name) } + } + repository = "EngineHub/WorldEditCUI" + releaseName = "WorldEditCUI v$version" + releaseBody = changelogContents + artifacts.from(tasks.remapJar) +} diff --git a/src/main/java/org/enginehub/worldeditcui/InitialisationFactory.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/InitialisationFactory.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/InitialisationFactory.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/InitialisationFactory.java diff --git a/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java similarity index 98% rename from src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/WorldEditCUI.java index 078a3960..c7343acb 100644 --- a/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/src/main/java/org/enginehub/worldeditcui/config/CUIConfiguration.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/config/CUIConfiguration.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/config/CUIConfiguration.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/config/CUIConfiguration.java diff --git a/src/main/java/org/enginehub/worldeditcui/config/Colour.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/config/Colour.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/config/Colour.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/config/Colour.java diff --git a/src/main/java/org/enginehub/worldeditcui/debug/CUIDebug.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/debug/CUIDebug.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/debug/CUIDebug.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/debug/CUIDebug.java diff --git a/src/main/java/org/enginehub/worldeditcui/debug/DebugModeEnabledFilter.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/debug/DebugModeEnabledFilter.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/debug/DebugModeEnabledFilter.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/debug/DebugModeEnabledFilter.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/CUIEvent.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEvent.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/CUIEvent.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEvent.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/CUIEventArgs.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEventArgs.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/CUIEventArgs.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEventArgs.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/CUIEventDispatcher.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEventDispatcher.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/CUIEventDispatcher.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEventDispatcher.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/CUIEventType.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEventType.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/CUIEventType.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/CUIEventType.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventBounds.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventBounds.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventBounds.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventBounds.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventColour.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventColour.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventColour.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventColour.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventCylinder.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventCylinder.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventCylinder.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventCylinder.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventEllipsoid.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventEllipsoid.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventEllipsoid.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventEllipsoid.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventGrid.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventGrid.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventGrid.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventGrid.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint2D.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint2D.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint2D.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint2D.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint3D.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint3D.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint3D.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPoint3D.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPolygon.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPolygon.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPolygon.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventPolygon.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventSelection.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventSelection.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventSelection.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventSelection.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventUpdate.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventUpdate.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventUpdate.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/cui/CUIEventUpdate.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java similarity index 90% rename from src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerChannel.java index ca9a2633..c06ba5a4 100644 --- a/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.network.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/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerWorldRender.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerWorldRender.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerWorldRender.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIListenerWorldRender.java diff --git a/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIRenderContext.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIRenderContext.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/event/listeners/CUIRenderContext.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/event/listeners/CUIRenderContext.java diff --git a/src/main/java/org/enginehub/worldeditcui/exceptions/InitialisationException.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/exceptions/InitialisationException.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/exceptions/InitialisationException.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/exceptions/InitialisationException.java diff --git a/src/main/java/org/enginehub/worldeditcui/exceptions/InvalidSelectionTypeException.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/exceptions/InvalidSelectionTypeException.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/exceptions/InvalidSelectionTypeException.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/exceptions/InvalidSelectionTypeException.java diff --git a/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java similarity index 63% rename from src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java index 14ea51df..bc26b987 100644 --- a/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java +++ b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/CUINetworking.java @@ -10,9 +10,11 @@ package org.enginehub.worldeditcui.fabric; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.loader.api.FabricLoader; -import org.enginehub.worldeditcui.network.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. @@ -28,14 +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) { - PayloadTypeRegistry.playS2C().register(CUIEventPayload.TYPE, CUIEventPayload.CODEC); - PayloadTypeRegistry.playC2S().register(CUIEventPayload.TYPE, CUIEventPayload.CODEC); - ClientPlayNetworking.registerGlobalReceiver(CUIEventPayload.TYPE, handler); + public static void subscribeToCuiPacket(final BiConsumer handler) { + CUIPacketHandler.instance().registerClientboundHandler(handler); if (VIAFABRICPLUS_AVAILABLE) { ViaFabricPlusHook.enable(); } diff --git a/src/main/java/org/enginehub/worldeditcui/fabric/ConfigPanelFactory.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ConfigPanelFactory.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/fabric/ConfigPanelFactory.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ConfigPanelFactory.java diff --git a/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java similarity index 95% rename from src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/FabricModWorldEditCUI.java index 6e16668f..b23e7529 100644 --- a/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.network.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/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java similarity index 81% rename from src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/ViaFabricPlusHook.java index 56b8462f..06f27d2f 100644 --- a/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.network.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/src/main/java/org/enginehub/worldeditcui/fabric/mixins/MinecraftAccess.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/mixins/MinecraftAccess.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/fabric/mixins/MinecraftAccess.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/fabric/mixins/MinecraftAccess.java diff --git a/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigList.java diff --git a/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigPanel.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigPanel.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/gui/CUIConfigPanel.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/gui/CUIConfigPanel.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/BufferBuilderRenderSink.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/BufferBuilderRenderSink.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/BufferBuilderRenderSink.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/BufferBuilderRenderSink.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/CUISelectionProvider.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/CUISelectionProvider.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/CUISelectionProvider.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/CUISelectionProvider.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/ConfiguredColour.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/ConfiguredColour.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/ConfiguredColour.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/ConfiguredColour.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/CustomStyle.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/CustomStyle.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/CustomStyle.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/CustomStyle.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/LineStyle.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/LineStyle.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/LineStyle.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/LineStyle.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/OptifinePipelineProvider.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/OptifinePipelineProvider.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/OptifinePipelineProvider.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/OptifinePipelineProvider.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/PipelineProvider.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/PipelineProvider.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/PipelineProvider.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/PipelineProvider.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/RenderSink.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/RenderSink.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/RenderSink.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/RenderSink.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/RenderStyle.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/RenderStyle.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/RenderStyle.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/RenderStyle.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/VanillaPipelineProvider.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/VanillaPipelineProvider.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/VanillaPipelineProvider.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/VanillaPipelineProvider.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/points/PointCube.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/points/PointCube.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/points/PointCube.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/points/PointCube.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/points/PointCubeTracking.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/points/PointCubeTracking.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/points/PointCubeTracking.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/points/PointCubeTracking.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/points/PointRectangle.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/points/PointRectangle.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/points/PointRectangle.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/points/PointRectangle.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/CuboidRegion.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/CuboidRegion.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/CuboidRegion.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/CuboidRegion.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/CylinderRegion.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/CylinderRegion.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/CylinderRegion.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/CylinderRegion.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/EllipsoidRegion.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/EllipsoidRegion.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/EllipsoidRegion.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/EllipsoidRegion.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/PolygonRegion.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/PolygonRegion.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/PolygonRegion.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/PolygonRegion.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/PolyhedronRegion.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/PolyhedronRegion.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/PolyhedronRegion.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/PolyhedronRegion.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/Region.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/Region.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/Region.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/Region.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/region/RegionType.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/RegionType.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/region/RegionType.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/region/RegionType.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DBox.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DBox.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DBox.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DBox.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DGrid.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DGrid.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DGrid.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render2DGrid.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DBox.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DBox.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DBox.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DBox.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DGrid.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DGrid.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DGrid.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DGrid.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DPolygon.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DPolygon.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DPolygon.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/Render3DPolygon.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderChunkBoundary.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderChunkBoundary.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/RenderChunkBoundary.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderChunkBoundary.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderBox.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderBox.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderBox.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderBox.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderCircles.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderCircles.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderCircles.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderCircles.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderGrid.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderGrid.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderGrid.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderCylinderGrid.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderEllipsoid.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderEllipsoid.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/RenderEllipsoid.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderEllipsoid.java diff --git a/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderRegion.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderRegion.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/render/shapes/RenderRegion.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/render/shapes/RenderRegion.java diff --git a/src/main/java/org/enginehub/worldeditcui/util/BoundingBox.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/BoundingBox.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/util/BoundingBox.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/BoundingBox.java diff --git a/src/main/java/org/enginehub/worldeditcui/util/Observable.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Observable.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/util/Observable.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Observable.java diff --git a/src/main/java/org/enginehub/worldeditcui/util/Observer.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Observer.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/util/Observer.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Observer.java diff --git a/src/main/java/org/enginehub/worldeditcui/util/Vector2.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Vector2.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/util/Vector2.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Vector2.java diff --git a/src/main/java/org/enginehub/worldeditcui/util/Vector2m.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Vector2m.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/util/Vector2m.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Vector2m.java diff --git a/src/main/java/org/enginehub/worldeditcui/util/Vector3.java b/worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Vector3.java similarity index 100% rename from src/main/java/org/enginehub/worldeditcui/util/Vector3.java rename to worldeditcui-fabric/src/main/java/org/enginehub/worldeditcui/util/Vector3.java diff --git a/src/main/resources/assets/worldeditcui/icon.png b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/icon.png similarity index 100% rename from src/main/resources/assets/worldeditcui/icon.png rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/icon.png diff --git a/src/main/resources/assets/worldeditcui/lang/de_de.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/de_de.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/de_de.json diff --git a/src/main/resources/assets/worldeditcui/lang/en_us.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/en_us.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/en_us.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/en_us.json diff --git a/src/main/resources/assets/worldeditcui/lang/fr_fr.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/fr_fr.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/fr_fr.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/fr_fr.json diff --git a/src/main/resources/assets/worldeditcui/lang/nl_nl.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/nl_nl.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/nl_nl.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/nl_nl.json diff --git a/src/main/resources/assets/worldeditcui/lang/ru_ru.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/ru_ru.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/ru_ru.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/ru_ru.json diff --git a/src/main/resources/assets/worldeditcui/lang/uk_ua.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/uk_ua.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/uk_ua.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/uk_ua.json diff --git a/src/main/resources/assets/worldeditcui/lang/zh_cn.json b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/zh_cn.json similarity index 100% rename from src/main/resources/assets/worldeditcui/lang/zh_cn.json rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/lang/zh_cn.json diff --git a/src/main/resources/assets/worldeditcui/textures/gui/checker.png b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/textures/gui/checker.png similarity index 100% rename from src/main/resources/assets/worldeditcui/textures/gui/checker.png rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/textures/gui/checker.png diff --git a/src/main/resources/assets/worldeditcui/textures/gui/picker.png b/worldeditcui-fabric/src/main/resources/assets/worldeditcui/textures/gui/picker.png similarity index 100% rename from src/main/resources/assets/worldeditcui/textures/gui/picker.png rename to worldeditcui-fabric/src/main/resources/assets/worldeditcui/textures/gui/picker.png diff --git a/src/main/resources/fabric.mod.json b/worldeditcui-fabric/src/main/resources/fabric.mod.json similarity index 95% rename from src/main/resources/fabric.mod.json rename to worldeditcui-fabric/src/main/resources/fabric.mod.json index 2a2c08ea..569bd100 100644 --- a/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": "*", @@ -44,7 +45,7 @@ "fabric-lifecycle-events-v1": "^2.0.0", "fabric-screen-api-v1": ">=1.0.9", "fabric-resource-loader-v0": ">=0.4.17", - "minecraft": ">=1.19.1" + "minecraft": ">=1.20.5" }, "suggests": { "worldedit": ">=7.2.0" diff --git a/src/main/resources/worldeditcui.mixins.json b/worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json similarity index 100% rename from src/main/resources/worldeditcui.mixins.json rename to worldeditcui-fabric/src/main/resources/worldeditcui.mixins.json diff --git a/worldeditcui-protocol-common/build.gradle.kts b/worldeditcui-protocol-common/build.gradle.kts new file mode 100644 index 00000000..75305afc --- /dev/null +++ b/worldeditcui-protocol-common/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + alias(libs.plugins.architecturyPlugin) + alias(libs.plugins.loom) +} + +indraSpotlessLicenser { + licenseHeaderFile(rootProject.file("HEADER-PROTOCOL")) +} + +val enabledPlatforms: String by project +architectury { + common(enabledPlatforms.split(',')) +} + +dependencies { + modImplementation(libs.fabric.loader) + modImplementation(libs.fabric.api) +} \ No newline at end of file diff --git a/src/main/java/org/enginehub/worldeditcui/network/CUIEventPayload.java b/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacket.java similarity index 67% rename from src/main/java/org/enginehub/worldeditcui/network/CUIEventPayload.java rename to worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacket.java index 9313cbbc..9ff9b48a 100644 --- a/src/main/java/org/enginehub/worldeditcui/network/CUIEventPayload.java +++ b/worldeditcui-protocol-common/src/main/java/org/enginehub/worldeditcui/protocol/CUIPacket.java @@ -5,9 +5,14 @@ * 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.network; +package org.enginehub.worldeditcui.protocol; import com.mojang.logging.LogUtils; import net.minecraft.network.FriendlyByteBuf; @@ -22,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"); @@ -48,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/build.gradle.kts b/worldeditcui-protocol-fabric/build.gradle.kts new file mode 100644 index 00000000..f0988693 --- /dev/null +++ b/worldeditcui-protocol-fabric/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + alias(libs.plugins.architecturyPlugin) + alias(libs.plugins.loom) + alias(libs.plugins.shadow) +} + +architectury { + fabric() +} + +indraSpotlessLicenser { + licenseHeaderFile(rootProject.file("HEADER-PROTOCOL")) +} + +configurations { + val common = dependencyScope("common") + compileClasspath { extendsFrom(common.get()) } + runtimeClasspath { extendsFrom(common.get()) } + "developmentFabric" { extendsFrom(common.get()) } +} + +val shadowBundle = configurations.dependencyScope("shadowBundle") +val shadowBundleClasspath = configurations.resolvable("shadowBundleClasspath") { + extendsFrom(shadowBundle.get()) +} + +dependencies { + "common"(project(":worldeditcui-protocol-common", configuration = "namedElements")) { isTransitive = false } + "shadowBundle"(project(":worldeditcui-protocol-common", configuration = "transformProductionFabric")) + modImplementation(libs.fabric.loader) + modImplementation(platform(libs.fabric.api.bom)) + modImplementation(libs.fabric.api.networking) +} + +tasks { + shadowJar { + configurations = listOf(shadowBundleClasspath.get()) + archiveClassifier = "dev-shadow" + } + + remapJar { + inputFile = shadowJar.flatMap { it.archiveFile } + } +} 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..86fc76c1 --- /dev/null +++ b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketHandler.java @@ -0,0 +1,60 @@ +/* + * 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.apache.commons.compress.archivers.sevenz.CLI; +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 : CLIENTBOUND_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/FabricCUIPacketRegistration.java b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketRegistration.java new file mode 100644 index 00000000..eace301f --- /dev/null +++ b/worldeditcui-protocol-fabric/src/main/java/org/enginehub/worldeditcui/fabric/network/FabricCUIPacketRegistration.java @@ -0,0 +1,28 @@ +/* + * 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.ModInitializer; +import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; +import org.enginehub.worldeditcui.protocol.CUIPacket; + +public class FabricCUIPacketRegistration implements ModInitializer { + @Override + public void onInitialize() { + PayloadTypeRegistry.playS2C().register(CUIPacket.TYPE, CUIPacket.CODEC); + PayloadTypeRegistry.playC2S().register(CUIPacket.TYPE, CUIPacket.CODEC); + FabricCUIPacketHandler.register(); + } +} 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 new file mode 100644 index 00000000..2b70e80f --- /dev/null +++ b/worldeditcui-protocol-fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,40 @@ +{ + "schemaVersion": 1, + "id": "worldeditcui_protocol", + "version": "${version}", + "name": "WorldEditCUI Protocol (Fabric)", + "description": "Protocol implementation for the client-side user interface for WorldEdit", + "authors": [ + "lahwran", + "yetanotherx", + "Mumfrey", + "TomyLobo", + "mikroskeem" + ], + "contact": { + "homepage": "https://github.com/EngineHub/WorldEditCUI", + "sources": "https://github.com/EngineHub/WorldEditCUI" + }, + "custom": { + "modmenu": { + "badges": [ "library" ], + "links": { + "modmenu.discord": "https://discord.gg/enginehub" + } + } + }, + "license": "EPL-2.0", + "entrypoints": { + "main": [ + "org.enginehub.worldeditcui.fabric.network.FabricCUIPacketRegistration" + ], + "client": [ + "org.enginehub.worldeditcui.fabric.network.FabricClientCUIPacketRegistration" + ] + }, + "depends": { + "fabric-api-base": "*", + "fabric-networking-api-v1": "*", + "minecraft": ">=1.20.5" + } +} diff --git a/worldeditcui-protocol-neoforge/build.gradle.kts b/worldeditcui-protocol-neoforge/build.gradle.kts new file mode 100644 index 00000000..77b32db6 --- /dev/null +++ b/worldeditcui-protocol-neoforge/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + alias(libs.plugins.architecturyPlugin) + alias(libs.plugins.loom) + alias(libs.plugins.shadow) +} + +architectury { + neoForge() + platformSetupLoomIde() +} + +configurations { + val common = dependencyScope("common") + compileClasspath { extendsFrom(common.get()) } + runtimeClasspath { extendsFrom(common.get()) } + "developmentNeoForge" { extendsFrom(common.get()) } +} + +val shadowBundle = configurations.dependencyScope("shadowBundle") +val shadowBundleClasspath = configurations.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")) +} + +tasks { + shadowJar { + configurations = listOf(shadowBundleClasspath.get()) + archiveClassifier = "dev-shadow" + } + + remapJar { + inputFile = shadowJar.flatMap { it.archiveFile } + } +} 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..3be62b20 --- /dev/null +++ b/worldeditcui-protocol-neoforge/src/main/java/org/enginehub/worldeditcui/neoforge/protocol/NeoForgeProtocolMod.java @@ -0,0 +1,36 @@ +/* + * 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.IEventBus; +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 { + + public NeoForgeProtocolMod(final IEventBus modBus) { + modBus.register(this); + } + + @SubscribeEvent + public void registerPacket(final RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar(CUIPacket.protocolVersion()).optional(); + 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..06eb65ff --- /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