diff --git a/.github/renovate.json b/.github/renovate.json index 9a1dd747..24daaacc 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -15,6 +15,16 @@ "DEFAULT_NFRT_VERSION\\s*=\\s*\"(?[\\d\\.\\-a-z]+)\"" ], "datasourceTemplate": "maven" + }, + { + "customType": "regex", + "fileMatch": [ + "RunUtils\\.java$" + ], + "matchStrings": [ + "String\\s+[A-Z_]+\\s*=\\s*\"(?[\\w:\\.-]+):(?[\\d\\.]+)(:(?[a-z]+))?\"\\s*;\\s*\\/\\/\\s*renovate" + ], + "datasourceTemplate": "maven" } ] } diff --git a/README.md b/README.md index 7d16ea34..583e2539 100644 --- a/README.md +++ b/README.md @@ -582,6 +582,26 @@ dependencies { } ``` +### Using Authenticated Minecraft Accounts +Minecraft runs normally use an offline user profile in a development environment. +If you want to run the game with your real user profile, you may do so using [DevLogin](https://github.com/covers1624/DevLogin) by setting +the `devLogin` property of a client run to `true`: + +```groovy +neoForge { + runs { + // Add a second client run that is authenticated + clientAuth { + client() + devLogin = true + } + } +} +``` + +The first time you launch the authenticated run you will be asked in the console to visit https://www.microsoft.com/link and enter +the given code. More information is available on the [DevLogin readme](https://github.com/covers1624/DevLogin) + ## Advanced Tips & Tricks ### Overriding Platform Libraries diff --git a/src/main/java/net/neoforged/moddevgradle/dsl/RunModel.java b/src/main/java/net/neoforged/moddevgradle/dsl/RunModel.java index 9bf0637d..d51b3dbe 100644 --- a/src/main/java/net/neoforged/moddevgradle/dsl/RunModel.java +++ b/src/main/java/net/neoforged/moddevgradle/dsl/RunModel.java @@ -56,6 +56,7 @@ public RunModel(String name, Project project, Iterable defaultMods) { }); getLogLevel().convention(Level.INFO); + getDevLogin().convention(false); // Build a nicer name for the IDE run configuration boolean isSubProject = project.getRootProject() != project; @@ -251,6 +252,12 @@ public Configuration getAdditionalRuntimeClasspathConfiguration() { */ public abstract Property getSourceSet(); + /** + * Enables DevLogin which is used to log into an + * official Minecraft account in development environments. + */ + public abstract Property getDevLogin(); + @Override public String toString() { return "Run[" + getName() + "]"; diff --git a/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java b/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java index 9fcad017..f28a2f91 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/ModDevPlugin.java @@ -56,6 +56,7 @@ import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Collectors; /** * The main plugin class. @@ -510,10 +511,13 @@ static void setupRuns(Project project, ) { var ideIntegration = IdeIntegration.of(project, branding); - // Create a configuration to resolve DevLaunch without leaking it to consumers + // Create a configuration to resolve DevLaunch and DevLogin without leaking them to consumers + var supplyDevLogin = project.provider(() -> runs.stream().anyMatch(model -> model.getDevLogin().get())); var devLaunchConfig = project.getConfigurations().create("devLaunchConfig", spec -> { - spec.setDescription("This configuration is used to inject DevLaunch into the runtime classpaths of runs."); + spec.setDescription("This configuration is used to inject DevLaunch and optionally DevLogin into the runtime classpaths of runs."); spec.getDependencies().add(project.getDependencyFactory().create(RunUtils.DEV_LAUNCH_GAV)); + spec.getDependencies().addAllLater(supplyDevLogin.map( + supply -> supply ? List.of(project.getDependencyFactory().create(RunUtils.DEV_LOGIN_GAV)) : List.of())); }); // Create an empty task similar to "assemble" which can be used to generate all launch scripts at once @@ -628,6 +632,7 @@ private static TaskProvider setupRunInGradle( task.getProgramArguments().set(run.getProgramArguments()); task.getJvmArguments().set(run.getJvmArguments()); task.getGameLogLevel().set(run.getLogLevel()); + task.getDevLogin().set(run.getDevLogin()); task.getVersionCapabilities().set(versionCapabilities); }); ideIntegration.runTaskOnProjectSync(prepareRunTask); diff --git a/src/main/java/net/neoforged/moddevgradle/internal/PrepareRunOrTest.java b/src/main/java/net/neoforged/moddevgradle/internal/PrepareRunOrTest.java index e50297ad..dc6cc7de 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/PrepareRunOrTest.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/PrepareRunOrTest.java @@ -104,11 +104,18 @@ abstract class PrepareRunOrTest extends DefaultTask { @Optional public abstract Property getVersionCapabilities(); + /** + * The property that decides whether DevLogin is enabled. + */ + @Input + public abstract Property getDevLogin(); + private final ProgramArgsFormat programArgsFormat; protected PrepareRunOrTest(ProgramArgsFormat programArgsFormat) { this.programArgsFormat = programArgsFormat; getVersionCapabilities().convention(VersionCapabilities.latest()); + getDevLogin().convention(false); } protected abstract UserDevRunType resolveRunType(UserDevConfig userDevConfig); @@ -153,8 +160,19 @@ public void prepareRun() throws IOException { runConfig = resolveRunType(userDevConfig); } - writeJvmArguments(runConfig); - writeProgramArguments(runConfig); + var mainClass = resolveMainClass(runConfig); + var devLogin = getDevLogin().get(); + + var sysProps = new LinkedHashMap(); + + // When DevLogin is used, we swap out the main class with the DevLogin one, and add the actual main class as a system property + if (devLogin && mainClass != null) { + sysProps.put("devlogin.launch_target", mainClass); + mainClass = RunUtils.DEV_LOGIN_MAIN_CLASS; + } + + writeJvmArguments(runConfig, sysProps); + writeProgramArguments(runConfig, mainClass); } private UserDevConfig loadUserDevConfig(File userDevFile) { @@ -208,7 +226,7 @@ private UserDevConfig getSimulatedUserDevConfigForVanilla() { return new UserDevConfig(runTypes); } - private void writeJvmArguments(UserDevRunType runConfig) throws IOException { + private void writeJvmArguments(UserDevRunType runConfig, Map additionalProperties) throws IOException { var lines = new ArrayList(); lines.addAll(getInterpolatedJvmArgs(runConfig)); @@ -238,7 +256,9 @@ private void writeJvmArguments(UserDevRunType runConfig) throws IOException { addSystemProp(prop.getKey(), propValue, lines); } - for (var entry : getSystemProperties().get().entrySet()) { + additionalProperties.putAll(getSystemProperties().get()); + + for (var entry : additionalProperties.entrySet()) { addSystemProp(entry.getKey(), entry.getValue(), lines); } @@ -250,10 +270,9 @@ private void writeJvmArguments(UserDevRunType runConfig) throws IOException { ); } - private void writeProgramArguments(UserDevRunType runConfig) throws IOException { + private void writeProgramArguments(UserDevRunType runConfig, @Nullable String mainClass) throws IOException { var lines = new ArrayList(); - var mainClass = resolveMainClass(runConfig); if (mainClass != null) { lines.add("# Main Class"); lines.add(mainClass); diff --git a/src/main/java/net/neoforged/moddevgradle/internal/RunUtils.java b/src/main/java/net/neoforged/moddevgradle/internal/RunUtils.java index aa9375a1..eb8fbce5 100644 --- a/src/main/java/net/neoforged/moddevgradle/internal/RunUtils.java +++ b/src/main/java/net/neoforged/moddevgradle/internal/RunUtils.java @@ -44,8 +44,10 @@ final class RunUtils { private RunUtils() { } - public static String DEV_LAUNCH_GAV = "net.neoforged:DevLaunch:1.0.1"; - public static String DEV_LAUNCH_MAIN_CLASS = "net.neoforged.devlaunch.Main"; + public static final String DEV_LAUNCH_GAV = "net.neoforged:DevLaunch:1.0.1"; // renovate + public static final String DEV_LAUNCH_MAIN_CLASS = "net.neoforged.devlaunch.Main"; + public static final String DEV_LOGIN_GAV = "net.covers1624:DevLogin:0.1.0.5"; // renovate + public static final String DEV_LOGIN_MAIN_CLASS = "net.covers1624.devlogin.DevLogin"; public static String escapeJvmArg(String arg) { var escaped = arg.replace("\\", "\\\\").replace("\"", "\\\""); diff --git a/testproject/build.gradle b/testproject/build.gradle index 44cdcbe5..3c718161 100644 --- a/testproject/build.gradle +++ b/testproject/build.gradle @@ -42,6 +42,10 @@ neoForge { client() programArguments.addAll('--username', 'Dev2') } + clientAuth { + client() + devLogin = true + } gradleOnlyClient { client() programArguments.addAll('--username', 'Dev3')