Skip to content

Commit

Permalink
Configure a game directory for every version
Browse files Browse the repository at this point in the history
  • Loading branch information
3arthqu4ke committed Aug 24, 2024
1 parent 38fe5cf commit e3044d8
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import me.earth.headlessmc.launcher.download.DownloadService;
import me.earth.headlessmc.launcher.files.ConfigService;
import me.earth.headlessmc.launcher.files.FileManager;
import me.earth.headlessmc.launcher.files.LauncherConfig;
import me.earth.headlessmc.launcher.java.JavaService;
import me.earth.headlessmc.launcher.launch.ProcessFactory;
import me.earth.headlessmc.launcher.plugin.PluginManager;
Expand Down Expand Up @@ -39,13 +40,9 @@ public class Launcher implements HeadlessMc {
*/
private VersionService versionService;
/**
* The .minecraft directory in which we store assets, libraries and versions.
*/
private FileManager mcFiles;
/**
* The directory in which the game will run.
* The directories the HeadlessMc launcher will work in.
*/
private FileManager gameDir;
private final LauncherConfig launcherConfig;
/**
* A service for checking SHA1 hashes.
*/
Expand All @@ -54,10 +51,6 @@ public class Launcher implements HeadlessMc {
* A service for making GET requests.
*/
private DownloadService downloadService;
/**
* The directory for HeadlessMc files.
*/
private FileManager fileManager;
/**
* Actual Launching happens here.
*/
Expand All @@ -83,4 +76,50 @@ public class Launcher implements HeadlessMc {
*/
private PluginManager pluginManager;

/**
* The FileManager managing the HeadlessMc config, log and other files.
* This is a convenience method that calls {@link LauncherConfig} and by extension {@link ConfigService}.
*
* @return the FileManager managing the HeadlessMc config, log and other files.
* @see LauncherConfig
* @see ConfigService
*/
public FileManager getFileManager() {
return launcherConfig.getFileManager();
}

/**
* The .minecraft directory in which we store assets, libraries and versions.
* This is a convenience method that calls {@link LauncherConfig}.
*
* @return the .minecraft directory in which we store assets, libraries and versions.
* @see LauncherConfig
*/
public FileManager getMcFiles() {
return launcherConfig.getMcFiles();
}

/**
* Returns the default game directory.
*
* @return the default game directory.
* @deprecated call {@link #getGameDir(Version)} or {@link LauncherConfig#getGameDir(String)} instead.
*/
@Deprecated
public FileManager getGameDir() {
return launcherConfig.getGameDir();
}

/**
* Gets the directory to run the game in for a specific version.
* This is a convenience method that calls {@link LauncherConfig#getGameDir(Version)}.
*
* @param version the version to get a game directory for.
* @return a FileManager managing the game dir for this version.
* @see LauncherConfig#getGameDir(Version)
*/
public FileManager getGameDir(Version version) {
return launcherConfig.getGameDir(version);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@
import me.earth.headlessmc.launcher.command.LaunchContext;
import me.earth.headlessmc.launcher.download.ChecksumService;
import me.earth.headlessmc.launcher.download.DownloadService;
import me.earth.headlessmc.launcher.files.AutoConfiguration;
import me.earth.headlessmc.launcher.files.ConfigService;
import me.earth.headlessmc.launcher.files.FileManager;
import me.earth.headlessmc.launcher.files.MinecraftFinder;
import me.earth.headlessmc.launcher.files.*;
import me.earth.headlessmc.launcher.java.JavaService;
import me.earth.headlessmc.launcher.launch.ProcessFactory;
import me.earth.headlessmc.launcher.os.OS;
Expand Down Expand Up @@ -55,9 +52,8 @@ public class LauncherBuilder {
private CommandLine commandLine = new CommandLine();
private PluginManager pluginManager = new PluginManager();

private LauncherConfig launcherConfig;
private FileManager fileManager;
private FileManager mcFiles;
private FileManager gameDir;

private HeadlessMc headlessMc;
private VersionService versionService;
Expand Down Expand Up @@ -88,7 +84,7 @@ public LauncherBuilder runAutoConfiguration() {

public LauncherBuilder initConfigService() {
return ifNull(LauncherBuilder::configService, LauncherBuilder::configService,
() -> Service.refresh(new ConfigService(requireNonNull(this.fileManager, "FileManager not initialized"))));
() -> Service.refresh(new ConfigService(requireNonNull(this.fileManager, "FileManager not initialized"))));
}

public LauncherBuilder initHmcInstance() {
Expand All @@ -108,18 +104,19 @@ public LauncherBuilder configureDownloadService() {

public LauncherBuilder initDefaultServices() {
return ifNull(LauncherBuilder::os, LauncherBuilder::os, () -> OSFactory.detect(requireNonNull(configService, "ConfigHolder was null!").getConfig()))
.ifNull(LauncherBuilder::mcFiles, LauncherBuilder::mcFiles, () -> MinecraftFinder.find(configService.getConfig(), os))
.ifNull(LauncherBuilder::gameDir, LauncherBuilder::gameDir, () -> FileManager.mkdir(configService.getConfig().get(LauncherProperties.GAME_DIR, mcFiles.getPath())))
.ifNull(LauncherBuilder::versionService, LauncherBuilder::versionService, () -> new VersionService(mcFiles))
.ifNull(LauncherBuilder::javaService, LauncherBuilder::javaService, () -> new JavaService(configService));
.ifNull(LauncherBuilder::launcherConfig, LauncherBuilder::launcherConfig, () -> {
FileManager mcFiles = MinecraftFinder.find(configService.getConfig(), os);
FileManager gameDir = FileManager.mkdir(configService.getConfig().get(LauncherProperties.GAME_DIR, mcFiles.getPath()));
return new LauncherConfig(configService, mcFiles, gameDir);
})
.ifNull(LauncherBuilder::versionService, LauncherBuilder::versionService, () -> new VersionService(requireNonNull(launcherConfig(), "LauncherConfig!")))
.ifNull(LauncherBuilder::javaService, LauncherBuilder::javaService, () -> new JavaService(configService));
}

public LauncherBuilder initAccountManager() throws AuthException {
if (this.accountManager == null) {
FileManager fileManager = requireNonNull(this.fileManager, "FileManager was null!");
ConfigService configService = requireNonNull(this.configService, "ConfigHolder was null!");
AccountStore accountStore = new AccountStore(fileManager, configService);
this.accountManager = new AccountManager(new AccountValidator(), new OfflineChecker(configService), accountStore);
AccountStore accountStore = new AccountStore(requireNonNull(launcherConfig));
this.accountManager = new AccountManager(new AccountValidator(), new OfflineChecker(requireNonNull(configService)), accountStore);
accountManager.load(configService.getConfig());
}

Expand All @@ -128,8 +125,9 @@ public LauncherBuilder initAccountManager() throws AuthException {

public LauncherBuilder configureVersionSpecificModManager() {
if (this.versionSpecificModManager == null) {
FileManager fileManager = requireNonNull(this.fileManager, "FileManager was null!");
this.versionSpecificModManager = new VersionSpecificModManager(downloadService, fileManager.createRelative("specifics"));
requireNonNull(downloadService, "DownloadService was null!");
requireNonNull(launcherConfig, "LauncherConfig was null!");
this.versionSpecificModManager = new VersionSpecificModManager(downloadService, launcherConfig);
versionSpecificModManager.addRepository(VersionSpecificMods.HMC_SPECIFICS);
versionSpecificModManager.addRepository(VersionSpecificMods.MC_RUNTIME_TEST);
}
Expand All @@ -149,8 +147,7 @@ public LauncherBuilder configureProcessFactory() {
if (this.processFactory == null) {
this.processFactory = new ProcessFactory(
requireNonNull(downloadService, "Download Service was null!"),
requireNonNull(mcFiles, "McFiles were null!"),
requireNonNull(configService, "ConfigHolder was null!"),
requireNonNull(launcherConfig, "LauncherConfig was null!"),
requireNonNull(os, "OS was null!")
);
}
Expand All @@ -163,7 +160,7 @@ public LauncherBuilder deleteOldFiles() {
return this;
}

for (val file : requireNonNull(fileManager, "FileManager was null!").listFiles()) {
for (val file : requireNonNull(launcherConfig, "LauncherConfig was null!").getFileManager().listFiles()) {
if (file.isDirectory() && UuidUtil.isUuid(file.getName())) {
try {
log.debug("Deleting " + file.getAbsolutePath());
Expand Down Expand Up @@ -214,11 +211,9 @@ public Launcher build() {
return new Launcher(
requireNonNull(headlessMc, "HeadlessMc was null!"),
requireNonNull(versionService, "VersionService was null!"),
requireNonNull(mcFiles, "McFiles were null!"),
requireNonNull(gameDir, "GameDir was null!"),
requireNonNull(launcherConfig, "LauncherConfig was null!"),
requireNonNull(sha1Service, "Sha1Service was null!"),
requireNonNull(downloadService, "Download Service was null"),
requireNonNull(fileManager, "FileManager was null!"),
requireNonNull(processFactory, "ProcessFactory was null!"),
requireNonNull(configService, "ConfigService was null!"),
requireNonNull(javaService, "JavaService was null!"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,6 @@ public interface LauncherProperties extends HmcProperties {
Property<Boolean> HTTP_USER_AGENT_ENABLED = bool("hmc.http.user.agent.enabled");
Property<String> HTTP_USER_AGENT = string("hmc.http.user.agent");

Property<Boolean> GAME_DIR_FOR_EACH_VERSION = bool("hmc.game.dir.for.each.version");

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
import com.google.gson.JsonObject;
import lombok.CustomLog;
import lombok.RequiredArgsConstructor;
import me.earth.headlessmc.api.config.HasConfig;
import me.earth.headlessmc.launcher.LauncherProperties;
import me.earth.headlessmc.launcher.files.FileManager;
import me.earth.headlessmc.launcher.files.LauncherConfig;
import me.earth.headlessmc.launcher.util.JsonUtil;

import java.io.File;
Expand All @@ -21,11 +20,10 @@
@CustomLog
@RequiredArgsConstructor
public class AccountStore {
private final FileManager fileManager;
private final HasConfig cfg;
private final LauncherConfig launcherConfig;

public void save(List<ValidatedAccount> accounts) throws IOException {
if (!cfg.getConfig().get(LauncherProperties.STORE_ACCOUNTS, true)) {
if (!launcherConfig.getConfig().getConfig().get(LauncherProperties.STORE_ACCOUNTS, true)) {
return;
}

Expand All @@ -41,15 +39,15 @@ public void save(List<ValidatedAccount> accounts) throws IOException {

JsonObject object = new JsonObject();
object.add("accounts", array);
File file = fileManager.create("auth", ".accounts.json");
File file = launcherConfig.getFileManager().create("auth", ".accounts.json");
String string = JsonUtil.PRETTY_PRINT.toJson(object);
try (OutputStream os = Files.newOutputStream(file.toPath())) {
os.write(string.getBytes(StandardCharsets.UTF_8));
}
}

public List<ValidatedAccount> load() throws IOException {
File file = fileManager.create("auth", ".accounts.json");
File file = launcherConfig.getFileManager().create("auth", ".accounts.json");
JsonElement je = JsonUtil.fromFile(file);

JsonArray array = JsonUtil.getArray(je, "accounts");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public void execute(Version version, String... args) throws CommandException {

try {
ctx.getVersionSpecificModManager().download(version, repository);
ctx.getVersionSpecificModManager().deleteSpecificsOfOtherVersions(version, repository, ctx.getGameDir().getDir("mods").toPath());
ctx.getVersionSpecificModManager().install(version, repository, ctx.getGameDir().getDir("mods").toPath());
ctx.getVersionSpecificModManager().deleteSpecificsOfOtherVersions(version, repository, ctx.getGameDir(version).getDir("mods").toPath());
ctx.getVersionSpecificModManager().install(version, repository, ctx.getGameDir(version).getDir("mods").toPath());
} catch (IOException e) {
log.debug("Failed to install " + repository.getName() + " for version " + version.getName(), e);
throw new CommandException("Failed to install " + repository.getName() + " for version " + version.getName() + ": " + e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@
import java.util.Properties;

// TODO: for convenience we could add a 'hmc.' to every property
@Setter
@Getter
@CustomLog
@RequiredArgsConstructor
public class ConfigService extends Service<Config> implements HasConfig {
private static final String ENDING = ".properties";
private final FileManager fileManager;
@Getter
@Setter
private FileManager fileManager;
private Config config;

public ConfigService(FileManager fileManager) {
this.fileManager = fileManager;
}

@Override
protected List<Config> update() {
val result = new ArrayList<Config>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package me.earth.headlessmc.launcher.files;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import me.earth.headlessmc.launcher.LauncherProperties;
import me.earth.headlessmc.launcher.version.Version;
import org.jetbrains.annotations.Nullable;

/**
* Manages the directories the HeadlessMc Launcher will work in.
*/
@Getter
@Setter
@AllArgsConstructor
public class LauncherConfig {
/**
* Supplies the config to check the {@link LauncherProperties#GAME_DIR_FOR_EACH_VERSION} property from.
* Also supplies {@link #getFileManager()}.
*/
private ConfigService config;
/**
* The .minecraft directory in which we store assets, libraries and versions.
*/
private FileManager mcFiles;
/**
* The directory in which the game will run.
*/
private FileManager gameDir;

/**
* The directory HeadlessMc configuration files, logs and others reside in.
* Usually the folder HeadlessMC where the launcher has been started.
* This FileManager is usually supplied from the {@link #config}.
*
* @return The directory for HeadlessMc files.
* @see #setFileManager(FileManager)
*/
public FileManager getFileManager() {
return config.getFileManager();
}

/**
* Sets the FileManager to use for HeadlessMc.
*
* @param fileManager the new file manager to use.
* @see #getFileManager()
*/
public void setFileManager(FileManager fileManager) {
config.setFileManager(fileManager);
}

/**
* Gets the directory to run the game in for a specific version.
* Usually this is just {@link #gameDir}, but if {@link LauncherProperties#GAME_DIR_FOR_EACH_VERSION} is enabled,
* a game directory for each version will be created inside {@link #gameDir}.
*
* @param version the version to get a game directory for.
* @return a FileManager managing the game dir for this version.
*/
public FileManager getGameDir(Version version) {
return getGameDir(version.getName());
}

/**
* Gets the directory to run the game in for a specific name.
* Usually this is just {@link #gameDir}, but if {@link LauncherProperties#GAME_DIR_FOR_EACH_VERSION} is enabled,
* a relative directory for the given name will be created inside {@link #gameDir}.
* If name is {@code null} the default game directory will be used instead.
*
* @param name the name to get a game directory for.
* @return a FileManager managing the game dir for this version.
*/
public FileManager getGameDir(@Nullable String name) {
if (name != null && config.getConfig().get(LauncherProperties.GAME_DIR_FOR_EACH_VERSION, false)) {
return gameDir.createRelative(name);
}

return gameDir;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static ArgumentAdapter create(Launcher launcher, Version version, String

adapter.add("${version_name}", version.getName());
adapter.add("${version_type}", "release");
val dir = new File(config.get(LauncherProperties.GAME_DIR, launcher.getGameDir().getPath()));
val dir = new File(config.get(LauncherProperties.GAME_DIR, launcher.getGameDir(version).getPath()));
//noinspection ResultOfMethodCallIgnored
dir.mkdirs();

Expand Down
Loading

0 comments on commit e3044d8

Please sign in to comment.