-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix issues with Forge #225
Changes from all commits
1138d0a
116f8ee
faca293
b27d721
7ad1fa8
294a30d
4de99f3
90bcdc0
07664a3
4bba791
8446f11
9feed22
a01b9a6
b9aaba2
f7102f2
19425cd
81b7f4f
20334f5
aa43f5a
555e1e0
64441fe
06ed900
e052ae9
900f2cf
81d92d6
acdc6db
9d33f3f
4a15c82
e35e30b
bef3ea8
1563c35
36777ef
21bf66d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -24,6 +24,7 @@ | |||||
|
||||||
package net.fabricmc.loom.configuration.providers.forge; | ||||||
|
||||||
import java.io.File; | ||||||
import java.io.Serializable; | ||||||
import java.util.HashMap; | ||||||
import java.util.List; | ||||||
|
@@ -110,12 +111,21 @@ public void applyTo(RunConfigSettings settings, ConfigValue.Resolver configValue | |||||
settings.getEnvironmentVariables().putIfAbsent(key, resolved); | ||||||
}); | ||||||
|
||||||
final ForgeProvider forgeProvider = settings.getExtension().getForgeProvider(); | ||||||
|
||||||
// Add MOD_CLASSES, this is something that ForgeGradle does | ||||||
settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> ConfigValue.of("{source_roots}").resolve(configValueResolver)); | ||||||
settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> { | ||||||
String modClasses = ConfigValue.of("{source_roots}").resolve(configValueResolver); | ||||||
|
||||||
final ForgeProvider forgeProvider = settings.getExtension().getForgeProvider(); | ||||||
if (File.pathSeparatorChar == ':' && forgeProvider.usesBootstrapDev()) { | ||||||
// bs-dev has a bug where ';' is used instead of File.pathSeparatorChar | ||||||
modClasses = modClasses.replaceAll(":", ";"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
No need to use regex here |
||||||
} | ||||||
|
||||||
return modClasses; | ||||||
}); | ||||||
|
||||||
if (settings.getExtension().isForge() && forgeProvider.getVersion().getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION) { | ||||||
if (settings.getExtension().isForge() && forgeProvider.usesUnionRelauncher()) { | ||||||
settings.defaultMainClass(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS); | ||||||
settings.property(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS_PROPERTY, main); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,6 +58,7 @@ | |
import org.gradle.api.Project; | ||
import org.gradle.api.logging.LogLevel; | ||
import org.gradle.api.logging.Logger; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.objectweb.asm.ClassReader; | ||
import org.objectweb.asm.ClassVisitor; | ||
import org.objectweb.asm.ClassWriter; | ||
|
@@ -111,6 +112,8 @@ public class MinecraftPatchedProvider { | |
private Path minecraftPatchedIntermediateJar; | ||
// Step 3: Access Transform | ||
private Path minecraftPatchedIntermediateAtJar; | ||
// Forge 1.20.6: Step 3.5: Remap Patched AT and Forge to mojmaps | ||
private Path minecraftPatchedMojangAtJar; | ||
// Step 4: Remap Patched AT & Forge to official | ||
private Path minecraftPatchedJar; | ||
private Path minecraftClientExtra; | ||
|
@@ -151,6 +154,11 @@ private void initPatchedFiles() { | |
minecraftIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + ".jar"); | ||
minecraftPatchedIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-patched.jar"); | ||
minecraftPatchedIntermediateAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-at-patched.jar"); | ||
|
||
if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) { | ||
minecraftPatchedMojangAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-mojang-at-patched.jar"); | ||
} | ||
|
||
minecraftPatchedJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-patched.jar"); | ||
minecraftClientExtra = forgeWorkingDir.resolve("client-extra.jar"); | ||
} | ||
|
@@ -162,13 +170,14 @@ private void cleanAllCache() throws IOException { | |
} | ||
|
||
private Path[] getGlobalCaches() { | ||
Path[] files = { | ||
Path[] files = Stream.of( | ||
minecraftIntermediateJar, | ||
minecraftPatchedIntermediateJar, | ||
minecraftPatchedIntermediateAtJar, | ||
minecraftPatchedMojangAtJar, | ||
minecraftPatchedJar, | ||
minecraftClientExtra, | ||
}; | ||
minecraftClientExtra | ||
).filter(Objects::nonNull).toArray(Path[]::new); | ||
|
||
return files; | ||
} | ||
|
@@ -201,7 +210,7 @@ public void provide() throws Exception { | |
patchJars(); | ||
} | ||
|
||
if (dirty || Files.notExists(minecraftPatchedIntermediateAtJar)) { | ||
if (dirty || Files.notExists(minecraftPatchedIntermediateAtJar) || (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime() && Files.notExists(minecraftPatchedMojangAtJar))) { | ||
this.dirty = true; | ||
accessTransformForge(); | ||
} | ||
|
@@ -227,14 +236,16 @@ private void fillClientExtraJar() throws IOException { | |
} | ||
|
||
private TinyRemapper buildRemapper(SharedServiceManager serviceManager, Path input) throws IOException { | ||
final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); | ||
return buildRemapper(MappingOption.forPlatform(getExtension()), IntermediaryNamespaces.intermediary(project), "official", serviceManager, input); | ||
} | ||
|
||
private TinyRemapper buildRemapper(final MappingOption mappingOption, final String sourceNamespace, final String to, SharedServiceManager serviceManager, Path input) throws IOException { | ||
TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); | ||
final String sourceNamespace = IntermediaryNamespaces.intermediary(project); | ||
MemoryMappingTree mappings = mappingsService.getMappingTree(); | ||
|
||
TinyRemapper.Builder builder = TinyRemapper.newRemapper() | ||
.withMappings(TinyRemapperHelper.create(mappings, sourceNamespace, "official", true)) | ||
.withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappings, sourceNamespace, "official")) | ||
.withMappings(TinyRemapperHelper.create(mappings, sourceNamespace, to, true)) | ||
.withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappings, sourceNamespace, to)) | ||
.renameInvalidLocals(true) | ||
.rebuildSourceFilenames(true); | ||
|
||
|
@@ -409,33 +420,51 @@ public static void accessTransform(Project project, Path input, Path target) thr | |
} | ||
|
||
private void remapPatchedJar(SharedServiceManager serviceManager) throws Exception { | ||
logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)"); | ||
Path mcInput = minecraftPatchedIntermediateAtJar; | ||
Path mcPatchedAt = minecraftPatchedMojangAtJar; | ||
Path mcOutput = minecraftPatchedJar; | ||
Path forgeJar = getForgeJar().toPath(); | ||
Path forgeUserdevJar = getForgeUserdevJar().toPath(); | ||
|
||
if (mcPatchedAt != null) { | ||
Files.deleteIfExists(mcPatchedAt); | ||
} | ||
|
||
Files.deleteIfExists(mcOutput); | ||
|
||
TinyRemapper remapper = buildRemapper(serviceManager, mcInput); | ||
if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) { | ||
logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> mojang)"); | ||
TinyRemapper remapper = buildRemapper(MappingOption.WITH_SRG, "srg", "mojang", serviceManager, mcInput); | ||
remapJar(remapper, serviceManager, mcInput, mcPatchedAt, forgeJar, forgeUserdevJar, false); | ||
logger.lifecycle(":remapping minecraft (TinyRemapper, mojang -> official)"); | ||
TinyRemapper remapper2 = buildRemapper(MappingOption.WITH_MOJANG, "mojang", "official", serviceManager, mcInput); | ||
remapJar(remapper2, serviceManager, mcPatchedAt, mcOutput, null, null, true); | ||
Comment on lines
+436
to
+441
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the game remapped twice? Remapping the game is slow, so it should be avoided. |
||
} else { | ||
logger.lifecycle(":remapping minecraft (TinyRemapper, %s -> official)".formatted(getExtension().isForge() ? "srg" : "mojang")); | ||
TinyRemapper remapper = buildRemapper(serviceManager, mcInput); | ||
remapJar(remapper, serviceManager, mcInput, mcOutput, forgeJar, forgeUserdevJar, true); | ||
} | ||
} | ||
|
||
private void remapJar(TinyRemapper remapper, SharedServiceManager serviceManager, Path mcInput, Path mcOutput, @Nullable Path forgeJar, @Nullable Path forgeUserdevJar, boolean remapCoreMods) throws Exception { | ||
try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(mcOutput).build()) { | ||
outputConsumer.addNonClassFiles(mcInput); | ||
outputConsumer.addNonClassFiles(forgeJar, NonClassCopyMode.FIX_META_INF, remapper); | ||
if (forgeJar != null) outputConsumer.addNonClassFiles(forgeJar, NonClassCopyMode.FIX_META_INF, remapper); | ||
|
||
InputTag mcTag = remapper.createInputTag(); | ||
InputTag forgeTag = remapper.createInputTag(); | ||
List<CompletableFuture<?>> futures = new ArrayList<>(); | ||
futures.add(remapper.readInputsAsync(mcTag, mcInput)); | ||
futures.add(remapper.readInputsAsync(forgeTag, forgeJar, forgeUserdevJar)); | ||
if (forgeJar != null) futures.add(remapper.readInputsAsync(forgeTag, forgeJar, forgeUserdevJar)); | ||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); | ||
remapper.apply(outputConsumer, mcTag); | ||
remapper.apply(outputConsumer, forgeTag); | ||
} finally { | ||
remapper.finish(); | ||
} | ||
|
||
copyUserdevFiles(forgeUserdevJar, mcOutput); | ||
remapCoreMods(mcOutput, serviceManager); | ||
if (forgeUserdevJar != null) copyUserdevFiles(forgeUserdevJar, mcOutput); | ||
if (remapCoreMods) remapCoreMods(mcOutput, serviceManager); | ||
applyLoomPatchVersion(mcOutput); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -99,6 +99,7 @@ public class MappingConfiguration { | |||||
private boolean hasUnpickDefinitions; | ||||||
private UnpickMetadata unpickMetadata; | ||||||
private Map<String, String> signatureFixes; | ||||||
private LoomGradleExtension extension; | ||||||
|
||||||
protected MappingConfiguration(String mappingsIdentifier, Path mappingsWorkingDir) { | ||||||
this.mappingsIdentifier = mappingsIdentifier; | ||||||
|
@@ -164,6 +165,11 @@ public TinyMappingsService getMappingsService(SharedServiceManager serviceManage | |||||
} | ||||||
|
||||||
public TinyMappingsService getMappingsService(SharedServiceManager serviceManager, MappingOption mappingOption) { | ||||||
if (extension.isForge() && extension.getForgeProvider().usesMojangAtRuntime() && mappingOption == MappingOption.WITH_MOJANG) { | ||||||
// Mojang mappings are merged into the SRG file. | ||||||
return getMappingsService(serviceManager, MappingOption.WITH_SRG); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
No need to recurse |
||||||
} | ||||||
|
||||||
final Path tinyMappings = switch (mappingOption) { | ||||||
case WITH_SRG -> { | ||||||
if (Files.notExists(this.tinyMappingsWithSrg)) { | ||||||
|
@@ -205,7 +211,7 @@ protected void setup(Project project, SharedServiceManager serviceManager, Minec | |||||
} | ||||||
|
||||||
public void setupPost(Project project) throws IOException { | ||||||
LoomGradleExtension extension = LoomGradleExtension.get(project); | ||||||
this.extension = LoomGradleExtension.get(project); | ||||||
|
||||||
if (extension.isNeoForge()) { | ||||||
// Generate the Mojmap-merged mappings if needed. | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
assert
here is a behaviour change (since this check needs assertions at runtime which are never enabled for Gradle probably?)