Skip to content

Commit

Permalink
Add a mod settings container to RunConfigSettings (#145)
Browse files Browse the repository at this point in the history
Closes #144.
  • Loading branch information
Juuxel committed Aug 12, 2023
1 parent 39426ac commit b084080
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,16 @@

import javax.inject.Inject;

import org.gradle.api.Action;
import org.gradle.api.Named;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
import org.jetbrains.annotations.ApiStatus;

import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.ModSettings;
import net.fabricmc.loom.configuration.providers.forge.ForgeRunTemplate;
import net.fabricmc.loom.configuration.providers.forge.ForgeRunsProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftSourceSets;
Expand Down Expand Up @@ -116,8 +119,11 @@ public class RunConfigSettings implements Named {

private final Project project;
private final LoomGradleExtension extension;

// Architectury
private final List<Runnable> evaluateLater = new ArrayList<>();
private boolean evaluated = false;
private final NamedDomainObjectContainer<ModSettings> mods;

@Inject
public RunConfigSettings(Project project, String name) {
Expand All @@ -130,6 +136,7 @@ public RunConfigSettings(Project project, String name) {
Objects.requireNonNull(defaultMainClass, "Run config " + name + " must specify default main class");
return RunConfig.getMainClass(environment, extension, defaultMainClass);
}));
this.mods = project.getObjects().domainObjectContainer(ModSettings.class);

setSource(p -> {
final String sourceSetName = MinecraftSourceSets.get(p).getSourceSetForEnv(getEnvironment());
Expand Down Expand Up @@ -385,7 +392,7 @@ public void forgeTemplate(String templateName) {
ForgeRunTemplate template = runsProvider.getTemplates().findByName(templateName);

if (template != null) {
template.applyTo(this, runsProvider);
template.applyTo(this, runsProvider.getResolver(this));
} else {
project.getLogger().warn("Could not find Forge run template with name '{}'", templateName);
}
Expand Down Expand Up @@ -422,4 +429,29 @@ public boolean isIdeConfigGenerated() {
public void setIdeConfigGenerated(boolean ideConfigGenerated) {
this.ideConfigGenerated = ideConfigGenerated;
}

/**
* {@return a container of mod settings for this run configuration}
*
* <p>If non-empty, this container will override the
* {@linkplain net.fabricmc.loom.api.LoomGradleExtensionAPI#getMods global container}
* declared in the {@code loom} extension.
*
* <p>This method is currently only available on Forge.
*/
@ApiStatus.Experimental
public NamedDomainObjectContainer<ModSettings> getMods() {
ModPlatform.assertPlatform(project, ModPlatform.FORGE);
return mods;
}

/**
* Configures the {@linkplain #getMods mods} of this run configuration.
*
* <p>This method is currently only available on Forge.
*/
@ApiStatus.Experimental
public void mods(Action<NamedDomainObjectContainer<ModSettings>> action) {
action.execute(getMods());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2022 FabricMC
* Copyright (c) 2022-2023 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -39,17 +39,20 @@
import com.google.common.collect.MultimapBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.NamedDomainObjectSet;
import org.gradle.api.Project;
import org.jetbrains.annotations.Nullable;

import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.api.ModSettings;
import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.DependencyDownloader;
import net.fabricmc.loom.util.gradle.SourceSetHelper;
import net.fabricmc.loom.util.gradle.SourceSetReference;

public class ForgeRunsProvider implements ConfigValue.Resolver {
public class ForgeRunsProvider {
private final Project project;
private final LoomGradleExtension extension;
private final JsonObject json;
Expand Down Expand Up @@ -79,8 +82,11 @@ public static ForgeRunsProvider create(Project project) {
return new ForgeRunsProvider(project, json);
}

@Override
public String resolve(ConfigValue.Variable variable) {
public ConfigValue.Resolver getResolver(@Nullable RunConfigSettings runConfig) {
return variable -> resolve(runConfig, variable);
}

private String resolve(@Nullable RunConfigSettings runConfig, ConfigValue.Variable variable) {
String key = variable.name();
String string = '{' + key + '}';

Expand Down Expand Up @@ -128,8 +134,13 @@ public String resolve(ConfigValue.Variable variable) {
} else if (key.equals("source_roots")) {
// Use a set-valued multimap for deduplicating paths.
Multimap<String, String> modClasses = MultimapBuilder.hashKeys().linkedHashSetValues().build();
NamedDomainObjectContainer<ModSettings> mods = extension.getMods();

if (runConfig != null && !runConfig.getMods().isEmpty()) {
mods = runConfig.getMods();
}

for (ModSettings mod : extension.getMods()) {
for (ModSettings mod : mods) {
// Note: In Forge 1.16.5, resources have to come first to find mods.toml
for (SourceSetReference modSourceSet : mod.getModSourceSets().get()) {
File resourcesDir = modSourceSet.sourceSet().getOutput().getResourcesDir();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,15 @@ public void run() throws IOException {
}

ForgeRunsProvider forgeRunsProvider = getExtension().getForgeRunsProvider();
ConfigValue.Resolver configResolver = forgeRunsProvider.getResolver(null);

for (ForgeRunTemplate template : forgeRunsProvider.getTemplates()) {
for (ConfigValue argument : template.args()) {
launchConfig.argument(template.name(), argument.resolve(forgeRunsProvider));
launchConfig.argument(template.name(), argument.resolve(configResolver));
}

for (Map.Entry<String, ConfigValue> property : template.props().entrySet()) {
launchConfig.property(template.name(), property.getKey(), property.getValue().resolve(forgeRunsProvider));
launchConfig.property(template.name(), property.getKey(), property.getValue().resolve(configResolver));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,55 @@ class ForgeRunConfigTest extends Specification implements GradleProjectTestTrait
'1.16.5' | "36.2.4" | 'net.minecraftforge.userdev.LaunchTesting'
'1.14.4' | "28.2.23" | 'net.minecraftforge.userdev.LaunchTesting'
}

def "verify mod classes"() {
setup:
def gradle = gradleProject(project: "forge/simple", version: DEFAULT_GRADLE)
gradle.buildGradle.text = gradle.buildGradle.text.replace('@MCVERSION@', '1.19.4')
.replace('@FORGEVERSION@', "45.0.43")
.replace('@MAPPINGS@', 'loom.officialMojangMappings()')
gradle.buildGradle << '''
sourceSets {
testMod {}
}
loom {
runs {
testMod {
client()
mods {
main { sourceSet 'main' }
testMod { sourceSet 'testMod' }
}
}
}
}
tasks.register('verifyRunConfigs') {
doLast {
def client = loom.runs.client
client.evaluateNow()
def clientClasses = client.environmentVariables.get('MOD_CLASSES')
if (!clientClasses.contains('main%%')) {
throw new AssertionError("MOD_CLASSES=clientClasses missing main classes")
} else if (clientClasses.contains('testMod%%')) {
throw new AssertionError("MOD_CLASSES=$clientClasses containing test mod classes")
}
def testMod = loom.runs.testMod
testMod.evaluateNow()
def testModClasses = testMod.environmentVariables.get('MOD_CLASSES')
if (!testModClasses.contains('main%%') || !testModClasses.contains('testMod%%')) {
throw new AssertionError("MOD_CLASSES=$testModClasses missing required entries")
}
}
}
'''.stripIndent()

when:
def result = gradle.run(task: "verifyRunConfigs")

then:
result.task(":verifyRunConfigs").outcome == SUCCESS
}
}

0 comments on commit b084080

Please sign in to comment.