Skip to content

Commit 71d809e

Browse files
authored
Fabric multi-version support using Stonecutter (#33)
* Some initial work Signed-off-by: IxPrumxI <walidaqeel@gmail.com> * Drop 1.18.2 and below. Working 1.21.4 build Signed-off-by: IxPrumxI <walidaqeel@gmail.com> * Working 1.19+ builds Signed-off-by: IxPrumxI <walidaqeel@gmail.com> * Switch to 1.21.4 Signed-off-by: IxPrumxI <walidaqeel@gmail.com> * Runnable Signed-off-by: IxPrumxI <walidaqeel@gmail.com> * Fix for idea plugin and build script changes * Cleanup comments * Working 1.17+ builds. Development guide for Fabric. * Cleaning up imports * Enable build action for fabric-stonecutter * Remove dependency graph * Add a script for re-creating symlink in windows * Chat suggestions and Skin info * Test commit * Stonecutter 0.7 Disables TextPlaceholder integration * Buildable with `gradle build -x fabirc:build` only 1.21.4 working * Fix mixin failure on 1.19.2 * Use project.property in gradle and remove loom MPO * Fix mixin for all versions * Suppress warning * Check to CallbackInfoReturnable due to warning * Fix advancement mixin for all versions * Fix translation bug on older adventure versions * Refactor FabricDeathModule to use ServerLivingEntityEvents instead of mixins * Fix the real issue with CommandManagerMixin * Fix issues with spectator action in Fabric * Bump stonecutter to 0.7.1 * 1.21.5 and 1.21.6-1.21.8 and a few bug fixes * CI builds for fabric * Set active fabric version to 1.21.6 * Bump Stonecutter to 0.7.3 * Disabled `:fabric:compileJava` task, Now `gradle build` works fine. * Fix mapped sources for fabric and updates link scripts Also ignores the symlinks for the fabric versions * Update development instructions for setting up mapped sources * Remove unused import * Remove idea module testing code * Re-enable TextPlaceholderIntegration * TextPlaceholderIntegration had wrong minecraft version * Drop fabric-stonecutter changes in build.yaml * Fabric adventure utility * Bump Stonecutter to 0.7.4 * Forgot licence * Update FabricPlayer#skinInfo to use skin parts * Remove MixinExtras from fabric * Update bungeecord-api to 1.21-R0.4-SNAPSHOT * Fix import issues * Suppress adventure removal warning * Fix build * Mixin into ServerPlayerEntity to support locale under 1.20.2 * Add task to delete mapped source for Fabric * Fix locale mixin * Change compatibility level to 17 * Remove TextColor usage * Remove unused import * Remove FabricCommandHandler#getSender to use ServerCommandSource#getEntity instead * Update kyori's ANSI library to 1.1.0 in older versions * Refactor FabricAdventureUtil to FabricComponentFactory * Implement player model parts correctly in lower versions * Fix an issue with PlayerAdvancementTrackerMixin in 1.20.1 * Add error when FabricDiscordSRV is null on server startup * Bump adventure-platform-mod to 6.5.1 for 1.21.6 --------- Signed-off-by: IxPrumxI <walidaqeel@gmail.com>
1 parent 5b66645 commit 71d809e

55 files changed

Lines changed: 844 additions & 186 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,7 @@ hs_err_pid*
4444
**/fabric/run
4545

4646
# Fabric mapping migration
47-
**/fabric/remappedSrc
47+
**/fabric/remappedSrc
48+
49+
# Fabric src links
50+
/fabric/versions/*/src

build.gradle

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ subprojects {
3030
targetCompatibility = JavaVersion.VERSION_1_8
3131
}
3232

33+
if (project.path == ":fabric") {
34+
compileJava.configure {
35+
doFirst {
36+
throw new StopExecutionException(
37+
"The 'compileJava' task is disabled in fabric root project."
38+
)
39+
}
40+
}
41+
}
42+
3343
configurations {
3444
// Exclude dependencies from being included in jars
3545
runtimeExclude {
@@ -121,7 +131,6 @@ subprojects {
121131
}
122132
clean.dependsOn deleteJarsDir
123133

124-
defaultTasks 'build'
125134
jar {
126135
duplicatesStrategy = DuplicatesStrategy.INCLUDE
127136

buildscript/final.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ shadowJar {
1414
rename { fileName -> 'LICENSE.txt' }
1515
}
1616

17-
if (it.project.name != "fabric") {
17+
if (it.project.parent.name != "fabric") {
1818
finalizedBy copyOutput
1919
}
20-
}
20+
}

common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ private String readAttribute(Attributes attributes, String key) {
374374
}
375375

376376
@Override
377-
public final @NotNull ComponentFactory componentFactory() {
377+
public @NotNull ComponentFactory componentFactory() {
378378
return componentFactory;
379379
}
380380

common/src/main/java/com/discordsrv/common/core/component/ComponentFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ public ComponentFactory(DiscordSRV discordSRV) {
111111
}
112112

113113
private final ThreadLocal<Set<String>> translationHistory = new ThreadLocal<>();
114+
@SuppressWarnings("deprecation")
114115
private String provideTranslation(TranslatableComponent component) {
115116
Set<String> history = translationHistory.get();
116117
if (history == null) {
@@ -140,7 +141,7 @@ private String provideTranslation(TranslatableComponent component) {
140141
translationHistory.set(history);
141142

142143
return translation.translate(
143-
component.arguments()
144+
component.args()
144145
.stream()
145146
.map(argument -> plainSerializer().serialize(argument.asComponent()))
146147
.toArray(Object[]::new)

fabric/DEVELOP.MD

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## Fabric Development
2+
This mod is using [Stonecutter](https://stonecutter.kikugie.dev/) to support multiple Minecraft versions.
3+
To add a new feature in this mod you need to follow these steps:
4+
1. Run gradle task "Set active project to X" in stonecutter where X is the lowest Minecraft version you want to support.
5+
2. Go to `fabric/scripts` and run the script for your operating system to set up the mapped sources
6+
3. Go to `fabric/versions/<version>/src` and add your changes there as intelij idea will not add the correct classpath to the main sources folder.
7+
4. Make sure that whatever api you are using is available in all Fabric and Minecraft versions.
8+
5. Before you commit your changes, run the gradle task "Reset active project" in stonecutter
9+
10+
## Adventure API
11+
This mod uses all 3 major versions of adventure-platform-fabric (4, 5 and 6) and the lowest Minecraft version supported due to this is 1.16.2.
12+
You can use the following examples to see how the checks are done in the code:
13+
```java
14+
//? if adventure: <6 {
15+
/*@SuppressWarnings("removal")
16+
Component component = discordSRV.getAdventure().toAdventure(signedMessage.getContent());
17+
*///?} else {
18+
Component component = discordSRV.getAdventure().asAdventure(signedMessage.getContent());
19+
//?}
20+
```
21+
```java
22+
//? if adventure: >=5.11.0 {
23+
return player.identity();
24+
//?} else {
25+
/*return Identity.identity(player.getUuid());
26+
*///?}
27+
```
28+
29+
## Mixins
30+
You may want to use mixins in the case that a fabric api is not supported in the lowest Minecraft version.
31+
Refer to CommandManagerMixin and FabricRequiredLinkingModule for an example of how to use mixins in this mod with changing Minecraft classes.

fabric/build.gradle

Lines changed: 96 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
plugins {
2+
id("dev.kikugie.stonecutter") version "0.7.4"
3+
id("fabric-loom")
4+
}
15
apply from: rootProject.file('buildscript/standalone.gradle')
2-
apply plugin: 'fabric-loom'
36

47
configurations.configureEach {
58
resolutionStrategy {
@@ -8,13 +11,45 @@ configurations.configureEach {
811
}
912

1013
java {
11-
sourceCompatibility = JavaVersion.VERSION_21
12-
targetCompatibility = JavaVersion.VERSION_21
14+
def javaVersion = project.property("deps.java") == 17 ? JavaVersion.VERSION_17 : project.property("deps.java") == 21 ? JavaVersion.VERSION_21 : null
15+
targetCompatibility = javaVersion
16+
sourceCompatibility = javaVersion
17+
}
18+
19+
if(project.path.startsWith(":fabric:")) {
20+
tasks.register('deleteMappedSrc', Delete) {
21+
delete project.file("src")
22+
}
23+
24+
clean.dependsOn deleteMappedSrc
25+
}
26+
27+
sourceSets {
28+
main {
29+
java {
30+
srcDirs("versions/${stonecutter.current.project}/src/main/java")
31+
}
32+
resources {
33+
srcDirs("versions/${stonecutter.current.project}/src/main/resources")
34+
}
35+
}
1336
}
1437

1538
processResources {
16-
filesMatching('**/fabric.mod.json') {
17-
expand 'VERSION': project.version, 'MINECRAFT_VERSION': libs.fabric.minecraft.get().version, 'LOADER_VERSION': libs.fabric.loader.get().version
39+
def version = project.version
40+
def loaderVersion = project.property("deps.fabric_loader")
41+
def minecraftVersion = stonecutter.current.project
42+
43+
inputs.property("version", version)
44+
inputs.property("loaderVersion", loaderVersion)
45+
inputs.property("minecraftVersion", minecraftVersion)
46+
47+
filesMatching("fabric.mod.json") {
48+
expand(
49+
VERSION: version,
50+
LOADER_VERSION: loaderVersion,
51+
MINECRAFT_VERSION: minecraftVersion
52+
)
1853
}
1954
dependsOn generateRuntimeDownloadResourceForRuntimeDownloadOnly
2055
}
@@ -24,29 +59,51 @@ shadowJar {
2459
mergeServiceFiles()
2560
}
2661

62+
stonecutter {
63+
def adventure = project.property("deps.adventure_platform_fabric").replace("-SNAPSHOT", "")
64+
dependency("adventure", adventure)
65+
dependency("java", project.property("deps.java"))
66+
67+
swap("dependencies_file", "\"dependencies/runtimeDownload-${stonecutter.current.version}.txt\";")
68+
}
69+
2770
tasks.register('copyRemappedJar', Copy) {
2871
from remapJar.archiveFile
29-
into rootProject.file('jars')
72+
into rootProject.file('jars/fabric')
3073
}
3174

3275
remapJar {
3376
dependsOn shadowJar
3477
mustRunAfter shadowJar
3578
inputFile = shadowJar.archiveFile
36-
archiveBaseName = 'DiscordSRV-Fabric'
79+
80+
archiveBaseName = "DiscordSRV-Fabric-${stonecutter.current.project}"
81+
if (stonecutter.current.version == "1.21.6") {
82+
archiveBaseName = "DiscordSRV-Fabric-${stonecutter.current.project}-1.21.8"
83+
}
3784
archiveClassifier = jar.archiveClassifier
3885

3986
finalizedBy copyRemappedJar
4087
}
4188

89+
spotless {
90+
java {
91+
if (stonecutter.current.isActive)
92+
target("src/main/java/")
93+
}
94+
}
95+
4296
artifacts {
4397
archives remapJar
4498
shadow shadowJar
4599
}
46100

47101
loom {
48102
serverOnlyMinecraftJar()
49-
accessWidenerPath = file('src/main/resources/discordsrv.accesswidener')
103+
runConfigs.all {
104+
ideConfigGenerated(true) // Run configurations are not created for subprojects by default
105+
runDir = "../../run" // Use a shared run folder and create separate worlds
106+
}
50107
}
51108

52109
repositories {
@@ -69,15 +126,30 @@ repositories {
69126
}
70127

71128
dependencies {
72-
// To change the versions see the settings.gradle file
73-
minecraft(libs.fabric.minecraft)
74-
mappings(variantOf(libs.fabric.yarn) { classifier("v2") })
75-
compileOnly(libs.fabric.loader)
129+
minecraft("com.mojang:minecraft:${stonecutter.current.project}")
130+
mappings("net.fabricmc:yarn:${project.property("deps.yarn_mappings")}:v2")
131+
compileOnly("net.fabricmc:fabric-loader:${project.property("deps.fabric_loader")}")
76132

77133
// Fabric API
78-
modImplementation(libs.fabric.api)
79-
modImplementation(libs.fabric.permissions.api)
80-
include(libs.fabric.permissions.api)
134+
Set<String> apiModules = [
135+
'fabric-api-base',
136+
'fabric-lifecycle-events-v1',
137+
'fabric-entity-events-v1',
138+
'fabric-networking-api-v1',
139+
]
140+
if (stonecutter.eval(stonecutter.current.version, ">=1.19.2")) {
141+
apiModules.add('fabric-message-api-v1')
142+
}
143+
apiModules.forEach {
144+
modImplementation(fabricApi.module(it, project.property("deps.fabric_api")))
145+
}
146+
147+
// Minecraft versions under 1.21.6 should use 0.3.3, while 1.21.6 and above should use 0.4.1
148+
modImplementation("me.lucko:fabric-permissions-api:${stonecutter.eval(stonecutter.current.version, ">=1.21.6") ? '0.4.1' : '0.3.3'}") {
149+
exclude group: 'net.fabricmc.fabric-api', module: 'fabric-api-base'
150+
exclude group: 'net.fabricmc.fabric-api', module: 'fabric-api-bom'
151+
}
152+
include ("me.lucko:fabric-permissions-api:${stonecutter.eval(stonecutter.current.version, ">=1.21.6") ? '0.4.1' : '0.3.3'}")
81153

82154
// API
83155
annotationProcessor project(':api')
@@ -87,14 +159,19 @@ dependencies {
87159
shadow project(':common')
88160

89161
// Adventure
90-
modImplementation(libs.adventure.platform.fabric)
91-
include(libs.adventure.platform.fabric)
162+
modImplementation("net.kyori:adventure-platform-fabric:${project.property("deps.adventure_platform_fabric")}") {
163+
exclude group: 'net.kyori', module: 'ansi'
164+
}
165+
include("net.kyori:adventure-platform-fabric:${project.property("deps.adventure_platform_fabric")}")
166+
167+
implementation(libs.kyori.ansi)
168+
include(libs.kyori.ansi)
92169

93170
// Integrations
94-
modCompileOnly(libs.textplaceholder.fabric)
171+
modCompileOnly("eu.pb4:placeholder-api:${project.property("deps.text_placeholder_api")}")
95172

96173
// DependencyDownload
97174
shadow(libs.mcdependencydownload.fabric) {
98175
exclude module: 'fabric-loader'
99176
}
100-
}
177+
}

fabric/gradle.properties

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
deps.fabric_loader=0.14.0
2+
3+
deps.yarn_mappings=[VERSIONED]
4+
deps.fabric_api=[VERSIONED]
5+
deps.adventure_platform_fabric=[VERSIONED]
6+
deps.text_placeholder_api=[VERSIONED]
7+
deps.java=[VERSIONED]

fabric/scripts/linux-link-src.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
5+
6+
SRC_DIR="$SCRIPT_DIR/../src"
7+
VERSIONS_DIR="$SCRIPT_DIR/../versions"
8+
9+
echo
10+
echo "Linking $SRC_DIR into each version under $VERSIONS_DIR"
11+
for version_path in "$VERSIONS_DIR"/*; do
12+
ver="$(basename "$version_path")"
13+
target="$version_path/src"
14+
if [[ -e "$target" ]]; then
15+
rm -rf "$target"
16+
fi
17+
echo "Linking src → versions/$ver/src"
18+
ln -s "$SRC_DIR" "$target"
19+
done
20+
21+
echo
22+
echo "All done. Each version now has a link to the src directory."
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Check if running as Administrator
2+
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
3+
Write-Host "Script needs to be run as Administrator. Restarting with elevated privileges..."
4+
5+
# Relaunch PowerShell as Administrator
6+
Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
7+
exit
8+
}
9+
10+
# Set base paths
11+
$basePath = "$PSScriptRoot\..\versions"
12+
$srcPath = "$PSScriptRoot\..\src"
13+
14+
# Loop through each version folder
15+
Get-ChildItem -Directory $basePath | ForEach-Object {
16+
$versionPath = $_.FullName
17+
$linkPath = Join-Path $versionPath "src"
18+
19+
# Remove existing link if it exists
20+
if (Test-Path $linkPath) {
21+
Write-Host "Removing existing link at $linkPath"
22+
Remove-Item $linkPath -Force
23+
}
24+
25+
# Create new symbolic link
26+
Write-Host "Creating symbolic link in $versionPath"
27+
cmd.exe /c "mklink /D `"$linkPath`" `"$srcPath`""
28+
}

0 commit comments

Comments
 (0)