From 7a830d867dc7a0f47e9339ac1997e70804c96cfa Mon Sep 17 00:00:00 2001 From: david Date: Sat, 27 Jun 2026 12:42:49 +0200 Subject: [PATCH 1/3] Update Gradle build scripts in preparation of proper multi version support --- .github/workflows/build.yml | 2 + .github/workflows/maven-publish.yml | 2 +- README.md | 20 ++++- build.gradle.kts | 80 +++++++++---------- bukkit/build.gradle.kts | 17 ++-- bukkit/example-plugin/build.gradle.kts | 13 ++- bungeecord/build.gradle.kts | 14 +++- bungeecord/example-plugin/build.gradle.kts | 11 +++ config/build.gradle.kts | 13 +++ core/build.gradle.kts | 13 +++ core/example/build.gradle.kts | 11 +++ fabric/build.gradle.kts | 21 ++++- fabric/example-mod/build.gradle.kts | 12 ++- .../dev/faststats/fabric/FabricContext.java | 10 ++- .../faststats/fabric/FabricMetricsClient.java | 21 ++--- .../faststats/fabric/FabricMetricsServer.java | 16 ++-- .../fabric/compat/CompatibilityLayer.java | 16 ++++ fabric/src/main/java/module-info.java | 3 + fabric/versions/26.1/build.gradle.kts | 21 +++++ .../v26_1/CompatibilityLayer_v26_1.java | 46 +++++++++++ .../26.1/src/main/java/module-info.java | 10 +++ ...faststats.fabric.compat.CompatibilityLayer | 1 + hytale/build.gradle.kts | 14 +++- hytale/example-plugin/build.gradle.kts | 11 +++ minestom/build.gradle.kts | 13 +++ minestom/example-server/build.gradle.kts | 11 +++ neoforge/build.gradle.kts | 19 ++++- neoforge/example-mod/build.gradle.kts | 4 +- .../faststats/neoforge/NeoForgeContext.java | 10 ++- .../neoforge/NeoForgeMetricsClient.java | 22 ++--- .../neoforge/NeoForgeMetricsServer.java | 17 ++-- .../neoforge/compat/CompatibilityLayer.java | 16 ++++ neoforge/src/main/java/module-info.java | 5 +- neoforge/versions/26.1/build.gradle.kts | 27 +++++++ .../v26_1/CompatibilityLayer_v26_1.java | 47 +++++++++++ .../26.1/src/main/java/module-info.java | 10 +++ ...ststats.neoforge.compat.CompatibilityLayer | 1 + nukkit/build.gradle.kts | 14 +++- nukkit/example-plugin/build.gradle.kts | 11 +++ settings.gradle.kts | 2 + sponge/build.gradle.kts | 14 +++- sponge/example-plugin/build.gradle.kts | 11 +++ velocity/build.gradle.kts | 13 +++ velocity/example-plugin/build.gradle.kts | 11 +++ 44 files changed, 562 insertions(+), 114 deletions(-) create mode 100644 fabric/src/main/java/dev/faststats/fabric/compat/CompatibilityLayer.java create mode 100644 fabric/versions/26.1/build.gradle.kts create mode 100644 fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java create mode 100644 fabric/versions/26.1/src/main/java/module-info.java create mode 100644 fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer create mode 100644 neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java create mode 100644 neoforge/versions/26.1/build.gradle.kts create mode 100644 neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java create mode 100644 neoforge/versions/26.1/src/main/java/module-info.java create mode 100644 neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 308b16fd..b87d5c62 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,5 +17,7 @@ jobs: cache-read-only: ${{ github.ref != 'refs/heads/main' }} - name: Build with Gradle run: ./gradlew build + - name: Check platform compatibility modules + run: ./gradlew checkPlatformCompat - name: Test with Gradle run: ./gradlew test diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index de77eea2..34f171af 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -21,4 +21,4 @@ jobs: env: REPOSITORY_USER: ${{ secrets.REPOSITORY_USER }} REPOSITORY_TOKEN: ${{ secrets.REPOSITORY_TOKEN }} - run: ./gradlew publish \ No newline at end of file + run: ./gradlew publish publishPlatformCompat diff --git a/README.md b/README.md index 76cf1ce6..8e8d9d22 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,23 @@ Use `build` for the reusable FastStats libraries: ./gradlew :config:build ./gradlew :bukkit:build ./gradlew :bungeecord:build -./gradlew :fabric:build +./gradlew :fabric:versions:26.1:build ./gradlew :hytale:build ./gradlew :minestom:build +./gradlew :neoforge:versions:26.1:build ./gradlew :nukkit:build ./gradlew :sponge:build ./gradlew :velocity:build ``` -Library jars are written to each module's `build/libs` directory. Fabric also produces a remapped jar through Fabric Loom as part of its build output. +Library jars are written to each module's `build/libs` directory. Fabric and NeoForge publish compatibility modules, such as `fabric:versions:26.1` and `neoforge:versions:26.1`, under stable Maven artifact IDs with Minecraft range suffixes: + +```text +dev.faststats.metrics:fabric:+mc26.1-26.2 +dev.faststats.metrics:neoforge:+mc26.1-26.2 +``` + +The `fabric` and `neoforge` modules contain shared platform code and are not published directly. ### Bukkit, BungeeCord, Hytale, Minestom, Nukkit, Sponge, and Velocity examples @@ -60,3 +68,11 @@ To compile and test all modules with the standard lifecycle, run: ``` For deployable example artifacts, run the platform-specific commands above after `build` or instead of it. + +### Platform compatibility checks + +Compile all published platform compatibility modules with: + +```sh +./gradlew checkPlatformCompat +``` diff --git a/build.gradle.kts b/build.gradle.kts index 0c68bb04..cbf25768 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,57 +4,25 @@ plugins { kotlin("jvm") version "2.4.20-Beta1" apply false } -val javaVersionsOverride = mapOf( - ":bukkit" to 21, - ":bukkit:example-plugin" to 21, - ":fabric" to 25, - ":fabric:example-mod" to 25, - ":hytale" to 25, - ":hytale:example-plugin" to 25, - ":minestom" to 25, - ":minestom:example-server" to 25, - ":neoforge" to 25, - ":neoforge:example-mod" to 25, - ":velocity" to 21, - ":velocity:example-plugin" to 21 -) -val defaultJavaVersion = 17 - subprojects { apply { plugin("java") plugin("java-library") } - val example = project.name.startsWith("example") - if (example) { - apply { plugin("org.jetbrains.kotlin.jvm") } - if (project.path != ":fabric:example-mod" && project.path != ":neoforge:example-mod") { - apply { plugin("com.gradleup.shadow") } - } - } else { - apply { plugin("maven-publish") } - } - group = "dev.faststats.metrics" repositories { mavenCentral() } - val javaVersion = javaVersionsOverride[project.path] ?: defaultJavaVersion - extensions.configure { - toolchain.languageVersion = JavaLanguageVersion.of(javaVersion) withSourcesJar() withJavadocJar() } - tasks.compileJava { - options.release.set(javaVersion) - } - - val generateFastStatsProperties by tasks.registering { + val generateFastStatsProperties = tasks.register("generateFastStatsProperties") { + description = "Generates the META-INF/faststats.properties file" val outputDir = layout.buildDirectory.dir("generated/resources/faststats") outputs.dir(outputDir) doLast { @@ -76,20 +44,24 @@ subprojects { } } + fun ownProperty(name: String): String? { + return if (extensions.extraProperties.has(name)) extensions.extraProperties.get(name).toString() else null + } + tasks.withType().configureEach { - project.findProperty("moduleName")?.let { moduleName -> + ownProperty("moduleName")?.let { moduleName -> options.compilerArgs.addAll(listOf("--add-reads", "$moduleName=ALL-UNNAMED")) } } tasks.withType().configureEach { - project.findProperty("moduleName")?.let { moduleName -> + ownProperty("moduleName")?.let { moduleName -> jvmArgs("--add-reads", "$moduleName=ALL-UNNAMED") } } tasks.withType().configureEach { - project.findProperty("moduleName")?.let { moduleName -> + ownProperty("moduleName")?.let { moduleName -> jvmArgs("--add-reads", "$moduleName=ALL-UNNAMED") } } @@ -101,20 +73,33 @@ subprojects { "implSpec:a:Implementation Requirements:", "implNote:a:Implementation Note:" ) - project.findProperty("moduleName")?.let { moduleName -> + ownProperty("moduleName")?.let { moduleName -> options.addStringOption("-add-reads", "$moduleName=ALL-UNNAMED") } } afterEvaluate { - if (example) return@afterEvaluate + val publishArtifactId = ownProperty("publishArtifactId") + if (!plugins.hasPlugin("maven-publish") && publishArtifactId == null) return@afterEvaluate + if (!plugins.hasPlugin("maven-publish") || publishArtifactId == null) throw IllegalStateException( + "Invalid publishing setup for project \"${project.path}\", " + + "maven-publish: ${plugins.hasPlugin("maven-publish")}, publishArtifactId: $publishArtifactId" + ) + + ownProperty("publishVersionSuffix")?.let { suffix -> + version = "${rootProject.version}+$suffix" + } + extensions.configure { publications.create("maven") { - artifactId = project.name + artifactId = publishArtifactId groupId = "dev.faststats.metrics" pom { - url.set("https://faststats.dev/docs") + url.set( + ownProperty("publishDocsUrl") + ?: throw IllegalStateException("No docs URL provided by \"${project.path}\"") + ) scm { val repository = "faststats-dev/faststats-java" url.set("https://github.com/$repository") @@ -139,3 +124,16 @@ subprojects { } } } + +// todo: automate dependsOn +tasks.register("checkPlatformCompat") { + group = "verification" + description = "Compiles all platform compatibility modules." + dependsOn(":fabric:versions:26.1:compileJava", ":neoforge:versions:26.1:compileJava") +} + +tasks.register("publishPlatformCompat") { + group = "publishing" + description = "Publishes all platform compatibility modules." + dependsOn(":fabric:versions:26.1:publish", ":neoforge:versions:26.1:publish") +} diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index dce2e74c..f0e9ba4f 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -1,15 +1,22 @@ -repositories { - maven("https://repo.papermc.io/repository/maven-public/") +extra.set("publishArtifactId", "bukkit") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/bukkit") + +plugins { + id("maven-publish") } +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + tasks.compileJava { options.release.set(17) } configurations.compileClasspath { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21) - } + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25) +} + +repositories { + maven("https://repo.papermc.io/repository/maven-public/") } dependencies { diff --git a/bukkit/example-plugin/build.gradle.kts b/bukkit/example-plugin/build.gradle.kts index 2eb110ef..f7bc721b 100644 --- a/bukkit/example-plugin/build.gradle.kts +++ b/bukkit/example-plugin/build.gradle.kts @@ -1,9 +1,20 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + repositories { maven("https://repo.papermc.io/repository/maven-public/") } dependencies { - compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:26.2.build.+") implementation(project(":bukkit")) } diff --git a/bungeecord/build.gradle.kts b/bungeecord/build.gradle.kts index 7bf56fae..54b2613c 100644 --- a/bungeecord/build.gradle.kts +++ b/bungeecord/build.gradle.kts @@ -1,4 +1,16 @@ -val moduleName by extra("dev.faststats.bungee") +extra.set("moduleName", "dev.faststats.bungee") +extra.set("publishArtifactId", "bungeecord") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/bungeecord") + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} repositories { maven("https://repo.papermc.io/repository/maven-public/") diff --git a/bungeecord/example-plugin/build.gradle.kts b/bungeecord/example-plugin/build.gradle.kts index 4c9f9bab..69d5ce9f 100644 --- a/bungeecord/example-plugin/build.gradle.kts +++ b/bungeecord/example-plugin/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} + repositories { maven("https://repo.papermc.io/repository/maven-public/") } diff --git a/config/build.gradle.kts b/config/build.gradle.kts index e762f00d..21598390 100644 --- a/config/build.gradle.kts +++ b/config/build.gradle.kts @@ -1,3 +1,16 @@ +extra.set("publishArtifactId", "config") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java") // todo: add dedicated docs + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} + dependencies { compileOnly(project(":core")) } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 8b573fab..eaa3ad58 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,3 +1,16 @@ +extra.set("publishArtifactId", "core") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java") // todo: add dedicated docs + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} + dependencies { compileOnlyApi("com.google.code.gson:gson:2.14.0") compileOnlyApi("org.jetbrains:annotations:26.1.0") diff --git a/core/example/build.gradle.kts b/core/example/build.gradle.kts index eca1ab1c..7a04956a 100644 --- a/core/example/build.gradle.kts +++ b/core/example/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} + dependencies { implementation(project(":core")) } diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 3bf8958f..6901dc86 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -1,7 +1,24 @@ -val moduleName by extra("dev.faststats.fabric") +extra.set("moduleName", "dev.faststats.fabric") plugins { - id("net.fabricmc.fabric-loom") version ("1.15-SNAPSHOT") + id("net.fabricmc.fabric-loom") version "1.15-SNAPSHOT" +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(21) +} + +configurations.compileClasspath { + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25) +} + +allprojects { + if (project.name == "example-mod") return@allprojects + apply { plugin("maven-publish") } + extra.set("publishArtifactId", "fabric") + extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/fabric") } dependencies { diff --git a/fabric/example-mod/build.gradle.kts b/fabric/example-mod/build.gradle.kts index 9d362001..0187763e 100644 --- a/fabric/example-mod/build.gradle.kts +++ b/fabric/example-mod/build.gradle.kts @@ -1,9 +1,16 @@ plugins { id("net.fabricmc.fabric-loom") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) } dependencies { - implementation(project(":fabric")) + implementation(project(":fabric:versions:26.1")) minecraft("com.mojang:minecraft:26.1.2") implementation("net.fabricmc.fabric-api:fabric-api:0.150.0+26.1.2") compileOnly("net.fabricmc:fabric-loader:0.19.3") @@ -14,4 +21,5 @@ tasks.jar { from(project(":config").sourceSets["main"].output) from(project(":core").sourceSets["main"].output) from(project(":fabric").sourceSets["main"].output) -} \ No newline at end of file + from(project(":fabric:versions:26.1").sourceSets["main"].output) +} diff --git a/fabric/src/main/java/dev/faststats/fabric/FabricContext.java b/fabric/src/main/java/dev/faststats/fabric/FabricContext.java index adc2ffa5..4bf33bcb 100644 --- a/fabric/src/main/java/dev/faststats/fabric/FabricContext.java +++ b/fabric/src/main/java/dev/faststats/fabric/FabricContext.java @@ -5,6 +5,7 @@ import dev.faststats.SimpleMetrics; import dev.faststats.Token; import dev.faststats.config.SimpleConfig; +import dev.faststats.fabric.compat.CompatibilityLayer; import dev.faststats.internal.PlatformLoggerFactory; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -13,6 +14,7 @@ import org.jetbrains.annotations.Contract; import java.util.Set; +import java.util.ServiceLoader; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -31,6 +33,7 @@ public final class FabricContext extends SimpleContext { return thread; }); private final Set> tasks = new CopyOnWriteArraySet<>(); + private final CompatibilityLayer compatibilityLayer; private final ModContainer mod; private FabricContext(final Factory factory, final dev.faststats.internal.LoggerFactory loggerFactory, final String modId, @Token final String token) { @@ -40,6 +43,9 @@ private FabricContext(final Factory factory, final dev.faststats.internal.Logger this.mod = FabricLoader.getInstance().getModContainer(modId).orElseThrow(() -> { return new IllegalArgumentException("Mod not found: " + modId); }); + this.compatibilityLayer = ServiceLoader.load(CompatibilityLayer.class) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No Fabric compatibility layer found")); initializeServices(factory); switch (FabricLoader.getInstance().getEnvironmentType()) { case CLIENT -> { @@ -60,8 +66,8 @@ protected Metrics.Factory metricsFactory() { @Override public Metrics create() throws IllegalStateException { return switch (FabricLoader.getInstance().getEnvironmentType()) { - case CLIENT -> new FabricMetricsClient(this, mod); - case SERVER -> new FabricMetricsServer(this, mod); + case CLIENT -> new FabricMetricsClient(this, mod, compatibilityLayer); + case SERVER -> new FabricMetricsServer(this, mod, compatibilityLayer); }; } }; diff --git a/fabric/src/main/java/dev/faststats/fabric/FabricMetricsClient.java b/fabric/src/main/java/dev/faststats/fabric/FabricMetricsClient.java index 908eb689..5bc711cc 100644 --- a/fabric/src/main/java/dev/faststats/fabric/FabricMetricsClient.java +++ b/fabric/src/main/java/dev/faststats/fabric/FabricMetricsClient.java @@ -1,30 +1,21 @@ package dev.faststats.fabric; import com.google.gson.JsonObject; +import dev.faststats.fabric.compat.CompatibilityLayer; import net.fabricmc.loader.api.ModContainer; -import net.minecraft.client.Minecraft; final class FabricMetricsClient extends FabricMetrics { - private final Minecraft client = Minecraft.getInstance(); + private final CompatibilityLayer compatibilityLayer; - public FabricMetricsClient(final Factory factory, final ModContainer mod) throws IllegalStateException { + FabricMetricsClient(final Factory factory, final ModContainer mod, final CompatibilityLayer compatibilityLayer) throws IllegalStateException { super(factory, mod); + this.compatibilityLayer = compatibilityLayer; } @Override protected void appendDefaultData(final JsonObject metrics) { - metrics.addProperty("online_mode", client.getUser().getXuid().isPresent() && !client.isOfflineDeveloperMode()); // todo: doublecheck - metrics.addProperty("player_count", getPlayerCount()); + metrics.addProperty("online_mode", compatibilityLayer.clientOnlineMode()); + metrics.addProperty("player_count", compatibilityLayer.clientPlayerCount()); appendFabricData(metrics, "Fabric Client"); } - - private int getPlayerCount() { - final var connection = client.getConnection(); - if (connection != null) return connection.getOnlinePlayers().size(); - - final var server = client.getSingleplayerServer(); - if (server != null) return server.getPlayerCount(); - - return client.player == null ? 0 : 1; - } } diff --git a/fabric/src/main/java/dev/faststats/fabric/FabricMetricsServer.java b/fabric/src/main/java/dev/faststats/fabric/FabricMetricsServer.java index f078f769..8fed32e6 100644 --- a/fabric/src/main/java/dev/faststats/fabric/FabricMetricsServer.java +++ b/fabric/src/main/java/dev/faststats/fabric/FabricMetricsServer.java @@ -1,24 +1,22 @@ package dev.faststats.fabric; import com.google.gson.JsonObject; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import dev.faststats.fabric.compat.CompatibilityLayer; import net.fabricmc.loader.api.ModContainer; -import net.minecraft.server.MinecraftServer; -import org.jspecify.annotations.Nullable; final class FabricMetricsServer extends FabricMetrics { - private @Nullable MinecraftServer server; + private final CompatibilityLayer compatibilityLayer; - public FabricMetricsServer(final Factory factory, final ModContainer mod) throws IllegalStateException { + FabricMetricsServer(final Factory factory, final ModContainer mod, final CompatibilityLayer compatibilityLayer) throws IllegalStateException { super(factory, mod); - ServerLifecycleEvents.SERVER_STARTING.register(server -> this.server = server); + this.compatibilityLayer = compatibilityLayer; + compatibilityLayer.initServer(); } @Override protected void appendDefaultData(final JsonObject metrics) { - assert server != null : "Server not initialized"; - metrics.addProperty("online_mode", server.usesAuthentication()); - metrics.addProperty("player_count", server.getPlayerCount()); + metrics.addProperty("online_mode", compatibilityLayer.serverOnlineMode()); + metrics.addProperty("player_count", compatibilityLayer.serverPlayerCount()); appendFabricData(metrics, "Fabric"); } } diff --git a/fabric/src/main/java/dev/faststats/fabric/compat/CompatibilityLayer.java b/fabric/src/main/java/dev/faststats/fabric/compat/CompatibilityLayer.java new file mode 100644 index 00000000..2a899e76 --- /dev/null +++ b/fabric/src/main/java/dev/faststats/fabric/compat/CompatibilityLayer.java @@ -0,0 +1,16 @@ +package dev.faststats.fabric.compat; + +/** + * Version-specific Fabric integration hooks. + */ +public interface CompatibilityLayer { + void initServer(); + + boolean clientOnlineMode(); + + int clientPlayerCount(); + + boolean serverOnlineMode(); + + int serverPlayerCount(); +} diff --git a/fabric/src/main/java/module-info.java b/fabric/src/main/java/module-info.java index 4f28b6c9..7a85bdcf 100644 --- a/fabric/src/main/java/module-info.java +++ b/fabric/src/main/java/module-info.java @@ -2,6 +2,7 @@ @NullMarked module dev.faststats.fabric { + exports dev.faststats.fabric.compat; exports dev.faststats.fabric; requires com.google.gson; @@ -13,4 +14,6 @@ requires static org.jetbrains.annotations; requires static org.jspecify; + + uses dev.faststats.fabric.compat.CompatibilityLayer; } diff --git a/fabric/versions/26.1/build.gradle.kts b/fabric/versions/26.1/build.gradle.kts new file mode 100644 index 00000000..0dc09d8f --- /dev/null +++ b/fabric/versions/26.1/build.gradle.kts @@ -0,0 +1,21 @@ +extra.set("moduleName", "dev.faststats.fabric.compat.v26_1") +extra.set("publishVersionSuffix", "mc26.1-26.2") + +plugins { + id("net.fabricmc.fabric-loom") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + +dependencies { + api(project(":fabric")) + api(project(":core")) + implementation(project(":config")) + minecraft("com.mojang:minecraft:26.1.2") + compileOnly("net.fabricmc.fabric-api:fabric-api:0.150.0+26.1.2") + compileOnly("net.fabricmc:fabric-loader:0.19.3") +} diff --git a/fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java b/fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java new file mode 100644 index 00000000..8107efa7 --- /dev/null +++ b/fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java @@ -0,0 +1,46 @@ +package dev.faststats.fabric.compat.v26_1; + +import dev.faststats.fabric.compat.CompatibilityLayer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.minecraft.client.Minecraft; +import net.minecraft.server.MinecraftServer; +import org.jspecify.annotations.Nullable; + +public final class CompatibilityLayer_v26_1 implements CompatibilityLayer { + private @Nullable MinecraftServer server; + + @Override + public void initServer() { + ServerLifecycleEvents.SERVER_STARTING.register(server -> this.server = server); + } + + @Override + public boolean clientOnlineMode() { + final var client = Minecraft.getInstance(); + return client.getUser().getXuid().isPresent() && !client.isOfflineDeveloperMode(); + } + + @Override + public int clientPlayerCount() { + final var client = Minecraft.getInstance(); + final var connection = client.getConnection(); + if (connection != null) return connection.getOnlinePlayers().size(); + + final var server = client.getSingleplayerServer(); + if (server != null) return server.getPlayerCount(); + + return client.player == null ? 0 : 1; + } + + @Override + public boolean serverOnlineMode() { + assert server != null : "Server not initialized"; + return server.usesAuthentication(); + } + + @Override + public int serverPlayerCount() { + assert server != null : "Server not initialized"; + return server.getPlayerCount(); + } +} diff --git a/fabric/versions/26.1/src/main/java/module-info.java b/fabric/versions/26.1/src/main/java/module-info.java new file mode 100644 index 00000000..21a215b8 --- /dev/null +++ b/fabric/versions/26.1/src/main/java/module-info.java @@ -0,0 +1,10 @@ +import org.jspecify.annotations.NullMarked; + +@NullMarked +module dev.faststats.fabric.compat.v26_1 { + requires dev.faststats.fabric; + + requires static org.jspecify; + + provides dev.faststats.fabric.compat.CompatibilityLayer with dev.faststats.fabric.compat.v26_1.CompatibilityLayer_v26_1; +} diff --git a/fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer b/fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer new file mode 100644 index 00000000..6345d674 --- /dev/null +++ b/fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.fabric.compat.v26_1.CompatibilityLayer_v26_1 diff --git a/hytale/build.gradle.kts b/hytale/build.gradle.kts index 5bc9ebac..04d0283a 100644 --- a/hytale/build.gradle.kts +++ b/hytale/build.gradle.kts @@ -1,4 +1,16 @@ -val moduleName by extra("dev.faststats.hytale") +extra.set("moduleName", "dev.faststats.hytale") +extra.set("publishArtifactId", "hytale") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/hytale") + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} repositories { maven("https://maven.hytale.com/pre-release") diff --git a/hytale/example-plugin/build.gradle.kts b/hytale/example-plugin/build.gradle.kts index 1f29c00a..be124366 100644 --- a/hytale/example-plugin/build.gradle.kts +++ b/hytale/example-plugin/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + repositories { maven("https://maven.hytale.com/pre-release") } diff --git a/minestom/build.gradle.kts b/minestom/build.gradle.kts index 08a06eeb..83bc75a0 100644 --- a/minestom/build.gradle.kts +++ b/minestom/build.gradle.kts @@ -1,3 +1,16 @@ +extra.set("publishArtifactId", "minestom") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/minestom") + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + dependencies { api(project(":core")) implementation(project(":config")) diff --git a/minestom/example-server/build.gradle.kts b/minestom/example-server/build.gradle.kts index 3206ab38..0de9b117 100644 --- a/minestom/example-server/build.gradle.kts +++ b/minestom/example-server/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + dependencies { implementation("net.minestom:minestom:2026.05.11-1.21.11") implementation(project(":minestom")) diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index dcb43d69..5555a288 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -1,9 +1,26 @@ -val moduleName by extra("dev.faststats.neoforge") +extra.set("moduleName", "dev.faststats.neoforge") plugins { id("net.neoforged.moddev") version "2.0.141" } +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(21) +} + +configurations.compileClasspath { + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25) +} + +allprojects { + if (project.name == "example-mod") return@allprojects + apply { plugin("maven-publish") } + extra.set("publishArtifactId", "neoforge") + extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/neoforge") +} + neoForge { version = "26.1.2.76" } diff --git a/neoforge/example-mod/build.gradle.kts b/neoforge/example-mod/build.gradle.kts index b053c020..40d9bcf0 100644 --- a/neoforge/example-mod/build.gradle.kts +++ b/neoforge/example-mod/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id("net.neoforged.moddev") version "2.0.141" + kotlin("jvm") } neoForge { @@ -11,7 +12,7 @@ configurations.configureEach { } dependencies { - implementation(project(":neoforge")) + implementation(project(":neoforge:versions:26.1")) } tasks.jar { @@ -19,4 +20,5 @@ tasks.jar { from(project(":config").sourceSets["main"].output) from(project(":core").sourceSets["main"].output) from(project(":neoforge").sourceSets["main"].output) + from(project(":neoforge:versions:26.1").sourceSets["main"].output) } diff --git a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java index b4fa6cde..ec3c6bc0 100644 --- a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java +++ b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java @@ -7,6 +7,7 @@ import dev.faststats.config.SimpleConfig; import dev.faststats.internal.LoggerFactory; import dev.faststats.internal.PlatformLoggerFactory; +import dev.faststats.neoforge.compat.CompatibilityLayer; import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModList; import net.neoforged.fml.loading.FMLEnvironment; @@ -18,6 +19,7 @@ import org.jetbrains.annotations.Contract; import java.util.Set; +import java.util.ServiceLoader; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -36,6 +38,7 @@ public final class NeoForgeContext extends SimpleContext { return thread; }); private final Set> tasks = new CopyOnWriteArraySet<>(); + private final CompatibilityLayer compatibilityLayer; private final IModInfo mod; private NeoForgeContext(final Factory factory, final LoggerFactory loggerFactory, final String modId, @Token final String token) { @@ -45,6 +48,9 @@ private NeoForgeContext(final Factory factory, final LoggerFactory loggerFactory this.mod = ModList.get().getModContainerById(modId).map(ModContainer::getModInfo).orElseThrow(() -> { return new IllegalArgumentException("Mod not found: " + modId); }); + this.compatibilityLayer = ServiceLoader.load(CompatibilityLayer.class) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No NeoForge compatibility layer found")); initializeServices(factory); switch (FMLEnvironment.getDist()) { case CLIENT -> ready(); @@ -62,8 +68,8 @@ protected Metrics.Factory metricsFactory() { @Override public Metrics create() throws IllegalStateException { return switch (FMLEnvironment.getDist()) { - case CLIENT -> new NeoForgeMetricsClient(this, mod); - case DEDICATED_SERVER -> new NeoForgeMetricsServer(this, mod); + case CLIENT -> new NeoForgeMetricsClient(this, mod, compatibilityLayer); + case DEDICATED_SERVER -> new NeoForgeMetricsServer(this, mod, compatibilityLayer); }; } }; diff --git a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsClient.java b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsClient.java index 78c7fc1d..8dbfbc25 100644 --- a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsClient.java +++ b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsClient.java @@ -1,29 +1,21 @@ package dev.faststats.neoforge; import com.google.gson.JsonObject; -import net.minecraft.client.Minecraft; +import dev.faststats.neoforge.compat.CompatibilityLayer; import net.neoforged.neoforgespi.language.IModInfo; final class NeoForgeMetricsClient extends NeoForgeMetrics { - NeoForgeMetricsClient(final Factory factory, final IModInfo mod) throws IllegalStateException { + private final CompatibilityLayer compatibilityLayer; + + NeoForgeMetricsClient(final Factory factory, final IModInfo mod, final CompatibilityLayer compatibilityLayer) throws IllegalStateException { super(factory, mod); + this.compatibilityLayer = compatibilityLayer; } @Override protected void appendDefaultData(final JsonObject metrics) { - final var client = Minecraft.getInstance(); - metrics.addProperty("online_mode", client.getUser().getXuid().isPresent() && !client.isOfflineDeveloperMode()); - metrics.addProperty("player_count", getPlayerCount(client)); + metrics.addProperty("online_mode", compatibilityLayer.clientOnlineMode()); + metrics.addProperty("player_count", compatibilityLayer.clientPlayerCount()); appendNeoForgeData(metrics, "NeoForge Client"); } - - private static int getPlayerCount(final Minecraft client) { - final var connection = client.getConnection(); - if (connection != null) return connection.getOnlinePlayers().size(); - - final var server = client.getSingleplayerServer(); - if (server != null) return server.getPlayerCount(); - - return client.player == null ? 0 : 1; - } } diff --git a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsServer.java b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsServer.java index 83ea2a1b..cd6da38f 100644 --- a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsServer.java +++ b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeMetricsServer.java @@ -1,25 +1,22 @@ package dev.faststats.neoforge; import com.google.gson.JsonObject; -import net.minecraft.server.MinecraftServer; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.server.ServerStartedEvent; +import dev.faststats.neoforge.compat.CompatibilityLayer; import net.neoforged.neoforgespi.language.IModInfo; -import org.jspecify.annotations.Nullable; final class NeoForgeMetricsServer extends NeoForgeMetrics { - private @Nullable MinecraftServer server; + private final CompatibilityLayer compatibilityLayer; - NeoForgeMetricsServer(final Factory factory, final IModInfo mod) throws IllegalStateException { + NeoForgeMetricsServer(final Factory factory, final IModInfo mod, final CompatibilityLayer compatibilityLayer) throws IllegalStateException { super(factory, mod); - NeoForge.EVENT_BUS.addListener((final ServerStartedEvent event) -> this.server = event.getServer()); + this.compatibilityLayer = compatibilityLayer; + compatibilityLayer.initServer(); } @Override protected void appendDefaultData(final JsonObject metrics) { - assert server != null : "Server not initialized"; - metrics.addProperty("online_mode", server.usesAuthentication()); - metrics.addProperty("player_count", server.getPlayerCount()); + metrics.addProperty("online_mode", compatibilityLayer.serverOnlineMode()); + metrics.addProperty("player_count", compatibilityLayer.serverPlayerCount()); appendNeoForgeData(metrics, "NeoForge"); } } diff --git a/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java b/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java new file mode 100644 index 00000000..553ec0cb --- /dev/null +++ b/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java @@ -0,0 +1,16 @@ +package dev.faststats.neoforge.compat; + +/** + * Version-specific NeoForge integration hooks. + */ +public interface CompatibilityLayer { + void initServer(); + + boolean clientOnlineMode(); + + int clientPlayerCount(); + + boolean serverOnlineMode(); + + int serverPlayerCount(); +} diff --git a/neoforge/src/main/java/module-info.java b/neoforge/src/main/java/module-info.java index 0835ea36..13f8a99b 100644 --- a/neoforge/src/main/java/module-info.java +++ b/neoforge/src/main/java/module-info.java @@ -2,6 +2,7 @@ @NullMarked module dev.faststats.neoforge { + exports dev.faststats.neoforge.compat; exports dev.faststats.neoforge; requires com.google.gson; @@ -13,4 +14,6 @@ requires static org.jetbrains.annotations; requires static org.jspecify; -} \ No newline at end of file + + uses dev.faststats.neoforge.compat.CompatibilityLayer; +} diff --git a/neoforge/versions/26.1/build.gradle.kts b/neoforge/versions/26.1/build.gradle.kts new file mode 100644 index 00000000..01feed0d --- /dev/null +++ b/neoforge/versions/26.1/build.gradle.kts @@ -0,0 +1,27 @@ +extra.set("moduleName", "dev.faststats.neoforge.compat.v26_1") +extra.set("publishVersionSuffix", "mc26.1-26.2") + +plugins { + id("net.neoforged.moddev") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + +neoForge { + version = "26.1.2.76" +} + +configurations.configureEach { + resolutionStrategy.force("com.google.code.gson:gson:2.14.0") +} + +dependencies { + api(project(":neoforge")) + api(project(":core")) + implementation(project(":config")) + compileOnly("net.neoforged:bus:8.0.5") +} diff --git a/neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java b/neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java new file mode 100644 index 00000000..22a3999f --- /dev/null +++ b/neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java @@ -0,0 +1,47 @@ +package dev.faststats.neoforge.compat.v26_1; + +import dev.faststats.neoforge.compat.CompatibilityLayer; +import net.minecraft.client.Minecraft; +import net.minecraft.server.MinecraftServer; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import org.jspecify.annotations.Nullable; + +public final class CompatibilityLayer_v26_1 implements CompatibilityLayer { + private @Nullable MinecraftServer server; + + @Override + public void initServer() { + NeoForge.EVENT_BUS.addListener((final ServerStartedEvent event) -> this.server = event.getServer()); + } + + @Override + public boolean clientOnlineMode() { + final var client = Minecraft.getInstance(); + return client.getUser().getXuid().isPresent() && !client.isOfflineDeveloperMode(); + } + + @Override + public int clientPlayerCount() { + final var client = Minecraft.getInstance(); + final var connection = client.getConnection(); + if (connection != null) return connection.getOnlinePlayers().size(); + + final var server = client.getSingleplayerServer(); + if (server != null) return server.getPlayerCount(); + + return client.player == null ? 0 : 1; + } + + @Override + public boolean serverOnlineMode() { + assert server != null : "Server not initialized"; + return server.usesAuthentication(); + } + + @Override + public int serverPlayerCount() { + assert server != null : "Server not initialized"; + return server.getPlayerCount(); + } +} diff --git a/neoforge/versions/26.1/src/main/java/module-info.java b/neoforge/versions/26.1/src/main/java/module-info.java new file mode 100644 index 00000000..d38b79d4 --- /dev/null +++ b/neoforge/versions/26.1/src/main/java/module-info.java @@ -0,0 +1,10 @@ +import org.jspecify.annotations.NullMarked; + +@NullMarked +module dev.faststats.neoforge.compat.v26_1 { + requires dev.faststats.neoforge; + + requires static org.jspecify; + + provides dev.faststats.neoforge.compat.CompatibilityLayer with dev.faststats.neoforge.compat.v26_1.CompatibilityLayer_v26_1; +} diff --git a/neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer b/neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer new file mode 100644 index 00000000..f9488860 --- /dev/null +++ b/neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.neoforge.compat.v26_1.CompatibilityLayer_v26_1 diff --git a/nukkit/build.gradle.kts b/nukkit/build.gradle.kts index d4a090a7..2525b95c 100644 --- a/nukkit/build.gradle.kts +++ b/nukkit/build.gradle.kts @@ -1,4 +1,16 @@ -val moduleName by extra("dev.faststats.nukkit") +extra.set("moduleName", "dev.faststats.nukkit") +extra.set("publishArtifactId", "nukkit") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/nukkit") + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} repositories { maven("https://repo.opencollab.dev/maven-releases") diff --git a/nukkit/example-plugin/build.gradle.kts b/nukkit/example-plugin/build.gradle.kts index f31553a9..0c189d41 100644 --- a/nukkit/example-plugin/build.gradle.kts +++ b/nukkit/example-plugin/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} + repositories { maven("https://repo.opencollab.dev/maven-releases") maven("https://repo.opencollab.dev/maven-snapshots") diff --git a/settings.gradle.kts b/settings.gradle.kts index ea636283..bc560836 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,12 +18,14 @@ include("core") include("core:example") include("fabric") include("fabric:example-mod") +include("fabric:versions:26.1") include("hytale") include("hytale:example-plugin") include("minestom") include("minestom:example-server") include("neoforge") include("neoforge:example-mod") +include("neoforge:versions:26.1") include("nukkit") include("nukkit:example-plugin") include("sponge") diff --git a/sponge/build.gradle.kts b/sponge/build.gradle.kts index 06fbed98..07c7e56e 100644 --- a/sponge/build.gradle.kts +++ b/sponge/build.gradle.kts @@ -1,4 +1,16 @@ -val moduleName by extra("dev.faststats.sponge") +extra.set("moduleName", "dev.faststats.sponge") +extra.set("publishArtifactId", "sponge") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/sponge") + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} repositories { maven("https://repo.spongepowered.org/repository/maven-public/") diff --git a/sponge/example-plugin/build.gradle.kts b/sponge/example-plugin/build.gradle.kts index ed18b01c..7519b842 100644 --- a/sponge/example-plugin/build.gradle.kts +++ b/sponge/example-plugin/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +tasks.compileJava { + options.release.set(17) +} + repositories { maven("https://repo.spongepowered.org/repository/maven-public/") } diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index ef8247d1..4266d238 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -1,3 +1,16 @@ +extra.set("publishArtifactId", "velocity") +extra.set("publishDocsUrl", "https://docs.faststats.dev/java/platform/velocity") + +plugins { + id("maven-publish") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(21) + +tasks.compileJava { + options.release.set(21) +} + repositories { maven("https://repo.papermc.io/repository/maven-public/") } diff --git a/velocity/example-plugin/build.gradle.kts b/velocity/example-plugin/build.gradle.kts index cb82cb3c..7913e9b3 100644 --- a/velocity/example-plugin/build.gradle.kts +++ b/velocity/example-plugin/build.gradle.kts @@ -1,3 +1,14 @@ +plugins { + id("com.gradleup.shadow") + kotlin("jvm") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(21) + +tasks.compileJava { + options.release.set(21) +} + repositories { maven("https://repo.papermc.io/repository/maven-public/") } From e86166cbff990a440cef3d29854b5ea3df92e3b3 Mon Sep 17 00:00:00 2001 From: david Date: Sat, 27 Jun 2026 14:54:03 +0200 Subject: [PATCH 2/3] Update 26.1 neoforge version to neoforge 26.2 dependency --- neoforge/build.gradle.kts | 4 ++++ neoforge/versions/26.1/build.gradle.kts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 5555a288..5af996fc 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -14,6 +14,10 @@ configurations.compileClasspath { attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25) } +configurations.runtimeClasspath { + attributes.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25) +} + allprojects { if (project.name == "example-mod") return@allprojects apply { plugin("maven-publish") } diff --git a/neoforge/versions/26.1/build.gradle.kts b/neoforge/versions/26.1/build.gradle.kts index 01feed0d..07115b09 100644 --- a/neoforge/versions/26.1/build.gradle.kts +++ b/neoforge/versions/26.1/build.gradle.kts @@ -12,7 +12,7 @@ tasks.compileJava { } neoForge { - version = "26.1.2.76" + version = "26.2.0.7-beta" } configurations.configureEach { From 0a3db5d6ce1ded54f8f35895bf0db9eccc45ac95 Mon Sep 17 00:00:00 2001 From: david Date: Sun, 28 Jun 2026 20:58:51 +0200 Subject: [PATCH 3/3] Add more version support --- README.md | 2 +- build.gradle.kts | 4 +- fabric/example-mod/build.gradle.kts | 6 +- fabric/versions/1.21.11/build.gradle.kts | 28 ++++++++++ .../v1_21_11/CompatibilityLayerImpl.java | 46 +++++++++++++++ .../1.21.11/src/main/java/module-info.java | 11 ++++ ...faststats.fabric.compat.CompatibilityLayer | 1 + fabric/versions/26.1-26.3/build.gradle.kts | 30 ++++++++++ .../compat/v26_1/CompatibilityLayerImpl.java} | 2 +- .../src/main/java/module-info.java | 3 +- ...faststats.fabric.compat.CompatibilityLayer | 1 + fabric/versions/26.1/build.gradle.kts | 21 ------- ...faststats.fabric.compat.CompatibilityLayer | 1 - neoforge/build.gradle.kts | 2 +- neoforge/example-mod/build.gradle.kts | 4 +- .../faststats/neoforge/NeoForgeContext.java | 11 ++-- .../neoforge/compat/CompatibilityLayer.java | 6 ++ neoforge/src/main/java/module-info.java | 1 + .../versions/1.20.6-1.21.8/build.gradle.kts | 36 ++++++++++++ .../v1_20_6/CompatibilityLayerImpl.java | 56 +++++++++++++++++++ .../src/main/java/module-info.java | 12 ++++ ...ststats.neoforge.compat.CompatibilityLayer | 1 + .../versions/1.21.9-1.21.11/build.gradle.kts | 29 ++++++++++ .../v1_21_9/CompatibilityLayerImpl.java | 56 +++++++++++++++++++ .../src/main/java/module-info.java | 12 ++++ ...ststats.neoforge.compat.CompatibilityLayer | 1 + .../{26.1 => 26.1-26.2}/build.gradle.kts | 5 +- .../compat/v26_1/CompatibilityLayerImpl.java} | 11 +++- .../src/main/java/module-info.java | 4 +- ...ststats.neoforge.compat.CompatibilityLayer | 1 + ...ststats.neoforge.compat.CompatibilityLayer | 1 - settings.gradle.kts | 8 ++- 32 files changed, 368 insertions(+), 45 deletions(-) create mode 100644 fabric/versions/1.21.11/build.gradle.kts create mode 100644 fabric/versions/1.21.11/src/main/java/dev/faststats/fabric/compat/v1_21_11/CompatibilityLayerImpl.java create mode 100644 fabric/versions/1.21.11/src/main/java/module-info.java create mode 100644 fabric/versions/1.21.11/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer create mode 100644 fabric/versions/26.1-26.3/build.gradle.kts rename fabric/versions/{26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java => 26.1-26.3/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayerImpl.java} (94%) rename fabric/versions/{26.1 => 26.1-26.3}/src/main/java/module-info.java (72%) create mode 100644 fabric/versions/26.1-26.3/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer delete mode 100644 fabric/versions/26.1/build.gradle.kts delete mode 100644 fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer create mode 100644 neoforge/versions/1.20.6-1.21.8/build.gradle.kts create mode 100644 neoforge/versions/1.20.6-1.21.8/src/main/java/dev/faststats/neoforge/compat/v1_20_6/CompatibilityLayerImpl.java create mode 100644 neoforge/versions/1.20.6-1.21.8/src/main/java/module-info.java create mode 100644 neoforge/versions/1.20.6-1.21.8/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer create mode 100644 neoforge/versions/1.21.9-1.21.11/build.gradle.kts create mode 100644 neoforge/versions/1.21.9-1.21.11/src/main/java/dev/faststats/neoforge/compat/v1_21_9/CompatibilityLayerImpl.java create mode 100644 neoforge/versions/1.21.9-1.21.11/src/main/java/module-info.java create mode 100644 neoforge/versions/1.21.9-1.21.11/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer rename neoforge/versions/{26.1 => 26.1-26.2}/build.gradle.kts (76%) rename neoforge/versions/{26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java => 26.1-26.2/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayerImpl.java} (80%) rename neoforge/versions/{26.1 => 26.1-26.2}/src/main/java/module-info.java (66%) create mode 100644 neoforge/versions/26.1-26.2/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer delete mode 100644 neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer diff --git a/README.md b/README.md index 8e8d9d22..27791475 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Use `build` for the reusable FastStats libraries: ./gradlew :config:build ./gradlew :bukkit:build ./gradlew :bungeecord:build -./gradlew :fabric:versions:26.1:build +./gradlew :fabric:versions:26.1-26.3:build ./gradlew :hytale:build ./gradlew :minestom:build ./gradlew :neoforge:versions:26.1:build diff --git a/build.gradle.kts b/build.gradle.kts index cbf25768..ca1fb050 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -129,11 +129,11 @@ subprojects { tasks.register("checkPlatformCompat") { group = "verification" description = "Compiles all platform compatibility modules." - dependsOn(":fabric:versions:26.1:compileJava", ":neoforge:versions:26.1:compileJava") + dependsOn(":fabric:versions:26.1-26.3:compileJava", ":neoforge:versions:26.1:compileJava") } tasks.register("publishPlatformCompat") { group = "publishing" description = "Publishes all platform compatibility modules." - dependsOn(":fabric:versions:26.1:publish", ":neoforge:versions:26.1:publish") + dependsOn(":fabric:versions:26.1-26.3:publish", ":neoforge:versions:26.1:publish") } diff --git a/fabric/example-mod/build.gradle.kts b/fabric/example-mod/build.gradle.kts index 0187763e..a75c01d5 100644 --- a/fabric/example-mod/build.gradle.kts +++ b/fabric/example-mod/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("net.fabricmc.fabric-loom") + id("net.fabricmc.fabric-loom") version "1.15-SNAPSHOT" kotlin("jvm") } @@ -10,7 +10,7 @@ tasks.compileJava { } dependencies { - implementation(project(":fabric:versions:26.1")) + implementation(project(":fabric:versions:26.1-26.3")) minecraft("com.mojang:minecraft:26.1.2") implementation("net.fabricmc.fabric-api:fabric-api:0.150.0+26.1.2") compileOnly("net.fabricmc:fabric-loader:0.19.3") @@ -21,5 +21,5 @@ tasks.jar { from(project(":config").sourceSets["main"].output) from(project(":core").sourceSets["main"].output) from(project(":fabric").sourceSets["main"].output) - from(project(":fabric:versions:26.1").sourceSets["main"].output) + from(project(":fabric:versions:26.1-26.3").sourceSets["main"].output) } diff --git a/fabric/versions/1.21.11/build.gradle.kts b/fabric/versions/1.21.11/build.gradle.kts new file mode 100644 index 00000000..a498b0bd --- /dev/null +++ b/fabric/versions/1.21.11/build.gradle.kts @@ -0,0 +1,28 @@ +extra.set("moduleName", "dev.faststats.fabric.compat.v1_21_11") +// todo: validate supported version range +extra.set("publishVersionSuffix", "mc1.21.11") + +plugins { + id("net.fabricmc.fabric-loom-remap") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + +dependencies { + api(project(":fabric")) + api(project(":core")) + implementation(project(":config")) + + // minecraft("com.mojang:minecraft:1.21.10") + minecraft("com.mojang:minecraft:1.21.11") + mappings(loom.officialMojangMappings()) + + // compileOnly("net.fabricmc.fabric-api:fabric-api:0.138.4+1.21.10") // 1.21.10 + compileOnly("net.fabricmc.fabric-api:fabric-api:0.141.4+1.21.11") // 1.21.11 + + compileOnly("net.fabricmc:fabric-loader:0.19.3") +} diff --git a/fabric/versions/1.21.11/src/main/java/dev/faststats/fabric/compat/v1_21_11/CompatibilityLayerImpl.java b/fabric/versions/1.21.11/src/main/java/dev/faststats/fabric/compat/v1_21_11/CompatibilityLayerImpl.java new file mode 100644 index 00000000..202329f2 --- /dev/null +++ b/fabric/versions/1.21.11/src/main/java/dev/faststats/fabric/compat/v1_21_11/CompatibilityLayerImpl.java @@ -0,0 +1,46 @@ +package dev.faststats.fabric.compat.v1_21_11; + +import dev.faststats.fabric.compat.CompatibilityLayer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.minecraft.client.Minecraft; +import net.minecraft.server.MinecraftServer; +import org.jspecify.annotations.Nullable; + +public final class CompatibilityLayerImpl implements CompatibilityLayer { + private @Nullable MinecraftServer server; + + @Override + public void initServer() { + ServerLifecycleEvents.SERVER_STARTING.register(server -> this.server = server); + } + + @Override + public boolean clientOnlineMode() { + final var client = Minecraft.getInstance(); + return client.getUser().getXuid().isPresent() && !client.isOfflineDeveloperMode(); + } + + @Override + public int clientPlayerCount() { + final var client = Minecraft.getInstance(); + final var connection = client.getConnection(); + if (connection != null) return connection.getOnlinePlayers().size(); + + final var server = client.getSingleplayerServer(); + if (server != null) return server.getPlayerCount(); + + return client.player == null ? 0 : 1; + } + + @Override + public boolean serverOnlineMode() { + assert server != null : "Server not initialized"; + return server.usesAuthentication(); + } + + @Override + public int serverPlayerCount() { + assert server != null : "Server not initialized"; + return server.getPlayerCount(); + } +} diff --git a/fabric/versions/1.21.11/src/main/java/module-info.java b/fabric/versions/1.21.11/src/main/java/module-info.java new file mode 100644 index 00000000..12aac481 --- /dev/null +++ b/fabric/versions/1.21.11/src/main/java/module-info.java @@ -0,0 +1,11 @@ +import dev.faststats.fabric.compat.v1_21_11.CompatibilityLayerImpl; +import org.jspecify.annotations.NullMarked; + +@NullMarked +module dev.faststats.fabric.compat.v1_21_11 { + requires dev.faststats.fabric; + + requires static org.jspecify; + + provides dev.faststats.fabric.compat.CompatibilityLayer with CompatibilityLayerImpl; +} diff --git a/fabric/versions/1.21.11/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer b/fabric/versions/1.21.11/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer new file mode 100644 index 00000000..34e58bd9 --- /dev/null +++ b/fabric/versions/1.21.11/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.fabric.compat.v1_21_11.CompatibilityLayerImpl diff --git a/fabric/versions/26.1-26.3/build.gradle.kts b/fabric/versions/26.1-26.3/build.gradle.kts new file mode 100644 index 00000000..0d84d62e --- /dev/null +++ b/fabric/versions/26.1-26.3/build.gradle.kts @@ -0,0 +1,30 @@ +extra.set("moduleName", "dev.faststats.fabric.compat.v26_1") +extra.set("publishVersionSuffix", "mc26.1-26.3") + +plugins { + id("net.fabricmc.fabric-loom") version "1.15-SNAPSHOT" +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + +dependencies { + api(project(":fabric")) + api(project(":core")) + implementation(project(":config")) + + // minecraft("com.mojang:minecraft:26.1") + // minecraft("com.mojang:minecraft:26.1.1") + // minecraft("com.mojang:minecraft:26.1.2") + // minecraft("com.mojang:minecraft:26.2") + minecraft("com.mojang:minecraft:26.3-snapshot-1") + + // compileOnly("net.fabricmc.fabric-api:fabric-api:0.153.0+26.1.2") // 26.1-26.1.2 + // compileOnly("net.fabricmc.fabric-api:fabric-api:0.153.0+26.2") // 26.2 + compileOnly("net.fabricmc.fabric-api:fabric-api:0.153.1+26.3") // 26.3 + + compileOnly("net.fabricmc:fabric-loader:0.19.3") +} diff --git a/fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java b/fabric/versions/26.1-26.3/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayerImpl.java similarity index 94% rename from fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java rename to fabric/versions/26.1-26.3/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayerImpl.java index 8107efa7..19d6036a 100644 --- a/fabric/versions/26.1/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayer_v26_1.java +++ b/fabric/versions/26.1-26.3/src/main/java/dev/faststats/fabric/compat/v26_1/CompatibilityLayerImpl.java @@ -6,7 +6,7 @@ import net.minecraft.server.MinecraftServer; import org.jspecify.annotations.Nullable; -public final class CompatibilityLayer_v26_1 implements CompatibilityLayer { +public final class CompatibilityLayerImpl implements CompatibilityLayer { private @Nullable MinecraftServer server; @Override diff --git a/fabric/versions/26.1/src/main/java/module-info.java b/fabric/versions/26.1-26.3/src/main/java/module-info.java similarity index 72% rename from fabric/versions/26.1/src/main/java/module-info.java rename to fabric/versions/26.1-26.3/src/main/java/module-info.java index 21a215b8..4336e589 100644 --- a/fabric/versions/26.1/src/main/java/module-info.java +++ b/fabric/versions/26.1-26.3/src/main/java/module-info.java @@ -1,3 +1,4 @@ +import dev.faststats.fabric.compat.v26_1.CompatibilityLayerImpl; import org.jspecify.annotations.NullMarked; @NullMarked @@ -6,5 +7,5 @@ requires static org.jspecify; - provides dev.faststats.fabric.compat.CompatibilityLayer with dev.faststats.fabric.compat.v26_1.CompatibilityLayer_v26_1; + provides dev.faststats.fabric.compat.CompatibilityLayer with CompatibilityLayerImpl; } diff --git a/fabric/versions/26.1-26.3/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer b/fabric/versions/26.1-26.3/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer new file mode 100644 index 00000000..fe00e330 --- /dev/null +++ b/fabric/versions/26.1-26.3/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.fabric.compat.v26_1.CompatibilityLayerImpl diff --git a/fabric/versions/26.1/build.gradle.kts b/fabric/versions/26.1/build.gradle.kts deleted file mode 100644 index 0dc09d8f..00000000 --- a/fabric/versions/26.1/build.gradle.kts +++ /dev/null @@ -1,21 +0,0 @@ -extra.set("moduleName", "dev.faststats.fabric.compat.v26_1") -extra.set("publishVersionSuffix", "mc26.1-26.2") - -plugins { - id("net.fabricmc.fabric-loom") -} - -java.toolchain.languageVersion = JavaLanguageVersion.of(25) - -tasks.compileJava { - options.release.set(25) -} - -dependencies { - api(project(":fabric")) - api(project(":core")) - implementation(project(":config")) - minecraft("com.mojang:minecraft:26.1.2") - compileOnly("net.fabricmc.fabric-api:fabric-api:0.150.0+26.1.2") - compileOnly("net.fabricmc:fabric-loader:0.19.3") -} diff --git a/fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer b/fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer deleted file mode 100644 index 6345d674..00000000 --- a/fabric/versions/26.1/src/main/resources/META-INF/services/dev.faststats.fabric.compat.CompatibilityLayer +++ /dev/null @@ -1 +0,0 @@ -dev.faststats.fabric.compat.v26_1.CompatibilityLayer_v26_1 diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 5af996fc..40b2caec 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -26,7 +26,7 @@ allprojects { } neoForge { - version = "26.1.2.76" + version = "21.8.53" // lowest bound, 1.20.6 } configurations.configureEach { diff --git a/neoforge/example-mod/build.gradle.kts b/neoforge/example-mod/build.gradle.kts index 40d9bcf0..653dcaee 100644 --- a/neoforge/example-mod/build.gradle.kts +++ b/neoforge/example-mod/build.gradle.kts @@ -12,7 +12,7 @@ configurations.configureEach { } dependencies { - implementation(project(":neoforge:versions:26.1")) + implementation(project(":neoforge:versions:26.1-26.2")) } tasks.jar { @@ -20,5 +20,5 @@ tasks.jar { from(project(":config").sourceSets["main"].output) from(project(":core").sourceSets["main"].output) from(project(":neoforge").sourceSets["main"].output) - from(project(":neoforge:versions:26.1").sourceSets["main"].output) + from(project(":neoforge:versions:26.1-26.2").sourceSets["main"].output) } diff --git a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java index ec3c6bc0..bd88b98c 100644 --- a/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java +++ b/neoforge/src/main/java/dev/faststats/neoforge/NeoForgeContext.java @@ -10,7 +10,6 @@ import dev.faststats.neoforge.compat.CompatibilityLayer; import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModList; -import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.fml.loading.FMLPaths; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.server.ServerStartedEvent; @@ -18,8 +17,8 @@ import net.neoforged.neoforgespi.language.IModInfo; import org.jetbrains.annotations.Contract; -import java.util.Set; import java.util.ServiceLoader; +import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -52,9 +51,9 @@ private NeoForgeContext(final Factory factory, final LoggerFactory loggerFactory .findFirst() .orElseThrow(() -> new IllegalStateException("No NeoForge compatibility layer found")); initializeServices(factory); - switch (FMLEnvironment.getDist()) { + switch (compatibilityLayer.getEnvironment()) { case CLIENT -> ready(); - case DEDICATED_SERVER -> { + case SERVER -> { NeoForge.EVENT_BUS.addListener((final ServerStartedEvent event) -> ready()); NeoForge.EVENT_BUS.addListener((final ServerStoppingEvent event) -> shutdown()); } @@ -67,9 +66,9 @@ protected Metrics.Factory metricsFactory() { return new SimpleMetrics.Factory(this) { @Override public Metrics create() throws IllegalStateException { - return switch (FMLEnvironment.getDist()) { + return switch (compatibilityLayer.getEnvironment()) { case CLIENT -> new NeoForgeMetricsClient(this, mod, compatibilityLayer); - case DEDICATED_SERVER -> new NeoForgeMetricsServer(this, mod, compatibilityLayer); + case SERVER -> new NeoForgeMetricsServer(this, mod, compatibilityLayer); }; } }; diff --git a/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java b/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java index 553ec0cb..454bdca4 100644 --- a/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java +++ b/neoforge/src/main/java/dev/faststats/neoforge/compat/CompatibilityLayer.java @@ -13,4 +13,10 @@ public interface CompatibilityLayer { boolean serverOnlineMode(); int serverPlayerCount(); + + Environment getEnvironment(); + + enum Environment { + CLIENT, SERVER + } } diff --git a/neoforge/src/main/java/module-info.java b/neoforge/src/main/java/module-info.java index 13f8a99b..cc654700 100644 --- a/neoforge/src/main/java/module-info.java +++ b/neoforge/src/main/java/module-info.java @@ -14,6 +14,7 @@ requires static org.jetbrains.annotations; requires static org.jspecify; + requires java.net.http; uses dev.faststats.neoforge.compat.CompatibilityLayer; } diff --git a/neoforge/versions/1.20.6-1.21.8/build.gradle.kts b/neoforge/versions/1.20.6-1.21.8/build.gradle.kts new file mode 100644 index 00000000..14ba7f9d --- /dev/null +++ b/neoforge/versions/1.20.6-1.21.8/build.gradle.kts @@ -0,0 +1,36 @@ +extra.set("moduleName", "dev.faststats.neoforge.compat.v1_20_6") +extra.set("publishVersionSuffix", "mc1.21-1.21.11") + +plugins { + id("net.neoforged.moddev") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + +neoForge { + // version = "20.6.139" // 1.20.6 + // version = "21.0.167" // 1.21 + // version = "21.1.234" // 1.21.1 + // version = "21.2.1-beta" // 1.21.2 + // version = "21.3.96" // 1.21.3 + // version = "21.4.157" // 1.21.4 + // version = "21.5.97" // 1.21.5 + // version = "21.6.20-beta" // 1.21.6 + // version = "21.7.25-beta" // 1.21.7 + version = "21.8.53" // 1.21.8 +} + +configurations.configureEach { + resolutionStrategy.force("com.google.code.gson:gson:2.14.0") +} + +dependencies { + api(project(":neoforge")) + api(project(":core")) + implementation(project(":config")) + compileOnly("net.neoforged:bus:8.0.5") +} diff --git a/neoforge/versions/1.20.6-1.21.8/src/main/java/dev/faststats/neoforge/compat/v1_20_6/CompatibilityLayerImpl.java b/neoforge/versions/1.20.6-1.21.8/src/main/java/dev/faststats/neoforge/compat/v1_20_6/CompatibilityLayerImpl.java new file mode 100644 index 00000000..076936dd --- /dev/null +++ b/neoforge/versions/1.20.6-1.21.8/src/main/java/dev/faststats/neoforge/compat/v1_20_6/CompatibilityLayerImpl.java @@ -0,0 +1,56 @@ +package dev.faststats.neoforge.compat.v1_20_6; + +import dev.faststats.neoforge.compat.CompatibilityLayer; +import net.minecraft.client.Minecraft; +import net.minecraft.server.MinecraftServer; +import net.neoforged.fml.loading.FMLLoader; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import org.jspecify.annotations.Nullable; + +public final class CompatibilityLayerImpl implements CompatibilityLayer { + private @Nullable MinecraftServer server; + + @Override + public void initServer() { + NeoForge.EVENT_BUS.addListener((final ServerStartedEvent event) -> this.server = event.getServer()); + } + + @Override + public boolean clientOnlineMode() { + final var client = Minecraft.getInstance(); + return client.getUser().getXuid().isPresent(); // todo: offline dev mode? + } + + @Override + public int clientPlayerCount() { + final var client = Minecraft.getInstance(); + final var connection = client.getConnection(); + if (connection != null) return connection.getOnlinePlayers().size(); + + final var server = client.getSingleplayerServer(); + if (server != null) return server.getPlayerCount(); + + return client.player == null ? 0 : 1; + } + + @Override + public boolean serverOnlineMode() { + assert server != null : "Server not initialized"; + return server.usesAuthentication(); + } + + @Override + public int serverPlayerCount() { + assert server != null : "Server not initialized"; + return server.getPlayerCount(); + } + + @Override + public Environment getEnvironment() { + return switch (FMLLoader.getDist()) { + case CLIENT -> Environment.CLIENT; + case DEDICATED_SERVER -> Environment.SERVER; + }; + } +} diff --git a/neoforge/versions/1.20.6-1.21.8/src/main/java/module-info.java b/neoforge/versions/1.20.6-1.21.8/src/main/java/module-info.java new file mode 100644 index 00000000..a3de003d --- /dev/null +++ b/neoforge/versions/1.20.6-1.21.8/src/main/java/module-info.java @@ -0,0 +1,12 @@ +import dev.faststats.neoforge.compat.v1_20_6.CompatibilityLayerImpl; +import org.jspecify.annotations.NullMarked; + +@NullMarked +module dev.faststats.neoforge.compat.v1_20_6 { + requires dev.faststats.neoforge; + + requires static org.jspecify; + requires fml_loader; + + provides dev.faststats.neoforge.compat.CompatibilityLayer with CompatibilityLayerImpl; +} diff --git a/neoforge/versions/1.20.6-1.21.8/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer b/neoforge/versions/1.20.6-1.21.8/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer new file mode 100644 index 00000000..2d58bba0 --- /dev/null +++ b/neoforge/versions/1.20.6-1.21.8/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.neoforge.compat.v1_20_6.CompatibilityLayerImpl diff --git a/neoforge/versions/1.21.9-1.21.11/build.gradle.kts b/neoforge/versions/1.21.9-1.21.11/build.gradle.kts new file mode 100644 index 00000000..f3008f6c --- /dev/null +++ b/neoforge/versions/1.21.9-1.21.11/build.gradle.kts @@ -0,0 +1,29 @@ +extra.set("moduleName", "dev.faststats.neoforge.compat.v1_21_9") +extra.set("publishVersionSuffix", "mc1.21.9-1.21.11") + +plugins { + id("net.neoforged.moddev") +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(25) + +tasks.compileJava { + options.release.set(25) +} + +neoForge { + // version = "21.9.16-beta" // 1.21.9 + // version = "21.10.64" // 1.21.10 + version = "21.11.42" // 1.21.11 +} + +configurations.configureEach { + resolutionStrategy.force("com.google.code.gson:gson:2.14.0") +} + +dependencies { + api(project(":neoforge")) + api(project(":core")) + implementation(project(":config")) + compileOnly("net.neoforged:bus:8.0.5") +} diff --git a/neoforge/versions/1.21.9-1.21.11/src/main/java/dev/faststats/neoforge/compat/v1_21_9/CompatibilityLayerImpl.java b/neoforge/versions/1.21.9-1.21.11/src/main/java/dev/faststats/neoforge/compat/v1_21_9/CompatibilityLayerImpl.java new file mode 100644 index 00000000..a4dafa07 --- /dev/null +++ b/neoforge/versions/1.21.9-1.21.11/src/main/java/dev/faststats/neoforge/compat/v1_21_9/CompatibilityLayerImpl.java @@ -0,0 +1,56 @@ +package dev.faststats.neoforge.compat.v1_21_9; + +import dev.faststats.neoforge.compat.CompatibilityLayer; +import net.minecraft.client.Minecraft; +import net.minecraft.server.MinecraftServer; +import net.neoforged.fml.loading.FMLEnvironment; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import org.jspecify.annotations.Nullable; + +public final class CompatibilityLayerImpl implements CompatibilityLayer { + private @Nullable MinecraftServer server; + + @Override + public void initServer() { + NeoForge.EVENT_BUS.addListener((final ServerStartedEvent event) -> this.server = event.getServer()); + } + + @Override + public boolean clientOnlineMode() { + final var client = Minecraft.getInstance(); + return client.getUser().getXuid().isPresent() && !client.isOfflineDeveloperMode(); + } + + @Override + public int clientPlayerCount() { + final var client = Minecraft.getInstance(); + final var connection = client.getConnection(); + if (connection != null) return connection.getOnlinePlayers().size(); + + final var server = client.getSingleplayerServer(); + if (server != null) return server.getPlayerCount(); + + return client.player == null ? 0 : 1; + } + + @Override + public boolean serverOnlineMode() { + assert server != null : "Server not initialized"; + return server.usesAuthentication(); + } + + @Override + public int serverPlayerCount() { + assert server != null : "Server not initialized"; + return server.getPlayerCount(); + } + + @Override + public Environment getEnvironment() { + return switch (FMLEnvironment.getDist()) { + case CLIENT -> Environment.CLIENT; + case DEDICATED_SERVER -> Environment.SERVER; + }; + } +} diff --git a/neoforge/versions/1.21.9-1.21.11/src/main/java/module-info.java b/neoforge/versions/1.21.9-1.21.11/src/main/java/module-info.java new file mode 100644 index 00000000..9dc3d86d --- /dev/null +++ b/neoforge/versions/1.21.9-1.21.11/src/main/java/module-info.java @@ -0,0 +1,12 @@ +import dev.faststats.neoforge.compat.v1_21_9.CompatibilityLayerImpl; +import org.jspecify.annotations.NullMarked; + +@NullMarked +module dev.faststats.neoforge.compat.v1_21_9 { + requires dev.faststats.neoforge; + + requires static org.jspecify; + requires fml_loader; + + provides dev.faststats.neoforge.compat.CompatibilityLayer with CompatibilityLayerImpl; +} diff --git a/neoforge/versions/1.21.9-1.21.11/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer b/neoforge/versions/1.21.9-1.21.11/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer new file mode 100644 index 00000000..b18986d3 --- /dev/null +++ b/neoforge/versions/1.21.9-1.21.11/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.neoforge.compat.v1_21_9.CompatibilityLayerImpl diff --git a/neoforge/versions/26.1/build.gradle.kts b/neoforge/versions/26.1-26.2/build.gradle.kts similarity index 76% rename from neoforge/versions/26.1/build.gradle.kts rename to neoforge/versions/26.1-26.2/build.gradle.kts index 07115b09..99c764b6 100644 --- a/neoforge/versions/26.1/build.gradle.kts +++ b/neoforge/versions/26.1-26.2/build.gradle.kts @@ -12,7 +12,10 @@ tasks.compileJava { } neoForge { - version = "26.2.0.7-beta" + // version = "26.1.0.19-beta" // 26.1 + // version = "26.1.1.15-beta" // 26.1.1 + // version = "26.1.2.76" // 26.1.2 + version = "26.2.0.7-beta" // 26.2 } configurations.configureEach { diff --git a/neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java b/neoforge/versions/26.1-26.2/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayerImpl.java similarity index 80% rename from neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java rename to neoforge/versions/26.1-26.2/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayerImpl.java index 22a3999f..4e54185d 100644 --- a/neoforge/versions/26.1/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayer_v26_1.java +++ b/neoforge/versions/26.1-26.2/src/main/java/dev/faststats/neoforge/compat/v26_1/CompatibilityLayerImpl.java @@ -3,11 +3,12 @@ import dev.faststats.neoforge.compat.CompatibilityLayer; import net.minecraft.client.Minecraft; import net.minecraft.server.MinecraftServer; +import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.server.ServerStartedEvent; import org.jspecify.annotations.Nullable; -public final class CompatibilityLayer_v26_1 implements CompatibilityLayer { +public final class CompatibilityLayerImpl implements CompatibilityLayer { private @Nullable MinecraftServer server; @Override @@ -44,4 +45,12 @@ public int serverPlayerCount() { assert server != null : "Server not initialized"; return server.getPlayerCount(); } + + @Override + public Environment getEnvironment() { + return switch (FMLEnvironment.getDist()) { + case CLIENT -> Environment.CLIENT; + case DEDICATED_SERVER -> Environment.SERVER; + }; + } } diff --git a/neoforge/versions/26.1/src/main/java/module-info.java b/neoforge/versions/26.1-26.2/src/main/java/module-info.java similarity index 66% rename from neoforge/versions/26.1/src/main/java/module-info.java rename to neoforge/versions/26.1-26.2/src/main/java/module-info.java index d38b79d4..cf64ccb7 100644 --- a/neoforge/versions/26.1/src/main/java/module-info.java +++ b/neoforge/versions/26.1-26.2/src/main/java/module-info.java @@ -1,3 +1,4 @@ +import dev.faststats.neoforge.compat.v26_1.CompatibilityLayerImpl; import org.jspecify.annotations.NullMarked; @NullMarked @@ -5,6 +6,7 @@ requires dev.faststats.neoforge; requires static org.jspecify; + requires fml_loader; - provides dev.faststats.neoforge.compat.CompatibilityLayer with dev.faststats.neoforge.compat.v26_1.CompatibilityLayer_v26_1; + provides dev.faststats.neoforge.compat.CompatibilityLayer with CompatibilityLayerImpl; } diff --git a/neoforge/versions/26.1-26.2/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer b/neoforge/versions/26.1-26.2/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer new file mode 100644 index 00000000..3f4c817a --- /dev/null +++ b/neoforge/versions/26.1-26.2/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer @@ -0,0 +1 @@ +dev.faststats.neoforge.compat.v26_1.CompatibilityLayer_v21_11 diff --git a/neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer b/neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer deleted file mode 100644 index f9488860..00000000 --- a/neoforge/versions/26.1/src/main/resources/META-INF/services/dev.faststats.neoforge.compat.CompatibilityLayer +++ /dev/null @@ -1 +0,0 @@ -dev.faststats.neoforge.compat.v26_1.CompatibilityLayer_v26_1 diff --git a/settings.gradle.kts b/settings.gradle.kts index bc560836..44310b23 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,14 +18,18 @@ include("core") include("core:example") include("fabric") include("fabric:example-mod") -include("fabric:versions:26.1") +include("fabric:versions:26.1-26.3") +include("fabric:versions:1.21.11") include("hytale") include("hytale:example-plugin") include("minestom") include("minestom:example-server") include("neoforge") include("neoforge:example-mod") -include("neoforge:versions:26.1") +// todo: automate version modules? +include("neoforge:versions:1.20.6-1.21.8") +include("neoforge:versions:1.21.9-1.21.11") +include("neoforge:versions:26.1-26.2") include("nukkit") include("nukkit:example-plugin") include("sponge")