Skip to content

Commit

Permalink
feat: update and enable SpongeForge for 1.21.3
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Harris-Rouquette <[email protected]>
  • Loading branch information
gabizou committed Dec 26, 2024
2 parents 707b3f1 + 88778c3 commit cd3f230
Show file tree
Hide file tree
Showing 47 changed files with 994 additions and 346 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ jobs:
matrix:
project:
- vanilla
# - forge
- forge
- neoforge
include:
- project: vanilla
gradleProject: SpongeVanilla
# - project: forge
# gradleProject: SpongeForge
- project: forge
gradleProject: SpongeForge
- project: neoforge
gradleProject: SpongeNeo
steps:
Expand Down
3 changes: 3 additions & 0 deletions bootstrap-dev/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies {
api(libs.bootstrap.api)
}
6 changes: 6 additions & 0 deletions bootstrap-dev/src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module org.spongepowered.boostrap.dev {
requires net.minecraftforge.bootstrap.api;
exports org.spongepowered.bootstrap.dev;

provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.bootstrap.dev;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class Multimap<K, V> extends HashMap<K, List<V>> {

public void add(K key, V value) {
this.computeIfAbsent(key, k -> new LinkedList<>()).add(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.vanilla.devlaunch;
package org.spongepowered.bootstrap.dev;

import java.nio.file.Files;
import java.nio.file.Path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.vanilla.devlaunch;
package org.spongepowered.bootstrap.dev;

import net.minecraftforge.bootstrap.api.BootstrapClasspathModifier;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

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

final Map<String, List<Path>> bootSourceSets = new HashMap<>();
final Map<String, List<Path>> unknownProjects = new HashMap<>();
// boot layer
final Multimap<String, Path> bootUnions = new Multimap<>();

final List<Path> spongeImplUnion = new ArrayList<>();
final List<Path> gameLibs = new ArrayList<>();
// game or plugin layer
final Multimap<String, Path> unions = new Multimap<>();
final List<Path> libs = new ArrayList<>();

final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false);

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

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

final String projectName = spongeRoot.relativize(sourceSet.project()).toString();
switch (projectName) {
case "modlauncher-transformers":
bootSourceSets.computeIfAbsent("transformers", k -> new LinkedList<>()).add(path);
case "bootstrap-dev":
// ignore
break;
case "modlauncher-transformers", "library-manager":
bootUnions.add(projectName, path);
break;
case "SpongeAPI":
switch (sourceSet.name()) {
Expand All @@ -91,39 +94,46 @@ public boolean process(final List<Path[]> classpath) {
hasAPISourceSet.set(true);
// no break
default:
spongeImplUnion.add(path);
unions.add("sponge", path);
break;
}
break;
case "", "vanilla":
case "", "vanilla", "forge":
switch (sourceSet.name()) {
case "devlaunch":
// ignore
break;
case "applaunch":
bootSourceSets.computeIfAbsent("applaunch", k -> new LinkedList<>()).add(path);
bootUnions.add("applaunch", path);
break;
case "lang":
unions.add("lang", path);
break;
default:
spongeImplUnion.add(path);
unions.add("sponge", path);
break;
}
break;
default:
unknownProjects.computeIfAbsent(projectName, k -> new LinkedList<>()).add(path);
unions.add(projectName, path);
break;
}
} else {
if (DEBUG) {
System.out.println("External SourceSet (" + sourceSet + "): " + path);
}

unknownProjects.computeIfAbsent(sourceSet.project().toString(), k -> new LinkedList<>()).add(path);
unions.add(sourceSet.project().toString(), path);
}
return true;
}

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

if (ignoredLibs.contains(fileName)) {
if (DEBUG) {
System.out.println("Ignored: " + path);
}
return true;
}

if (bootLibs.contains(fileName)) {
if (DEBUG) {
System.out.println("Boot: " + path);
Expand All @@ -135,27 +145,27 @@ public boolean process(final List<Path[]> classpath) {
if (DEBUG) {
System.out.println("Sponge: " + path);
}
spongeImplUnion.add(path);
unions.add("sponge", path);
return true;
}

if (DEBUG) {
System.out.println("Game: " + path);
}
gameLibs.add(path);
libs.add(path);
return true;
});

if (!modified) {
return false;
}

for (final List<Path> sourceSets : bootSourceSets.values()) {
for (final List<Path> sourceSets : bootUnions.values()) {
classpath.add(sourceSets.toArray(Path[]::new));
}

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

final StringBuilder gameResourcesEnvBuilder = new StringBuilder();
for (final Path resource : gameLibs) {
gameResourcesEnvBuilder.append(resource).append(';');
final StringBuilder resourcesEnvBuilder = new StringBuilder();
for (final Path resource : libs) {
resourcesEnvBuilder.append(resource).append(File.pathSeparator);
}
for (final List<Path> project : unknownProjects.values()) {
for (final List<Path> project : unions.values()) {
for (final Path resource : project) {
gameResourcesEnvBuilder.append(resource).append('&');
resourcesEnvBuilder.append(resource).append('&');
}
gameResourcesEnvBuilder.setCharAt(gameResourcesEnvBuilder.length() - 1, ';');
}
for (final Path resource : spongeImplUnion) {
gameResourcesEnvBuilder.append(resource).append('&');
resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar);
}
gameResourcesEnvBuilder.setLength(gameResourcesEnvBuilder.length() - 1);
final String gameResourcesEnv = gameResourcesEnvBuilder.toString();
resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1);
final String resourcesEnv = resourcesEnvBuilder.toString();

if (DEBUG) {
System.out.println("Game resources env: " + gameResourcesEnv);
System.out.println("Resources env: " + resourcesEnv);
}
System.setProperty("sponge.gameResources", gameResourcesEnv);
System.setProperty("sponge.resources", resourcesEnv);
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer
5 changes: 5 additions & 0 deletions build-logic/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ indra {
dependencies {
api(apiLibs.gson)
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:${apiLibs.versions.ideaExt.get()}")
implementation(libs.at)
implementation(libs.accessWidener)

// arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies
api("dev.architectury:architectury-loom:1.6.411")
}

indraSpotlessLicenser {
Expand Down
9 changes: 8 additions & 1 deletion build-logic/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ pluginManagement {

dependencyResolutionManagement {
repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS
repositories { pluginManagement.repositories.each { add(it) } }
repositories {
pluginManagement.repositories.each { add(it) }
maven {
url = "https://maven.architectury.dev/"
name = "architectury"
}
}

versionCatalogs {
libs {
from files("../gradle/libs.versions.toml")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* This file is part of Sponge, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.gradle.impl;

import dev.architectury.at.AccessChange;
import dev.architectury.at.AccessTransform;
import dev.architectury.at.AccessTransformSet;
import dev.architectury.at.ModifierChange;
import dev.architectury.at.io.AccessTransformFormats;
import net.fabricmc.accesswidener.AccessWidenerReader;
import net.fabricmc.accesswidener.AccessWidenerVisitor;
import org.cadixdev.bombe.type.signature.MethodSignature;
import org.gradle.api.GradleException;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class AWToAT {
private static final Logger logger = Logging.getLogger(AWToAT.class);

public static void convert(final Iterable<File> awFiles, final File atFile) {
AWToAT.logger.lifecycle("Converting AWs {} to AT {} ...", awFiles, atFile);

final AccessTransformSet at = AccessTransformSet.create();

for (final File awFile : awFiles) {
try (final BufferedReader reader = Files.newBufferedReader(awFile.toPath())) {
AWToAT.convert(reader, at);
} catch (final IOException e) {
throw new GradleException("Failed to read access widener: " + awFile, e);
}
}

try (final BufferedWriter writer = Files.newBufferedWriter(atFile.toPath())) {
AccessTransformFormats.FML.write(writer, at);
} catch (IOException e) {
throw new GradleException("Failed to write access transformer: " + atFile, e);
}

AWToAT.logger.lifecycle("Converted AWs to AT.");
}

private static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException {
new AccessWidenerReader(new AccessWidenerVisitor() {
@Override
public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) {
at.getOrCreateClass(name).merge(AWToAT.convertEntry(access));
}

@Override
public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) {
at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), AWToAT.convertEntry(access));
}

@Override
public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) {
at.getOrCreateClass(owner).mergeField(name, AWToAT.convertEntry(access));
}
}).read(reader);
}

private static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) {
return switch (access) {
case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC);
case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE);
};
}
}
Loading

0 comments on commit cd3f230

Please sign in to comment.