From 9aa84fa04e416b0090e86d8b8cb77f09fcd318bc Mon Sep 17 00:00:00 2001 From: obus-globus <254700516+obus-globus@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:23:34 +0200 Subject: [PATCH 1/2] Add a NeoForge subproject Builds mcef-neoforge from the same sources via ModDevGradle. Publish with: ./gradlew :neoforge:publishToMavenLocal -Pmod_version= --- gradle.properties | 5 + neoforge/build.gradle | 143 ++++++++++++++++++ .../mcef/neoforge/MCEFNeoForge.java | 15 ++ .../resources/META-INF/neoforge.mods.toml | 25 +++ settings.gradle | 7 + 5 files changed, 195 insertions(+) create mode 100644 neoforge/build.gradle create mode 100644 neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java create mode 100644 neoforge/src/main/resources/META-INF/neoforge.mods.toml diff --git a/gradle.properties b/gradle.properties index c8ebea8c..1662c21d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,11 @@ maven_group=CCBlueX loom_version=1.16-SNAPSHOT +moddev_version=2.0.141 +neoforge_version=26.1.2.75 +neoforge_version_range=[26.1,) +mod_mc_version_range=(1.21.11,26.2) + mod_id=mcef mod_name=MCEF (Minecraft Chromium Embedded Framework) mod_vendor=CCBlueX diff --git a/neoforge/build.gradle b/neoforge/build.gradle new file mode 100644 index 00000000..e8b6b6ac --- /dev/null +++ b/neoforge/build.gradle @@ -0,0 +1,143 @@ +plugins { + id 'net.neoforged.moddev' + id 'maven-publish' +} + +static def getCheckedOutGitCommitHash(Project mcefParent) { + def gitFolder = "$mcefParent.projectDir/.git/modules/java-cef/" + def takeFromHash = 40 + /* + * '.git/HEAD' contains either + * in case of detached head: the currently checked out commit hash + * otherwise: a reference to a file containing the current commit hash + */ + def gitHeadFile = new File(gitFolder + "HEAD") + if (gitHeadFile.exists()) { + def head = gitHeadFile.text.split(":") // .git/HEAD + def isCommit = head.length == 1 // e5a7c79edabbf7dd39888442df081b1c9d8e88fd + + if (isCommit) return head[0].trim().take(takeFromHash) // e5a7c79edabb + + def refHead = new File(gitFolder + head[1].trim()) // .git/refs/heads/master + refHead.text.trim().take takeFromHash + } else { + return "" + } +} + +tasks.register('generateJcefCommitFile') { + def commitFile = layout.buildDirectory.file("jcef.commit") + outputs.file commitFile + doLast { + def commitHash = getCheckedOutGitCommitHash(rootProject) + if (!commitHash.isEmpty()) { + commitFile.get().asFile.text = commitHash + } else { + throw new GradleException("Unable to determine JCEF commit hash.") + } + } +} + +version = project.mod_version +group = 'net.ccbluex' + +base { + archivesName = "${project.archives_base_name}-neoforge" +} + +repositories { + mavenCentral() + mavenLocal() +} + +neoForge { + version = project.neoforge_version +} + +dependencies { + implementation "com.squareup.okhttp3:okhttp:4.12.0" + implementation "org.lwjgl:lwjgl-egl:3.4.1" +} + +sourceSets { + jcef { + java { + srcDir rootProject.file("java-cef/java") + exclude "**/tests/**" + } + } + + main { + java { + srcDir rootProject.file("src/main/java") + } + resources { + srcDir rootProject.file("src/main/resources") + } + compileClasspath += jcef.output + runtimeClasspath += jcef.output + } +} + +processResources { + exclude 'fabric.mod.json' + + filesMatching('META-INF/neoforge.mods.toml') { + expand 'mod_id': mod_id, + 'mod_name': mod_name, + 'mod_vendor': mod_vendor, + 'mod_version': mod_version, + 'minecraft_version_range': mod_mc_version_range, + 'neoforge_version_range': neoforge_version_range + } + + inputs.property "version", project.version +} + +jar { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + manifest { + attributes(['Specification-Title' : "${archives_base_name}-neoforge", + 'Specification-Vendor' : group, + 'Specification-Version' : "1", + 'Implementation-Title' : "${archives_base_name}-neoforge", + 'Implementation-Version' : mod_version, + 'Implementation-Vendor' : group, + 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + 'java-cef-commit' : getCheckedOutGitCommitHash(rootProject) + ]) + } + from sourceSets.jcef.output + from(rootProject.file("LICENSE")) { + rename { "${it}_${project.base.archivesName.get()}" } + } + from tasks.named('generateJcefCommitFile') +} + +java { + withSourcesJar() +} + +publishing { + publications { + mavenJava(MavenPublication) { + artifactId = "${project.archives_base_name}-neoforge" + from components.java + } + } + + repositories { + maven { + name = "ccbluex-maven" + def isSnapshot = version.toString().endsWith("-SNAPSHOT") + url = isSnapshot ? uri("https://maven.ccbluex.net/snapshots") : uri("https://maven.ccbluex.net/releases") + credentials { + username = System.getenv("MAVEN_TOKEN_NAME") + password = System.getenv("MAVEN_TOKEN_SECRET") + } + authentication { + basic(BasicAuthentication) + } + } + } +} diff --git a/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java b/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java new file mode 100644 index 00000000..84d3eda0 --- /dev/null +++ b/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java @@ -0,0 +1,15 @@ +package net.ccbluex.liquidbounce.mcef.neoforge; + +import net.neoforged.fml.common.Mod; + +/** + * NeoForge mod entry point. MCEF is a pure library mod and performs no + * initialization on its own; this class only exists because the javafml + * language provider requires an {@link Mod @Mod} annotated class per mod id. + */ +@Mod("mcef") +public final class MCEFNeoForge { + + public MCEFNeoForge() { + } +} diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 00000000..9f26eb41 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,25 @@ +modLoader = "javafml" +loaderVersion = "[1,)" +license = "LGPL 2.1" + +[[mods]] +modId = "${mod_id}" +version = "${mod_version}" +displayName = "${mod_name}" +authors = "${mod_vendor}" +description = "A Minecraft mod and library for adding the Chromium web browser into the game (Minecraft Chromium Embedded Framework)." +logoFile = "icon.png" + +[[dependencies.${mod_id}]] +modId = "minecraft" +type = "required" +versionRange = "${minecraft_version_range}" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${mod_id}]] +modId = "neoforge" +type = "required" +versionRange = "${neoforge_version_range}" +ordering = "NONE" +side = "BOTH" diff --git a/settings.gradle b/settings.gradle index ad9339e7..8f73d4f0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,13 +4,20 @@ pluginManagement { name = 'Fabric' url = 'https://maven.fabricmc.net/' } + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } gradlePluginPortal() } plugins { id 'fabric-loom' version loom_version + id 'net.neoforged.moddev' version moddev_version } } rootProject.name = 'mcef' + +include 'neoforge' From 542a7e5857bff54178354b36f87250d5734da3ab Mon Sep 17 00:00:00 2001 From: obus-globus <254700516+obus-globus@users.noreply.github.com> Date: Wed, 10 Jun 2026 18:09:37 +0200 Subject: [PATCH 2/2] Harden the NeoForge subproject Disable the module's tasks while the NeoForge version does not match the Minecraft version: NeoForge releases lag new Minecraft versions, and a failing neoforge build would otherwise block the push-triggered publishing workflow. Pin the bytecode target to Java 25 (required by NeoForge 26.1; the Fabric artifact stays on 21), declare the version ranges as processResources inputs, and limit the NeoForged repository to its own groups. --- gradle.properties | 1 + neoforge/build.gradle | 21 ++++++++++++++++ .../mcef/neoforge/MCEFNeoForge.java | 24 ++++++++++++++++--- settings.gradle | 3 +++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1662c21d..e664ee1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,6 +13,7 @@ loom_version=1.16-SNAPSHOT moddev_version=2.0.141 neoforge_version=26.1.2.75 neoforge_version_range=[26.1,) +# The same range as mod_mc_version, in Maven syntax - keep the two in sync mod_mc_version_range=(1.21.11,26.2) mod_id=mcef diff --git a/neoforge/build.gradle b/neoforge/build.gradle index e8b6b6ac..cec6922d 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -45,6 +45,19 @@ base { archivesName = "${project.archives_base_name}-neoforge" } +// If NeoForge lags behind after a Minecraft update, it must not break the Fabric +// build or its publishing: disable this module's tasks while the versions do not match. +def neoForgeMinecraftVersion = neoforge_version.tokenize('.').take(3).join('.') +def paddedMinecraftVersion = (minecraft_version.tokenize('.') + ['0', '0']).take(3).join('.') + +if (neoForgeMinecraftVersion != paddedMinecraftVersion) { + logger.warn("NeoForge ${neoforge_version} targets Minecraft ${neoForgeMinecraftVersion}, but the " + + "project is on Minecraft ${minecraft_version}. The neoforge tasks are disabled " + + "until a matching NeoForge version is available.") + + tasks.configureEach { enabled = false } +} + repositories { mavenCentral() mavenLocal() @@ -59,6 +72,12 @@ dependencies { implementation "org.lwjgl:lwjgl-egl:3.4.1" } +// NeoForge 26.1 requires Java 25, so this artifact targets a newer level than +// the Fabric artifact (Java 21) +tasks.withType(JavaCompile).configureEach { + options.release = 25 +} + sourceSets { jcef { java { @@ -92,6 +111,8 @@ processResources { } inputs.property "version", project.version + inputs.property "minecraft_version_range", mod_mc_version_range + inputs.property "neoforge_version_range", neoforge_version_range } jar { diff --git a/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java b/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java index 84d3eda0..d813cee9 100644 --- a/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java +++ b/neoforge/src/main/java/net/ccbluex/liquidbounce/mcef/neoforge/MCEFNeoForge.java @@ -1,3 +1,24 @@ +/* + * MCEF (Minecraft Chromium Embedded Framework) + * Copyright (C) 2025 CCBlueX + * Copyright (C) 2023 CinemaMod Group + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + package net.ccbluex.liquidbounce.mcef.neoforge; import net.neoforged.fml.common.Mod; @@ -9,7 +30,4 @@ */ @Mod("mcef") public final class MCEFNeoForge { - - public MCEFNeoForge() { - } } diff --git a/settings.gradle b/settings.gradle index 8f73d4f0..73959eb4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,6 +7,9 @@ pluginManagement { maven { name = 'NeoForged' url = 'https://maven.neoforged.net/releases' + content { + includeGroupAndSubgroups 'net.neoforged' + } } gradlePluginPortal() }