From addc4f4cee7ae2e1bc0ed754e2ba950b70ec688d Mon Sep 17 00:00:00 2001 From: String Date: Thu, 22 Jan 2026 04:14:35 -0600 Subject: [PATCH 1/5] Add modding SDK task for future autocomplete with mod development --- .gitignore | 2 +- build.gradle | 1 - core/build.gradle | 24 +++++++++++-- lwjgl3/build.gradle | 84 ++++++++++++++++++++++----------------------- 4 files changed, 65 insertions(+), 46 deletions(-) diff --git a/.gitignore b/.gitignore index 159c8cd..54ac2f5 100644 --- a/.gitignore +++ b/.gitignore @@ -155,8 +155,8 @@ Thumbs.db *~ *.*# *#*# -/.kotlin/ /assets/assets.txt +/assets/sdk/ ## Special cases: diff --git a/build.gradle b/build.gradle index 199446c..a90df70 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,6 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:8.7.3" - } } diff --git a/core/build.gradle b/core/build.gradle index c0c016b..ecb889e 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -11,10 +11,30 @@ dependencies { api "games.rednblack.miniaudio:miniaudio:$miniaudioVersion" // FNF:JE. - implementation "org.apache.groovy:groovy:4.0.12" - implementation "org.jetbrains:annotations:15.0" + implementation "org.apache.groovy:groovy:5.0.3" + implementation "org.jetbrains:annotations:26.0.2-1" if(enableGraalNative == 'true') { implementation "io.github.berstanio:gdx-svmhelper-annotations:$graalHelperVersion" } } + +tasks.register('exportModSDK', Copy) { + group = "modding" + description = "Copies all JARs needed for modding into the assets folder." + + into "$rootProject.projectDir/assets/sdk/libs" + + from(tasks.named('jar')) { + rename { "game-api.jar" } + } + + // Include every external dependency. + from(configurations.runtimeClasspath) { + // Exclude native files, since modders only need the Java interfaces. + exclude "**/*.dll", "**/*.so", "**/*.dylib", "**/*.jnilib" + } +} + +// Make sure the assets are ready before the game runs. +classes.dependsOn exportModSDK diff --git a/lwjgl3/build.gradle b/lwjgl3/build.gradle index 9e4435f..027d290 100644 --- a/lwjgl3/build.gradle +++ b/lwjgl3/build.gradle @@ -4,7 +4,7 @@ buildscript { } dependencies { classpath "io.github.fourlastor:construo:1.7.1" - if(enableGraalNative == 'true') { + if (enableGraalNative == 'true') { classpath "org.graalvm.buildtools.native:org.graalvm.buildtools.native.gradle.plugin:0.9.28" } } @@ -17,14 +17,14 @@ apply plugin: 'io.github.fourlastor.construo' import io.github.fourlastor.construo.Target -sourceSets.main.resources.srcDirs += [ rootProject.file('assets').path ] +sourceSets.main.resources.srcDirs += [rootProject.file('assets').path] mainClassName = 'me.stringfromjava.funkin.lwjgl3.Lwjgl3Launcher' application.setMainClass(mainClassName) eclipse.project.name = appName + '-lwjgl3' java.sourceCompatibility = 17 java.targetCompatibility = 17 if (JavaVersion.current().isJava9Compatible()) { - compileJava.options.release.set(17) + compileJava.options.release.set(17) } dependencies { @@ -34,7 +34,7 @@ dependencies { implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" implementation project(':core') - if(enableGraalNative == 'true') { + if (enableGraalNative == 'true') { implementation "io.github.berstanio:gdx-svmhelper-backend-lwjgl3:$graalHelperVersion" } } @@ -114,44 +114,44 @@ tasks.register("jarWin") { } construo { - // name of the executable - name.set(appName) - // human-readable name, used for example in the `.app` name for macOS - humanName.set(appName) - // Optional, defaults to project version property - version.set("$projectVersion") - - targets.configure { - register("linuxX64", Target.Linux) { - architecture.set(Target.Architecture.X86_64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_linux_hotspot_17.0.15_6.tar.gz") - // Linux does not currently have a way to set the icon on the executable - } - register("macM1", Target.MacOs) { - architecture.set(Target.Architecture.AARCH64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.tar.gz") - // macOS needs an identifier - identifier.set("me.stringfromjava.funkin." + appName) - // Optional: icon for macOS, as an ICNS file - macIcon.set(project.file("icons/logo.icns")) - } - register("macX64", Target.MacOs) { - architecture.set(Target.Architecture.X86_64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_mac_hotspot_17.0.15_6.tar.gz") - // macOS needs an identifier - identifier.set("me.stringfromjava.funkin." + appName) - // Optional: icon for macOS, as an ICNS file - macIcon.set(project.file("icons/logo.icns")) - } - register("winX64", Target.Windows) { - architecture.set(Target.Architecture.X86_64) - // Optional: icon for Windows, as a PNG - icon.set(project.file("icons/logo.png")) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_windows_hotspot_17.0.15_6.zip") - // Uncomment the next line to show a console when the game runs, to print messages. - //useConsole.set(true) - } + // name of the executable + name.set(appName) + // human-readable name, used for example in the `.app` name for macOS + humanName.set(appName) + // Optional, defaults to project version property + version.set("$projectVersion") + + targets.configure { + register("linuxX64", Target.Linux) { + architecture.set(Target.Architecture.X86_64) + jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_linux_hotspot_17.0.15_6.tar.gz") + // Linux does not currently have a way to set the icon on the executable } + register("macM1", Target.MacOs) { + architecture.set(Target.Architecture.AARCH64) + jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.tar.gz") + // macOS needs an identifier + identifier.set("me.stringfromjava.funkin." + appName) + // Optional: icon for macOS, as an ICNS file + macIcon.set(project.file("icons/logo.icns")) + } + register("macX64", Target.MacOs) { + architecture.set(Target.Architecture.X86_64) + jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_mac_hotspot_17.0.15_6.tar.gz") + // macOS needs an identifier + identifier.set("me.stringfromjava.funkin." + appName) + // Optional: icon for macOS, as an ICNS file + macIcon.set(project.file("icons/logo.icns")) + } + register("winX64", Target.Windows) { + architecture.set(Target.Architecture.X86_64) + // Optional: icon for Windows, as a PNG + icon.set(project.file("icons/logo.png")) + jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_windows_hotspot_17.0.15_6.zip") + // Uncomment the next line to show a console when the game runs, to print messages. + //useConsole.set(true) + } + } } // Equivalent to the jar task; here for compatibility with gdx-setup. @@ -176,6 +176,6 @@ distributions { startScripts.dependsOn(':lwjgl3:jar') startScripts.classpath = project.tasks.jar.outputs.files -if(enableGraalNative == 'true') { +if (enableGraalNative == 'true') { apply from: file("nativeimage.gradle") } From 650ba475b0418089c4f4523f365dfa0feb7e38d6 Mon Sep 17 00:00:00 2001 From: String Date: Sat, 24 Jan 2026 05:20:54 -0600 Subject: [PATCH 2/5] Update build.gradle --- core/build.gradle | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index ecb889e..c03b084 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -14,19 +14,19 @@ dependencies { implementation "org.apache.groovy:groovy:5.0.3" implementation "org.jetbrains:annotations:26.0.2-1" - if(enableGraalNative == 'true') { + if (enableGraalNative == 'true') { implementation "io.github.berstanio:gdx-svmhelper-annotations:$graalHelperVersion" } } tasks.register('exportModSDK', Copy) { group = "modding" - description = "Copies all JARs needed for modding into the assets folder." + description = "Copies all API JARs needed for modding into the assets folder." - into "$rootProject.projectDir/assets/sdk/libs" + into "$rootProject.projectDir/assets/sdk/api" from(tasks.named('jar')) { - rename { "game-api.jar" } + rename { "funkin-api.jar" } } // Include every external dependency. @@ -37,4 +37,6 @@ tasks.register('exportModSDK', Copy) { } // Make sure the assets are ready before the game runs. -classes.dependsOn exportModSDK +tasks.named('build').configure { + dependsOn exportModSDK +} From 4df18500a73437783784d3884caaa2807bdca9b0 Mon Sep 17 00:00:00 2001 From: String Date: Sat, 24 Jan 2026 05:30:50 -0600 Subject: [PATCH 3/5] Update build.gradle --- lwjgl3/build.gradle | 55 +++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/lwjgl3/build.gradle b/lwjgl3/build.gradle index 0ce60aa..50f9fb6 100644 --- a/lwjgl3/build.gradle +++ b/lwjgl3/build.gradle @@ -17,7 +17,7 @@ apply plugin: 'io.github.fourlastor.construo' import io.github.fourlastor.construo.Target -sourceSets.main.resources.srcDirs += [ rootProject.file('assets').path ] +sourceSets.main.resources.srcDirs += [rootProject.file('assets').path] mainClassName = 'me.stringdotjar.funkin.lwjgl3.Lwjgl3Launcher' application.setMainClass(mainClassName) eclipse.project.name = appName + '-lwjgl3' @@ -114,49 +114,24 @@ tasks.register("jarWin") { } construo { - // name of the executable - name.set(appName) - // human-readable name, used for example in the `.app` name for macOS - humanName.set(appName) - // Optional, defaults to project version property - version.set("$projectVersion") - - targets.configure { - register("linuxX64", Target.Linux) { - architecture.set(Target.Architecture.X86_64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_linux_hotspot_17.0.15_6.tar.gz") - // Linux does not currently have a way to set the icon on the executable - } - register("macM1", Target.MacOs) { - architecture.set(Target.Architecture.AARCH64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.tar.gz") - // macOS needs an identifier - identifier.set("me.stringdotjar.funkin." + appName) - // Optional: icon for macOS, as an ICNS file - macIcon.set(project.file("icons/logo.icns")) - } - register("macX64", Target.MacOs) { - architecture.set(Target.Architecture.X86_64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_mac_hotspot_17.0.15_6.tar.gz") - // macOS needs an identifier - identifier.set("me.stringdotjar.funkin." + appName) - // Optional: icon for macOS, as an ICNS file - macIcon.set(project.file("icons/logo.icns")) - } - register("winX64", Target.Windows) { - architecture.set(Target.Architecture.X86_64) - // Optional: icon for Windows, as a PNG - icon.set(project.file("icons/logo.png")) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_windows_hotspot_17.0.15_6.zip") - // Uncomment the next line to show a console when the game runs, to print messages. - //useConsole.set(true) - } + // name of the executable + name.set(appName) + // human-readable name, used for example in the `.app` name for macOS + humanName.set(appName) + // Optional, defaults to project version property + version.set("$projectVersion") + + targets.configure { + register("linuxX64", Target.Linux) { + architecture.set(Target.Architecture.X86_64) + jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_linux_hotspot_17.0.15_6.tar.gz") + // Linux does not currently have a way to set the icon on the executable } register("macM1", Target.MacOs) { architecture.set(Target.Architecture.AARCH64) jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.tar.gz") // macOS needs an identifier - identifier.set("me.stringfromjava.funkin." + appName) + identifier.set("me.stringdotjar.funkin." + appName) // Optional: icon for macOS, as an ICNS file macIcon.set(project.file("icons/logo.icns")) } @@ -164,7 +139,7 @@ construo { architecture.set(Target.Architecture.X86_64) jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_mac_hotspot_17.0.15_6.tar.gz") // macOS needs an identifier - identifier.set("me.stringfromjava.funkin." + appName) + identifier.set("me.stringdotjar.funkin." + appName) // Optional: icon for macOS, as an ICNS file macIcon.set(project.file("icons/logo.icns")) } From 8d46c305fa2d1acfa11f71db0ec507230d581bea Mon Sep 17 00:00:00 2001 From: String Date: Sat, 24 Jan 2026 05:37:29 -0600 Subject: [PATCH 4/5] =?UTF-8?q?Dude=20please=20work=20=F0=9F=99=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lwjgl3/build.gradle | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/lwjgl3/build.gradle b/lwjgl3/build.gradle index 50f9fb6..09b5ba1 100644 --- a/lwjgl3/build.gradle +++ b/lwjgl3/build.gradle @@ -113,47 +113,6 @@ tasks.register("jarWin") { } } -construo { - // name of the executable - name.set(appName) - // human-readable name, used for example in the `.app` name for macOS - humanName.set(appName) - // Optional, defaults to project version property - version.set("$projectVersion") - - targets.configure { - register("linuxX64", Target.Linux) { - architecture.set(Target.Architecture.X86_64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_linux_hotspot_17.0.15_6.tar.gz") - // Linux does not currently have a way to set the icon on the executable - } - register("macM1", Target.MacOs) { - architecture.set(Target.Architecture.AARCH64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.tar.gz") - // macOS needs an identifier - identifier.set("me.stringdotjar.funkin." + appName) - // Optional: icon for macOS, as an ICNS file - macIcon.set(project.file("icons/logo.icns")) - } - register("macX64", Target.MacOs) { - architecture.set(Target.Architecture.X86_64) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_mac_hotspot_17.0.15_6.tar.gz") - // macOS needs an identifier - identifier.set("me.stringdotjar.funkin." + appName) - // Optional: icon for macOS, as an ICNS file - macIcon.set(project.file("icons/logo.icns")) - } - register("winX64", Target.Windows) { - architecture.set(Target.Architecture.X86_64) - // Optional: icon for Windows, as a PNG - icon.set(project.file("icons/logo.png")) - jdkUrl.set("https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_x64_windows_hotspot_17.0.15_6.zip") - // Uncomment the next line to show a console when the game runs, to print messages. - //useConsole.set(true) - } - } -} - // Equivalent to the jar task; here for compatibility with gdx-setup. tasks.register('dist') { dependsOn 'jar' From e967e515e831ba34fb2f48e259e3482a3ce04578 Mon Sep 17 00:00:00 2001 From: String Date: Sat, 24 Jan 2026 06:06:16 -0600 Subject: [PATCH 5/5] =?UTF-8?q?I=20want=20to=20go=20to=20bed=20bro=20pleas?= =?UTF-8?q?e=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/build.gradle | 2 +- android/proguard-rules.pro | 17 +++++++++++++++++ core/build.gradle | 6 ++++-- lwjgl3/build.gradle | 3 --- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index c340702..f1e7e80 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -47,7 +47,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { - minifyEnabled true + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } diff --git a/android/proguard-rules.pro b/android/proguard-rules.pro index 771fa1a..39a0674 100644 --- a/android/proguard-rules.pro +++ b/android/proguard-rules.pro @@ -24,6 +24,17 @@ -dontwarn android.support.** -dontwarn com.badlogic.gdx.backends.android.AndroidFragmentApplication +# Ignore missing AWT classes (desktop-only, not needed on Android) +-dontwarn java.awt.** +-dontwarn javax.swing.** + +# Ignore Java 9+ classes that don't exist on Android +-dontwarn java.lang.Runtime$Version +-dontwarn java.lang.reflect.InaccessibleObjectException + +# Ignore all Groovy warnings (Gradle's internal dependency) +-dontwarn org.codehaus.groovy.** + # Needed by the gdx-controllers official extension. -keep class com.badlogic.gdx.controllers.android.AndroidControllers @@ -39,6 +50,10 @@ float reportRayFixture(long, float, float, float, float, float); } +# Don't obfuscate code at all, since it's open source and we want people to mess with the game's +# internals and reverse engineer the code as much as possible. +-dontobfuscate + # Ignore missing Java Beans classes (Android doesn't have java.beans, Groovy handles this internally) -dontwarn java.beans.** @@ -61,6 +76,8 @@ # You will probably need this line in most cases: -keep public class com.badlogic.gdx.graphics.Color { *; } +-keep class me.stringdotjar.** { *; } + # These two lines are used with mapping files; see https://developer.android.com/build/shrink-code#retracing -keepattributes LineNumberTable,SourceFile -renamesourcefileattribute SourceFile diff --git a/core/build.gradle b/core/build.gradle index c03b084..4dd5eed 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -37,6 +37,8 @@ tasks.register('exportModSDK', Copy) { } // Make sure the assets are ready before the game runs. -tasks.named('build').configure { - dependsOn exportModSDK +if (project.name == 'lwjgl3') { + tasks.named('run') { + dependsOn(rootProject.tasks.named('processAssets')) + } } diff --git a/lwjgl3/build.gradle b/lwjgl3/build.gradle index 09b5ba1..aedb396 100644 --- a/lwjgl3/build.gradle +++ b/lwjgl3/build.gradle @@ -14,9 +14,6 @@ plugins { } apply plugin: 'io.github.fourlastor.construo' - -import io.github.fourlastor.construo.Target - sourceSets.main.resources.srcDirs += [rootProject.file('assets').path] mainClassName = 'me.stringdotjar.funkin.lwjgl3.Lwjgl3Launcher' application.setMainClass(mainClassName)