diff --git a/Fabric/build.gradle.kts b/Fabric/build.gradle.kts
index eed0938..473294f 100644
--- a/Fabric/build.gradle.kts
+++ b/Fabric/build.gradle.kts
@@ -1,6 +1,8 @@
+import net.fabricmc.loom.configuration.ide.RunConfigSettings
 import org.gradle.jvm.tasks.Jar
 
 val modId: String by project
+val modSides: String by project
 val minecraftVersion: String by project
 val fabricVersion: String by project
 
@@ -24,12 +26,24 @@ loom {
 			ideConfigGenerated(true)
 		}
 		
-		named("client") {
+		fun side(name: String, configure: RunConfigSettings.() -> Unit) {
+			if (modSides == "both" || modSides == name) {
+				named(name, configure)
+			}
+			else {
+				findByName(name)?.let(::remove)
+			}
+		}
+		
+		side("client") {
 			configName = "Fabric Client"
 			client()
 		}
 		
-		findByName("server")?.let(::remove)
+		side("server") {
+			configName = "Fabric Server"
+			server()
+		}
 	}
 	
 	mixin {
@@ -51,7 +65,7 @@ tasks.register<Jar>("uncompressedRemapJar") {
 	group = "fabric"
 	
 	from(tasks.remapJar.map { it.outputs.files.map(::zipTree) })
-
+	
 	archiveClassifier.set("uncompressed")
 	entryCompression = ZipEntryCompression.STORED // Reduces size of multiloader jar.
 }
diff --git a/NeoForge/build.gradle.kts b/NeoForge/build.gradle.kts
index f0ea275..3e0a01f 100644
--- a/NeoForge/build.gradle.kts
+++ b/NeoForge/build.gradle.kts
@@ -1,4 +1,7 @@
+import net.neoforged.moddevgradle.dsl.RunModel
+
 val modId: String by project
+val modSides: String by project
 val neoForgeVersion: String by project
 
 plugins {
@@ -23,10 +26,21 @@ neoForge {
 			jvmArguments.addAll(runJvmArgs)
 		}
 		
-		register("client") {
+		fun side(name: String, configure: RunModel.() -> Unit) {
+			if (modSides == "both" || modSides == name) {
+				register(name, configure)
+			}
+		}
+		
+		side("client") {
 			ideName.set("NeoForge Client")
 			client()
 		}
+		
+		side("server") {
+			ideName.set("NeoForge Server")
+			server()
+		}
 	}
 }
 
diff --git a/gradle.properties b/gradle.properties
index 90a698e..fe11b4e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -10,20 +10,21 @@ modIssuesURL=https://github.com/chylex/Better-Controls/issues
 modSides=client
 
 # Dependencies
-minecraftVersion=1.21
-neoForgeVersion=21.0.0-beta
-neoModDevVersion=1.0.10
-fabricVersion=0.15.11
-loomVersion=1.7
+minecraftVersion=1.21.4
+neoForgeVersion=21.4.77-beta
+neoModDevVersion=2.0.76
+fabricVersion=0.16.10
+loomVersion=1.9
 mixinVersion=0.12.5+mixin.0.8.5
 
+# https://projects.neoforged.net/neoforged/neoforge
 # https://projects.neoforged.net/neoforged/moddevgradle
 # https://fabricmc.net/develop/
 # https://github.com/FabricMC/fabric-loom/releases
 
 # Constraints
-minimumMinecraftVersion=1.21
-minimumNeoForgeVersion=21.0.0-beta
+minimumMinecraftVersion=1.21.4
+minimumNeoForgeVersion=21.4.0-beta
 minimumFabricVersion=0.12.3
 
 # Gradle
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e644113..a4b76b9 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a441313..e18bc25 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
 networkTimeout=10000
 validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index b740cf1..f3b75f3 100755
--- a/gradlew
+++ b/gradlew
@@ -15,6 +15,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+# SPDX-License-Identifier: Apache-2.0
+#
 
 ##############################################################################
 #
@@ -84,7 +86,7 @@ done
 # shellcheck disable=SC2034
 APP_BASE_NAME=${0##*/}
 # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD=maximum
diff --git a/gradlew.bat b/gradlew.bat
index 25da30d..9d21a21 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,6 +13,8 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 @rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
 
 @if "%DEBUG%"=="" @echo off
 @rem ##########################################################################