Skip to content

Commit cd3f230

Browse files
committed
feat: update and enable SpongeForge for 1.21.3
Signed-off-by: Gabriel Harris-Rouquette <[email protected]>
2 parents 707b3f1 + 88778c3 commit cd3f230

File tree

47 files changed

+994
-346
lines changed

Some content is hidden

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

47 files changed

+994
-346
lines changed

.github/workflows/deploy.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ jobs:
2929
matrix:
3030
project:
3131
- vanilla
32-
# - forge
32+
- forge
3333
- neoforge
3434
include:
3535
- project: vanilla
3636
gradleProject: SpongeVanilla
37-
# - project: forge
38-
# gradleProject: SpongeForge
37+
- project: forge
38+
gradleProject: SpongeForge
3939
- project: neoforge
4040
gradleProject: SpongeNeo
4141
steps:

bootstrap-dev/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dependencies {
2+
api(libs.bootstrap.api)
3+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module org.spongepowered.boostrap.dev {
2+
requires net.minecraftforge.bootstrap.api;
3+
exports org.spongepowered.bootstrap.dev;
4+
5+
provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer;
6+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.bootstrap.dev;
26+
27+
import java.util.HashMap;
28+
import java.util.LinkedList;
29+
import java.util.List;
30+
31+
public class Multimap<K, V> extends HashMap<K, List<V>> {
32+
33+
public void add(K key, V value) {
34+
this.computeIfAbsent(key, k -> new LinkedList<>()).add(value);
35+
}
36+
}

vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java renamed to bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323
* THE SOFTWARE.
2424
*/
25-
package org.spongepowered.vanilla.devlaunch;
25+
package org.spongepowered.bootstrap.dev;
2626

2727
import java.nio.file.Files;
2828
import java.nio.file.Path;

vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java renamed to bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,16 @@
2222
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323
* THE SOFTWARE.
2424
*/
25-
package org.spongepowered.vanilla.devlaunch;
25+
package org.spongepowered.bootstrap.dev;
2626

2727
import net.minecraftforge.bootstrap.api.BootstrapClasspathModifier;
2828

29+
import java.io.File;
2930
import java.nio.file.Files;
3031
import java.nio.file.Path;
3132
import java.nio.file.Paths;
3233
import java.util.ArrayList;
33-
import java.util.HashMap;
34-
import java.util.LinkedList;
3534
import java.util.List;
36-
import java.util.Map;
3735
import java.util.Set;
3836
import java.util.concurrent.atomic.AtomicBoolean;
3937

@@ -53,14 +51,16 @@ public String name() {
5351
@Override
5452
public boolean process(final List<Path[]> classpath) {
5553
final Path spongeRoot = Paths.get(System.getProperty("sponge.dev.root")).toAbsolutePath();
56-
final Set<String> bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(";"));
57-
final Set<String> gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(";"));
54+
final Set<String> ignoredLibs = Set.of("bootstrap-dev.jar");
55+
final Set<String> bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator));
56+
final Set<String> gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator));
5857

59-
final Map<String, List<Path>> bootSourceSets = new HashMap<>();
60-
final Map<String, List<Path>> unknownProjects = new HashMap<>();
58+
// boot layer
59+
final Multimap<String, Path> bootUnions = new Multimap<>();
6160

62-
final List<Path> spongeImplUnion = new ArrayList<>();
63-
final List<Path> gameLibs = new ArrayList<>();
61+
// game or plugin layer
62+
final Multimap<String, Path> unions = new Multimap<>();
63+
final List<Path> libs = new ArrayList<>();
6464

6565
final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false);
6666

@@ -69,7 +69,7 @@ public boolean process(final List<Path[]> classpath) {
6969
return false;
7070
}
7171

72-
final Path path = paths[0].toAbsolutePath();
72+
final Path path = paths[0];
7373
final SourceSet sourceSet = SourceSet.identify(path);
7474
if (sourceSet != null) {
7575
if (sourceSet.project().startsWith(spongeRoot)) {
@@ -79,8 +79,11 @@ public boolean process(final List<Path[]> classpath) {
7979

8080
final String projectName = spongeRoot.relativize(sourceSet.project()).toString();
8181
switch (projectName) {
82-
case "modlauncher-transformers":
83-
bootSourceSets.computeIfAbsent("transformers", k -> new LinkedList<>()).add(path);
82+
case "bootstrap-dev":
83+
// ignore
84+
break;
85+
case "modlauncher-transformers", "library-manager":
86+
bootUnions.add(projectName, path);
8487
break;
8588
case "SpongeAPI":
8689
switch (sourceSet.name()) {
@@ -91,39 +94,46 @@ public boolean process(final List<Path[]> classpath) {
9194
hasAPISourceSet.set(true);
9295
// no break
9396
default:
94-
spongeImplUnion.add(path);
97+
unions.add("sponge", path);
9598
break;
9699
}
97100
break;
98-
case "", "vanilla":
101+
case "", "vanilla", "forge":
99102
switch (sourceSet.name()) {
100-
case "devlaunch":
101-
// ignore
102-
break;
103103
case "applaunch":
104-
bootSourceSets.computeIfAbsent("applaunch", k -> new LinkedList<>()).add(path);
104+
bootUnions.add("applaunch", path);
105+
break;
106+
case "lang":
107+
unions.add("lang", path);
105108
break;
106109
default:
107-
spongeImplUnion.add(path);
110+
unions.add("sponge", path);
108111
break;
109112
}
110113
break;
111114
default:
112-
unknownProjects.computeIfAbsent(projectName, k -> new LinkedList<>()).add(path);
115+
unions.add(projectName, path);
113116
break;
114117
}
115118
} else {
116119
if (DEBUG) {
117120
System.out.println("External SourceSet (" + sourceSet + "): " + path);
118121
}
119122

120-
unknownProjects.computeIfAbsent(sourceSet.project().toString(), k -> new LinkedList<>()).add(path);
123+
unions.add(sourceSet.project().toString(), path);
121124
}
122125
return true;
123126
}
124127

125128
final String fileName = path.getFileName().toString();
126129

130+
if (ignoredLibs.contains(fileName)) {
131+
if (DEBUG) {
132+
System.out.println("Ignored: " + path);
133+
}
134+
return true;
135+
}
136+
127137
if (bootLibs.contains(fileName)) {
128138
if (DEBUG) {
129139
System.out.println("Boot: " + path);
@@ -135,27 +145,27 @@ public boolean process(final List<Path[]> classpath) {
135145
if (DEBUG) {
136146
System.out.println("Sponge: " + path);
137147
}
138-
spongeImplUnion.add(path);
148+
unions.add("sponge", path);
139149
return true;
140150
}
141151

142152
if (DEBUG) {
143153
System.out.println("Game: " + path);
144154
}
145-
gameLibs.add(path);
155+
libs.add(path);
146156
return true;
147157
});
148158

149159
if (!modified) {
150160
return false;
151161
}
152162

153-
for (final List<Path> sourceSets : bootSourceSets.values()) {
163+
for (final List<Path> sourceSets : bootUnions.values()) {
154164
classpath.add(sourceSets.toArray(Path[]::new));
155165
}
156166

157167
if (hasAPISourceSet.get()) {
158-
spongeImplUnion.removeIf((path) -> {
168+
unions.get("sponge").removeIf((path) -> {
159169
if (Files.isRegularFile(path)) {
160170
final String fileName = path.getFileName().toString();
161171
if (fileName.startsWith("spongeapi") && fileName.endsWith(".jar")) {
@@ -169,26 +179,23 @@ public boolean process(final List<Path[]> classpath) {
169179
});
170180
}
171181

172-
final StringBuilder gameResourcesEnvBuilder = new StringBuilder();
173-
for (final Path resource : gameLibs) {
174-
gameResourcesEnvBuilder.append(resource).append(';');
182+
final StringBuilder resourcesEnvBuilder = new StringBuilder();
183+
for (final Path resource : libs) {
184+
resourcesEnvBuilder.append(resource).append(File.pathSeparator);
175185
}
176-
for (final List<Path> project : unknownProjects.values()) {
186+
for (final List<Path> project : unions.values()) {
177187
for (final Path resource : project) {
178-
gameResourcesEnvBuilder.append(resource).append('&');
188+
resourcesEnvBuilder.append(resource).append('&');
179189
}
180-
gameResourcesEnvBuilder.setCharAt(gameResourcesEnvBuilder.length() - 1, ';');
181-
}
182-
for (final Path resource : spongeImplUnion) {
183-
gameResourcesEnvBuilder.append(resource).append('&');
190+
resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar);
184191
}
185-
gameResourcesEnvBuilder.setLength(gameResourcesEnvBuilder.length() - 1);
186-
final String gameResourcesEnv = gameResourcesEnvBuilder.toString();
192+
resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1);
193+
final String resourcesEnv = resourcesEnvBuilder.toString();
187194

188195
if (DEBUG) {
189-
System.out.println("Game resources env: " + gameResourcesEnv);
196+
System.out.println("Resources env: " + resourcesEnv);
190197
}
191-
System.setProperty("sponge.gameResources", gameResourcesEnv);
198+
System.setProperty("sponge.resources", resourcesEnv);
192199
return true;
193200
}
194201
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer

build-logic/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ indra {
1313
dependencies {
1414
api(apiLibs.gson)
1515
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:${apiLibs.versions.ideaExt.get()}")
16+
implementation(libs.at)
17+
implementation(libs.accessWidener)
18+
19+
// arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies
20+
api("dev.architectury:architectury-loom:1.6.411")
1621
}
1722

1823
indraSpotlessLicenser {

build-logic/settings.gradle

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ pluginManagement {
99

1010
dependencyResolutionManagement {
1111
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
12-
repositories { pluginManagement.repositories.each { add(it) } }
12+
repositories {
13+
pluginManagement.repositories.each { add(it) }
14+
maven {
15+
url = "https://maven.architectury.dev/"
16+
name = "architectury"
17+
}
18+
}
19+
1320
versionCatalogs {
1421
libs {
1522
from files("../gradle/libs.versions.toml")
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.gradle.impl;
26+
27+
import dev.architectury.at.AccessChange;
28+
import dev.architectury.at.AccessTransform;
29+
import dev.architectury.at.AccessTransformSet;
30+
import dev.architectury.at.ModifierChange;
31+
import dev.architectury.at.io.AccessTransformFormats;
32+
import net.fabricmc.accesswidener.AccessWidenerReader;
33+
import net.fabricmc.accesswidener.AccessWidenerVisitor;
34+
import org.cadixdev.bombe.type.signature.MethodSignature;
35+
import org.gradle.api.GradleException;
36+
import org.gradle.api.logging.Logger;
37+
import org.gradle.api.logging.Logging;
38+
39+
import java.io.BufferedReader;
40+
import java.io.BufferedWriter;
41+
import java.io.File;
42+
import java.io.IOException;
43+
import java.nio.file.Files;
44+
45+
public class AWToAT {
46+
private static final Logger logger = Logging.getLogger(AWToAT.class);
47+
48+
public static void convert(final Iterable<File> awFiles, final File atFile) {
49+
AWToAT.logger.lifecycle("Converting AWs {} to AT {} ...", awFiles, atFile);
50+
51+
final AccessTransformSet at = AccessTransformSet.create();
52+
53+
for (final File awFile : awFiles) {
54+
try (final BufferedReader reader = Files.newBufferedReader(awFile.toPath())) {
55+
AWToAT.convert(reader, at);
56+
} catch (final IOException e) {
57+
throw new GradleException("Failed to read access widener: " + awFile, e);
58+
}
59+
}
60+
61+
try (final BufferedWriter writer = Files.newBufferedWriter(atFile.toPath())) {
62+
AccessTransformFormats.FML.write(writer, at);
63+
} catch (IOException e) {
64+
throw new GradleException("Failed to write access transformer: " + atFile, e);
65+
}
66+
67+
AWToAT.logger.lifecycle("Converted AWs to AT.");
68+
}
69+
70+
private static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException {
71+
new AccessWidenerReader(new AccessWidenerVisitor() {
72+
@Override
73+
public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) {
74+
at.getOrCreateClass(name).merge(AWToAT.convertEntry(access));
75+
}
76+
77+
@Override
78+
public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) {
79+
at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), AWToAT.convertEntry(access));
80+
}
81+
82+
@Override
83+
public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) {
84+
at.getOrCreateClass(owner).mergeField(name, AWToAT.convertEntry(access));
85+
}
86+
}).read(reader);
87+
}
88+
89+
private static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) {
90+
return switch (access) {
91+
case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC);
92+
case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE);
93+
};
94+
}
95+
}

0 commit comments

Comments
 (0)