Refactor mods once again

This commit is contained in:
Johannes Frohnmeyer 2022-10-27 20:54:55 +02:00
parent 7e42e6b02f
commit ff7dddbd35
Signed by: Johannes
GPG Key ID: E76429612C2929F4
67 changed files with 641 additions and 509 deletions

View File

@ -5,7 +5,7 @@ All of these are subject to change, though automatic migrations will likely be p
## inceptum.json (Main Config)
```json
```json5
{
// Whether to show snapshots in the version selector for new instances
"snapshots": false,
@ -38,7 +38,7 @@ It stores your minecraft account login and CAN BE USED TO IMPERSONATE YOU!
Please note that all entries except for "version" are optional
```json
```json5
{
// The version to use for launching this
// Can be a fabric loader version (as seen here) or a normal minecraft version (like "1.17.1")
@ -74,7 +74,7 @@ Please note that all entries except for "version" are optional
## *.imod (Mod Metadata)
```json
```json5
{
// Where the JAR file for this mod can be obtained
"sources": [
@ -121,6 +121,8 @@ Please note that all entries except for "version" are optional
// A list of dependencies by their file names
"dependencies": [
"someOtherMod.imod"
]
],
// Whether this mod was explicitly installed (used during mod removal)
"explicit": true
}
```

View File

@ -1,11 +1,9 @@
package io.gitlab.jfronny.inceptum.cli;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -1,10 +1,8 @@
package io.gitlab.jfronny.inceptum.cli.commands;
import io.gitlab.jfronny.inceptum.cli.*;
import io.gitlab.jfronny.inceptum.common.R;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.export.Exporters;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import java.nio.file.Paths;

View File

@ -3,10 +3,10 @@ package io.gitlab.jfronny.inceptum.cli.commands;
import io.gitlab.jfronny.inceptum.cli.*;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.launch.*;
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import java.io.IOException;
import java.util.*;

View File

@ -5,8 +5,8 @@ import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.cli.Command;
import io.gitlab.jfronny.inceptum.cli.CommandArgs;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -4,15 +4,15 @@ import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.commons.throwable.ThrowingBiFunction;
import io.gitlab.jfronny.inceptum.cli.*;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.util.ModManager;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModManager;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import io.gitlab.jfronny.inceptum.launcher.util.Unchecked;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
@ -54,8 +54,8 @@ public class ModCommand extends Command {
}
System.out.println("Scanning installed mods, this might take a while");
instance.mds().runOnce((path, mod) -> {
boolean hasSources = mod.mod().isPresent() && !mod.mod().get().sources.isEmpty();
boolean updatable = hasSources && mod.mod().get().sources.values().stream().anyMatch(Optional::isPresent);
boolean hasSources = !mod.getMetadata().sources.isEmpty();
boolean updatable = hasSources && mod.getMetadata().sources.values().stream().anyMatch(Optional::isPresent);
if (filterUpdatable && !updatable) return;
System.out.println("- " + path.getFileName().toString());
System.out.println(" " + mod.getName());
@ -64,7 +64,7 @@ public class ModCommand extends Command {
}
if (hasSources) {
System.out.println(" Sources:");
for (Map.Entry<ModSource, Optional<ModSource>> entry : mod.mod().get().sources.entrySet()) {
for (Map.Entry<ModSource, Optional<ModSource>> entry : mod.getMetadata().sources.entrySet()) {
System.out.println(" - " + entry.getKey().getName() + " (" + entry.getKey().getVersion() + ")");
System.out.println(" Local: " + entry.getKey().getJarPath().toString());
if (entry.getValue().isPresent())
@ -116,7 +116,7 @@ public class ModCommand extends Command {
}
for (Path mod : mods) {
try {
ModManager.delete(instance, mds.get(mod));
mds.get(mod).delete();
} catch (IOException e) {
Utils.LOGGER.error("Could not delete " + mod, e);
return;
@ -166,35 +166,25 @@ public class ModCommand extends Command {
}
for (Path mod : mods) {
try {
Utils.LOGGER.info("Updating " + mod);
ModManager.delete(instance, mds.get(mod));
mds.get(mod).delete();
Mod md = mds.get(mod);
if (md.mod().isEmpty()) {
throw new IOException("Could not load mod description");
}
boolean found = false;
for (Map.Entry<ModSource, Optional<ModSource>> source : md.mod().get().sources.entrySet()) {
Optional<ModSource> ms = source.getValue();
if (ms.isPresent()) {
try {
Utils.LOGGER.info("Updating to " + ms.get().getVersion());
Path imodPath = md.imod().isPresent() ? md.imod().get() : instance.modsDir().resolve(ms.get().getShortName() + ModPath.EXT_IMOD);
ModManager.DownloadMeta dm = ModManager.download(ms.get(), imodPath, mds);
Files.delete(md.path());
if (md.imod().isPresent() && Files.exists(md.imod().get()))
Files.delete(md.imod().get());
dm.write();
mds.invalidate(imodPath);
Utils.LOGGER.info("Update completed");
found = true;
} catch (IOException e) {
throw new IOException("Update failed", e);
}
}
}
if (!found) Utils.LOGGER.error("Could not find any update");
md.getMetadata().sources.values().stream()
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst()
.ifPresentOrElse(update -> {
try {
Utils.LOGGER.info("Updating " + mod + " to " + update.getVersion());
md.update(update);
Utils.LOGGER.info("Update completed");
} catch (IOException e) {
throw new Unchecked(e);
}
}, () -> Utils.LOGGER.error("Could not find any update for " + mod));
} catch (IOException e) {
throw new IOException("Could not delete " + mod, e);
} catch (Unchecked e) {
throw new IOException("Could not delete " + mod, e.exception);
}
}
}

View File

@ -10,10 +10,10 @@ import io.gitlab.jfronny.inceptum.gtk.window.NewInstanceWindow;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import java.io.IOException;
import java.util.*;

View File

@ -5,7 +5,7 @@ import ch.bailu.gtk.bridge.ListIndex;
import ch.bailu.gtk.gtk.*;
import ch.bailu.gtk.pango.EllipsizeMode;
import ch.bailu.gtk.type.Str;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import java.util.List;

View File

@ -8,7 +8,7 @@ import ch.bailu.gtk.type.Str;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.gtk.GtkMenubar;
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import java.util.List;

View File

@ -2,7 +2,7 @@ package io.gitlab.jfronny.inceptum.gtk.control;
import ch.bailu.gtk.gtk.*;
import ch.bailu.gtk.type.*;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
public class InstanceThumbnail extends Stack {
private static final Str SPINNER = new Str("spinner");

View File

@ -14,8 +14,8 @@ import io.gitlab.jfronny.inceptum.gtk.control.InstanceGridEntryFactory;
import io.gitlab.jfronny.inceptum.gtk.control.InstanceListEntryFactory;
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder;
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import java.io.IOException;
import java.net.URI;

View File

@ -5,17 +5,14 @@ import imgui.ImGuiIO;
import imgui.flag.ImGuiConfigFlags;
import imgui.gl3.ImGuiImplGl3;
import imgui.glfw.ImGuiImplGlfw;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.commons.log.*;
import io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateMetadata;
import io.gitlab.jfronny.inceptum.imgui.window.MainWindow;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.imgui.window.Window;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.*;

View File

@ -7,12 +7,12 @@ import io.gitlab.jfronny.commons.tuple.Tuple;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.imgui.window.GuiUtil;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceNameTool;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceNameTool;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;

View File

@ -5,10 +5,10 @@ import imgui.flag.ImGuiTableFlags;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.imgui.GuiMain;
import io.gitlab.jfronny.inceptum.imgui.window.edit.InstanceEditWindow;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -6,21 +6,18 @@ import imgui.type.ImString;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeMod;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.*;
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
import io.gitlab.jfronny.inceptum.launcher.util.ModManager;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModManager;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import io.gitlab.jfronny.inceptum.launcher.api.CurseforgeApi;
import io.gitlab.jfronny.inceptum.launcher.api.ModrinthApi;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.util.List;
public class AddModWindow extends Window {
@ -90,8 +87,7 @@ public class AddModWindow extends Window {
ImGui.tableNextColumn();
boolean alreadyPresent = false;
for (Mod mdsMod : instance.getMods()) {
alreadyPresent = mdsMod.mod().isPresent()
&& mdsMod.mod().get().sources.keySet().stream()
alreadyPresent = mdsMod.getMetadata().sources.keySet().stream()
.anyMatch(s -> s instanceof ModrinthModSource ms
&& ms.getModId().equals(mod.project_id));
if (alreadyPresent)
@ -166,8 +162,7 @@ public class AddModWindow extends Window {
ImGui.tableNextColumn();
boolean alreadyPresent = false;
for (Mod mdsMod : instance.mds().getMods()) {
alreadyPresent = mdsMod.mod().isPresent()
&& mdsMod.mod().get().sources.keySet().stream()
alreadyPresent = mdsMod.getMetadata().sources.keySet().stream()
.anyMatch(s -> s instanceof CurseforgeModSource ms
&& ms.getProjectId() == mod.id);
if (alreadyPresent)

View File

@ -6,9 +6,9 @@ import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.imgui.GuiMain;
import io.gitlab.jfronny.inceptum.imgui.window.dialog.ProcessStateWatcherWindow;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.install.*;
import io.gitlab.jfronny.inceptum.launcher.util.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.setup.*;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import java.io.IOException;

View File

@ -8,8 +8,8 @@ import io.gitlab.jfronny.inceptum.imgui.control.InstanceManageControls;
import io.gitlab.jfronny.inceptum.imgui.window.dialog.ProcessStateWatcherWindow;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.launcher.system.importer.Importers;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import java.io.IOException;

View File

@ -7,12 +7,11 @@ import io.gitlab.jfronny.inceptum.imgui.control.Tab;
import io.gitlab.jfronny.inceptum.imgui.window.dialog.ProcessStateWatcherWindow;
import io.gitlab.jfronny.inceptum.imgui.window.dialog.TextBoxWindow;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.launcher.system.export.Exporter;
import io.gitlab.jfronny.inceptum.launcher.system.export.Exporters;
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporter;
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ExportTab extends Tab {
private final InstanceEditWindow window;

View File

@ -4,7 +4,7 @@ import imgui.ImGui;
import io.gitlab.jfronny.inceptum.imgui.control.Tab;
import io.gitlab.jfronny.inceptum.imgui.window.GuiUtil;
import io.gitlab.jfronny.inceptum.imgui.window.Window;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import java.io.IOException;
import java.util.List;

View File

@ -7,9 +7,9 @@ import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.imgui.GuiMain;
import io.gitlab.jfronny.inceptum.imgui.control.Tab;
import io.gitlab.jfronny.inceptum.imgui.window.AddModWindow;
import io.gitlab.jfronny.inceptum.launcher.util.ModManager;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModManager;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import java.io.IOException;
@ -59,10 +59,9 @@ public class ModsTab extends Tab {
float scannedPercentage = 0;
boolean hasUnScanned = false;
for (Mod mod : modSet) {
if (window.instance.mds().hasScanned(mod.path())) scannedPercentage++;
if (window.instance.mds().hasScanned(mod)) scannedPercentage++;
else hasUnScanned = true;
if (mod.mod().isEmpty()) continue;
for (Optional<ModSource> value : mod.mod().get().sources.values()) {
for (Optional<ModSource> value : mod.getMetadata().sources.values()) {
if (value.isPresent()) {
updatesFound = true;
break;
@ -80,25 +79,21 @@ public class ModsTab extends Tab {
ImGui.separator();
for (Mod mod : modSet) {
updatesFound = false;
if (mod.mod().isPresent()) {
for (Optional<ModSource> value : mod.mod().get().sources.values()) {
updatesFound |= value.isPresent();
}
for (Optional<ModSource> value : mod.getMetadata().sources.values()) {
updatesFound |= value.isPresent();
}
if (filterUpdates.get() && !updatesFound) continue;
boolean wasEnabled = ModPath.isEnabled(mod.path());
if (ImGui.checkbox("##" + mod.getName(), wasEnabled)) {
Path newSel = ModPath.toggle(mod.path());
if (ImGui.checkbox("##" + mod.getName(), mod.isEnabled())) {
Path newSel = ModPath.toggle(mod.getMetadataPath());
try {
Files.move(mod.path(), newSel);
if (mod.path().equals(selected)) selected = newSel;
mod = new Mod(newSel, mod);
Files.move(mod.getMetadataPath(), newSel);
if (mod.getMetadataPath().equals(selected)) selected = newSel;
} catch (IOException e) {
LauncherEnv.showError("Could not change disabled state", e);
}
}
ImGui.sameLine();
if (ImGui.button(mod.getName())) selected = mod.path();
if (ImGui.button(mod.getName())) selected = mod.getMetadataPath();
}
} catch (IOException e) {
Utils.LOGGER.error("Could not show mod list", e);
@ -116,41 +111,31 @@ public class ModsTab extends Tab {
ImGui.text(s);
}
ImGui.separator();
if (md.mod().isPresent()) {
Map<ModSource, Optional<ModSource>> sources = md.mod().get().sources;
ImGui.text("Sources:");
if (sources.isEmpty())
ImGui.bulletText("Local Drive");
else {
for (Map.Entry<ModSource, Optional<ModSource>> source : sources.entrySet()) {
ImGui.bulletText(source.getKey().getName());
Optional<ModSource> ms = source.getValue();
if (ms.isPresent()) {
ImGui.sameLine();
if (ImGui.button("Update to " + ms.get().getVersion())) {
try {
Path imodPath = md.imod().isPresent() ? md.imod().get() : window.instance.modsDir().resolve(ms.get().getShortName() + ModPath.EXT_IMOD);
ModManager.DownloadMeta dm = ModManager.download(ms.get(), imodPath, window.instance.mds());
Files.delete(md.path());
if (md.imod().isPresent() && Files.exists(md.imod().get()))
Files.delete(md.imod().get());
dm.write();
selected = imodPath;
window.instance.mds().invalidate(imodPath);
} catch (IOException e) {
LauncherEnv.showError("Update failed", e);
}
Map<ModSource, Optional<ModSource>> sources = md.getMetadata().sources;
ImGui.text("Sources:");
if (sources.isEmpty())
ImGui.bulletText("Local Drive");
else {
for (Map.Entry<ModSource, Optional<ModSource>> source : sources.entrySet()) {
ImGui.bulletText(source.getKey().getName());
source.getValue().ifPresent(update -> {
ImGui.sameLine();
if (ImGui.button("Update to " + update.getVersion())) {
try {
selected = md.update(update);
} catch (IOException e) {
LauncherEnv.showError("Update failed", e);
}
}
}
});
}
}
if (ImGui.button("Delete")) {
if (md.mod().isPresent() && !md.mod().get().dependents.isEmpty())
LauncherEnv.showError("This mod still has the following dependent mods installed: " + String.join(", ", md.mod().get().dependents), "Dependents present");
if (!md.getMetadata().dependents.isEmpty())
LauncherEnv.showError("This mod still has the following dependent mods installed: " + String.join(", ", md.getMetadata().dependents), "Dependents present");
else {
try {
delete(md);
md.delete();
} catch (IOException e) {
LauncherEnv.showError("Couldn't delete the file", e);
}
@ -163,10 +148,6 @@ public class ModsTab extends Tab {
ImGui.endGroup();
}
private void delete(Mod md) throws IOException {
ModManager.delete(window.instance, md);
}
@Override
protected boolean canShow() {
return window.instance.isFabric();

View File

@ -4,8 +4,8 @@ import io.gitlab.jfronny.gson.reflect.TypeToken;
import io.gitlab.jfronny.inceptum.common.Net;
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
import java.io.IOException;
import java.lang.reflect.Type;
@ -53,7 +53,7 @@ public class FabricMetaApi {
floader.name = ver.intermediary.maven;
libs.add(convertLib(floader));
result.libraries = List.copyOf(libs);
result.id = InstanceMeta.floaderPrefix + fabricVersion + "-" + version.id;
result.id = GameVersionParser.floaderPrefix + fabricVersion + "-" + version.id;
return result;
}

View File

@ -1,13 +1,9 @@
package io.gitlab.jfronny.inceptum.launcher.model.inceptum;
import io.gitlab.jfronny.commons.serialize.gson.api.Ignore;
import java.util.List;
import java.util.Objects;
public class InstanceMeta {
@Ignore
public static final String floaderPrefix = "fabric-loader-";
public String version;
public String java;
public Long minMem;
@ -15,22 +11,6 @@ public class InstanceMeta {
public Long lastLaunched;
public Arguments arguments;
public boolean isFabric() {
return version.startsWith(floaderPrefix);
}
public String getMinecraftVersion() {
return getMinecraftVersion(version);
}
public static String getMinecraftVersion(String id) {
return id.startsWith(floaderPrefix) ? id.substring(id.lastIndexOf('-') + 1) : id;
}
public String getLoaderVersion() {
return isFabric() ? version.substring(floaderPrefix.length()).split("-")[0] : "";
}
public static class Arguments {
public List<String> jvm;
public List<String> client;

View File

@ -14,12 +14,13 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
public class ModDescription {
public class ModMeta {
public Map<ModSource, Optional<ModSource>> sources; //key: source, value: update
public String sha1;
public Long murmur2;
public List<String> dependents; // by file name
public List<String> dependencies; // by file name
public boolean explicit = true;
public boolean initialize(String gameVersion) {
boolean modrinth = false;
@ -53,23 +54,25 @@ public class ModDescription {
return changed;
}
public static ModDescription of(Path mod) {
ModDescription res = new ModDescription();
public static ModMeta of(Path mod) {
ModMeta res = new ModMeta();
res.sources = new LinkedHashMap<>();
try {
byte[] data = Files.readAllBytes(mod);
res.sha1 = HashUtils.sha1(data);
res.murmur2 = HashUtils.murmur2(data);
} catch (IOException e) {
Utils.LOGGER.error("Could not read file hash", e);
if (!Files.isDirectory(mod)) {
try {
byte[] data = Files.readAllBytes(mod);
res.sha1 = HashUtils.sha1(data);
res.murmur2 = HashUtils.murmur2(data);
} catch (IOException e) {
Utils.LOGGER.error("Could not read file hash", e);
}
}
res.dependents = new ArrayList<>();
res.dependencies = new ArrayList<>();
return res;
}
public static ModDescription of(String sha1, Long murmur2, @Nullable ModSource knownSource, String gameVersion) {
ModDescription res = new ModDescription();
public static ModMeta of(String sha1, Long murmur2, @Nullable ModSource knownSource, String gameVersion) {
ModMeta res = new ModMeta();
res.sources = new LinkedHashMap<>();
res.sha1 = sha1;
res.murmur2 = murmur2;

View File

@ -1,68 +0,0 @@
package io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModDescription;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
public record Mod(Path path, Optional<ModDescription> mod, Optional<FabricModJson> fmj, Optional<Path> imod) implements Comparable<Mod> {
public String getName() {
if (fmj.isEmpty()) return path.getFileName().toString();
String base;
if (fmj.get().name != null) base = fmj.get().name;
else if (fmj.get().id != null) base = fmj.get().id;
else {
base = path.getFileName().toString();
if (Files.isDirectory(path))
base += '/';
}
if (fmj.get().version != null) base += ' ' + fmj.get().version;
return base;
}
public String[] getDescription() {
try {
if (fmj.isPresent() && fmj.get().description != null) {
return fmj.get().description.split("\n");
} else if (Files.isDirectory(path)) {
return JFiles.listNames(path);
}
} catch (IOException e) {
Utils.LOGGER.error("Could not get description", e);
}
return new String[]{"No description is available", "This mod may have been added manually"};
}
/**
* Generates a description with only the path and no additional information
*
* @param path The path of the mod entry
*/
public Mod(Path path) {
this(path,
Files.isDirectory(path) ? Optional.empty() : Optional.of(ModDescription.of(path)),
Optional.empty(),
ModPath.hasImod(path) ? Optional.of(ModPath.appendImod(path)) : Optional.empty());
}
/**
* Generates a new mod description based on an existing one with an adjusted path
*
* @param path The new path to use
* @param base The mod description to copy
*/
public Mod(Path path, Mod base) {
this(path, base.mod, base.fmj, base.imod);
}
@Override
public int compareTo(Mod o) {
return getName().compareTo(o.getName());
}
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.system.export;
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
import io.gitlab.jfronny.commons.io.JFiles;

View File

@ -1,14 +1,13 @@
package io.gitlab.jfronny.inceptum.launcher.system.export;
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.InceptumConfig;
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeModpackManifest;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.source.CurseforgeModSource;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -48,26 +47,18 @@ public class CurseForgeExporter extends Exporter<CurseforgeModpackManifest> {
@Override
protected void addMods(Path root, Instance instance, Iterable<Mod> mods, CurseforgeModpackManifest manifest, Path modsOverrides) throws IOException {
modsLoop: for(Mod mod : mods) {
if (ModPath.isImod(mod.path())) {
Set<ModSource> sources = mod.mod().orElseThrow().sources.keySet();
if (mod.needsInject()) {
Set<ModSource> sources = mod.getMetadata().sources.keySet();
for (ModSource source : sources) {
if (source instanceof CurseforgeModSource cms) {
manifest.files.add(cms.toManifest());
continue modsLoop;
}
}
// Not available on CF
for (ModSource source : sources) {
Files.createDirectories(modsOverrides);
Files.copy(source.getJarPath(), modsOverrides.resolve(mod.path().getFileName().toString()));
continue modsLoop;
}
} else {
Files.createDirectories(modsOverrides);
Files.copy(mod.path(), modsOverrides.resolve(mod.path().getFileName().toString()));
continue modsLoop;
}
throw new FileNotFoundException("Could not find mod file for " + mod.path());
// Not available on CF
Files.createDirectories(modsOverrides);
Files.copy(mod.getJarPath(), modsOverrides.resolve(mod.getJarPath().getFileName().toString()));
}
JFiles.writeObject(root.resolve("manifest.json"), manifest);
}

View File

@ -1,12 +1,9 @@
package io.gitlab.jfronny.inceptum.launcher.system.export;
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
import io.gitlab.jfronny.inceptum.launcher.util.*;
import io.gitlab.jfronny.inceptum.launcher.util.ignore.IgnoringWalk;
import io.gitlab.jfronny.inceptum.launcher.util.gitignore.IgnoringWalk;
import java.io.IOException;
import java.net.URISyntaxException;
@ -37,8 +34,8 @@ public abstract class Exporter<Manifest> {
if (instance.isFabric()) {
state.incrementStep("Adding mods");
addMods(root, instance, new StreamIterable<>(instance.getMods().stream().filter(mod -> {
if (!ModPath.isEnabled(mod.path())) return false;
state.updateStep(mod.path().toString());
if (!mod.isEnabled()) return false;
state.updateStep(mod.getName());
return true;
})), manifest, overrides.resolve("mods"));
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.system.export;
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
import java.util.List;

View File

@ -1,13 +1,12 @@
package io.gitlab.jfronny.inceptum.launcher.system.export;
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.modrinth.ModrinthModpackManifest;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModrinthModSource;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -41,26 +40,18 @@ public class ModrinthExporter extends Exporter<ModrinthModpackManifest> {
@Override
protected void addMods(Path root, Instance instance, Iterable<Mod> mods, ModrinthModpackManifest manifest, Path modsOverrides) throws IOException {
modsLoop: for(Mod mod : mods) {
if (ModPath.isImod(mod.path())) {
Set<ModSource> sources = mod.mod().orElseThrow().sources.keySet();
if (mod.needsInject()) {
Set<ModSource> sources = mod.getMetadata().sources.keySet();
for (ModSource source : sources) {
if (source instanceof ModrinthModSource cms) {
manifest.files.add(cms.toManifest());
continue modsLoop;
}
}
// Not available on modrinth
for (ModSource source : sources) {
Files.createDirectories(modsOverrides);
Files.copy(source.getJarPath(), modsOverrides.resolve(mod.path().getFileName().toString()));
continue modsLoop;
}
} else {
Files.createDirectories(modsOverrides);
Files.copy(mod.path(), modsOverrides.resolve(mod.path().getFileName().toString()));
continue modsLoop;
}
throw new FileNotFoundException("Could not find mod file for " + mod.path());
// Not available on modrinth
Files.createDirectories(modsOverrides);
Files.copy(mod.getJarPath(), modsOverrides.resolve(mod.getJarPath().getFileName().toString()));
}
JFiles.writeObject(root.resolve("modrinth.index.json"), manifest);
}

View File

@ -1,12 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.system.export;
package io.gitlab.jfronny.inceptum.launcher.system.exporter;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.multimc.MMCPackMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -82,20 +81,7 @@ public class MultiMCExporter extends Exporter<MMCPackMeta> {
@Override
protected void addMods(Path root, Instance instance, Iterable<Mod> mods, MMCPackMeta mmcPackMeta, Path modsOverrides) throws IOException {
modsLoop: for (Mod mod : mods) {
if (ModPath.isImod(mod.path())) {
Set<ModSource> sources = mod.mod().orElseThrow().sources.keySet();
for (ModSource source : sources) {
Files.createDirectories(modsOverrides);
Files.copy(source.getJarPath(), modsOverrides.resolve(mod.path().getFileName().toString()));
continue modsLoop;
}
} else {
Files.createDirectories(modsOverrides);
Files.copy(mod.path(), modsOverrides.resolve(mod.path().getFileName().toString()));
continue modsLoop;
}
throw new FileNotFoundException("Could not find mod file for " + mod.path());
}
Files.createDirectories(modsOverrides);
for (Mod mod : mods) Files.copy(mod.getJarPath(), modsOverrides.resolve(mod.getJarPath().getFileName().toString()));
}
}

View File

@ -2,7 +2,8 @@ package io.gitlab.jfronny.inceptum.launcher.system.importer;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.CurseforgeModpackManifest;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModDescription;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
import io.gitlab.jfronny.inceptum.launcher.util.*;
@ -42,7 +43,7 @@ public class CurseForgeImporter extends Importer<CurseforgeModpackManifest> {
CurseforgeModSource source = new CurseforgeModSource(file.projectID, file.fileID);
state.updateStep("Downloading " + source.getName());
ModDownload download = source.download();
ModDescription imod = ModDescription.of(download.sha1(), download.murmur2(), source, manifest.minecraft.version);
ModMeta imod = ModMeta.of(download.sha1(), download.murmur2(), source, manifest.minecraft.version);
Files.createDirectories(modsPath);
JFiles.writeObject(modsPath.resolve(source.getShortName() + ModPath.EXT_IMOD), imod);
}

View File

@ -6,8 +6,8 @@ import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import io.gitlab.jfronny.inceptum.launcher.util.*;
import org.jetbrains.annotations.Nullable;
@ -41,7 +41,7 @@ public abstract class Importer<T> {
return gameVersion;
} else {
FabricMetaApi.getLoaderVersion(gameVersion, fabricVersion);
return InstanceMeta.floaderPrefix + fabricVersion + '-' + gameVersion;
return GameVersionParser.floaderPrefix + fabricVersion + '-' + gameVersion;
}
}

View File

@ -1,7 +1,7 @@
package io.gitlab.jfronny.inceptum.launcher.system.importer;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.system.install.Steps;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import java.io.IOException;

View File

@ -1,10 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt;
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.R;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessUtils;
import org.jetbrains.annotations.NotNull;
@ -81,7 +82,15 @@ public record Instance(String id, Path path, InstanceMeta meta, ModsDirScanner m
}
public boolean isFabric() {
return meta.isFabric();
return GameVersionParser.isFabric(meta.version);
}
public String getMinecraftVersion() {
return GameVersionParser.getMinecraftVersion(meta.version);
}
public String getLoaderVersion() {
return GameVersionParser.getLoaderVersion(meta.version);
}
public boolean isSetupLocked() {

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util;
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.commons.cache.FileBackedRef;
import io.gitlab.jfronny.commons.io.JFiles;
@ -6,7 +6,7 @@ import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import java.io.Closeable;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util;
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.inceptum.common.MetaHolder;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt;
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricLoaderVersion;

View File

@ -0,0 +1,37 @@
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Set;
public abstract class Mod implements Comparable<Mod> {
public abstract String getName();
public abstract String[] getDescription();
public abstract boolean needsInject();
public abstract Path getJarPath();
public abstract Path getMetadataPath();
public abstract void delete() throws IOException;
public abstract Path update(ModSource update) throws IOException;
public abstract Set<Mod> getDependencies();
public abstract Set<Mod> getDependents();
public abstract void removeDependency(Mod dependency) throws IOException;
public abstract void removeDependent(Mod dependent) throws IOException;
public abstract ModMeta getMetadata();
public abstract boolean isEnabled();
@Override
public int compareTo(@NotNull Mod mod) {
return getName().compareTo(mod.getName());
}
@Override
public String toString() {
return getName();
}
}

View File

@ -0,0 +1,37 @@
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModDownload;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import java.io.IOException;
import java.nio.file.Path;
public class ModManager {
public static DownloadMeta download(ModSource ms, Path metaFile, ModsDirScanner mds) throws IOException {
for (Mod value : mds.getMods()) {
for (ModSource source : value.getMetadata().sources.keySet()) {
if (ms.equals(source)) {
return new DownloadMeta(new ModDownload(value.getMetadata().sha1, value.getMetadata().murmur2, value.getJarPath()), value.getMetadata(), source, metaFile);
}
}
}
ModDownload md = ms.download();
ModMeta manifest = ModMeta.of(md.sha1(), md.murmur2(), ms, mds.getGameVersion());
for (ModSource depSrc : ms.getDependencies(mds.getGameVersion())) {
DownloadMeta depMeta = download(depSrc, metaFile.getParent().resolve(depSrc.getShortName() + ModPath.EXT_IMOD), mds);
depMeta.meta.dependents.add(metaFile.getFileName().toString());
manifest.dependencies.add(depMeta.metaFile.getFileName().toString());
depMeta.write();
}
return new DownloadMeta(md, manifest, ms, metaFile);
}
public record DownloadMeta(ModDownload download, ModMeta meta, ModSource source, Path metaFile) {
public void write() throws IOException {
JFiles.writeObject(metaFile, meta);
}
}
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util;
package io.gitlab.jfronny.inceptum.launcher.system.instance;
import io.gitlab.jfronny.inceptum.common.Utils;

View File

@ -6,13 +6,14 @@ import io.gitlab.jfronny.inceptum.common.api.MavenApi;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.*;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.launcher.api.account.AuthInfo;
import io.gitlab.jfronny.inceptum.launcher.system.install.steps.DownloadLibrariesStep;
import io.gitlab.jfronny.inceptum.launcher.system.setup.steps.DownloadLibrariesStep;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import io.gitlab.jfronny.inceptum.launcher.util.*;
@ -105,7 +106,7 @@ public class InstanceLauncher {
String fn = imod.getFileName().toString();
if (Files.exists(imod.getParent().resolve(fn.substring(0, fn.length() - 5))))
continue;
Map<ModSource, Optional<ModSource>> sources = JFiles.readObject(imod, ModDescription.class).sources;
Map<ModSource, Optional<ModSource>> sources = JFiles.readObject(imod, ModMeta.class).sources;
if (sources.isEmpty()) throw new LaunchException(".imod without attached jar contains no sources");
ModSource ms = List.copyOf(sources.keySet()).get(0);
Path p = ms.getJarPath().toAbsolutePath();

View File

@ -1,93 +1,73 @@
package io.gitlab.jfronny.inceptum.launcher.system.mds;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.commons.throwable.ThrowingConsumer;
import io.gitlab.jfronny.gson.JsonParseException;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModDescription;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.noop.NoopMod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import org.jetbrains.annotations.Nullable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.*;
public record FileScanTask(Path file, BiConsumer<Path, Mod> discovered,
String gameVersion) implements Runnable {
public record FileScanTask(ProtoInstance instance, Path file, BiConsumer<Path, Mod> discovered, String gameVersion) implements Runnable {
@Override
public void run() {
if (!Files.exists(file)) return;
if (Files.isDirectory(file)) {
discovered.accept(file, new Mod(file));
return;
}
if (Files.isDirectory(file)) return; // Directories are not supported
try {
if (ModPath.isJar(file)) {
final var imod = new Object() {
Path i = file.getParent().resolve(file.getFileName() + ModPath.EXT_IMOD);
ModDescription md;
};
// mod description
if (!Files.exists(imod.i)) {
JFiles.writeObject(imod.i, ModDescription.of(file));
}
imod.md = JFiles.readObject(imod.i, ModDescription.class);
evaluateSources(imod.md, file, imod.i, newImod -> {
imod.i = newImod;
imod.md = JFiles.readObject(imod.i, ModDescription.class);
});
discovered.accept(imod.i, new Mod(file, Optional.of(imod.md), getFmj(file, imod.md), Optional.of(imod.i)));
return;
}
if (ModPath.isImod(file)) {
final MetadataRef imod = new MetadataRef(file.getParent().resolve(file.getFileName() + ModPath.EXT_IMOD), ModMeta::of);
evaluateSources(file, imod);
discovered.accept(imod.imodPath, new MdsMod(instance, imod.imodPath, file, false, imod.meta, getFmj(file, imod.meta)));
} else if (ModPath.isImod(file)) {
String fn = file.getFileName().toString();
Path modFile = file.getParent().resolve(fn.substring(0, fn.length() - ModPath.EXT_IMOD.length()));
final var imod = new Object() {
Path i = file;
ModDescription md = JFiles.readObject(file, ModDescription.class);
};
evaluateSources(imod.md, modFile, imod.i, newImod -> {
imod.i = newImod;
imod.md = JFiles.readObject(imod.i, ModDescription.class);
});
discovered.accept(imod.i, new Mod(imod.i, Optional.of(imod.md), getFmj(modFile, imod.md), Optional.of(imod.i)));
return;
}
discovered.accept(file, new Mod(file));
final MetadataRef imod = new MetadataRef(file, null);
evaluateSources(modFile, imod);
boolean managedJar = !Files.exists(modFile);
discovered.accept(imod.imodPath, new MdsMod(instance, imod.imodPath, managedJar ? imod.jarPath : modFile, managedJar, imod.meta, getFmj(modFile, imod.meta)));
} else discovered.accept(file, new NoopMod(file));
} catch (IOException | URISyntaxException | JsonParseException e) {
Utils.LOGGER.error("Could not scan file for mod info", e);
}
}
private <TEx extends Throwable> void evaluateSources(ModDescription md, Path modFile, Path imodFile, ThrowingConsumer<Path, TEx> imodModified) throws IOException, TEx {
private <TEx extends Throwable> void evaluateSources(Path modFile, MetadataRef ref) throws IOException, TEx {
boolean modified = false;
if (md.initialize(gameVersion)) {
JFiles.writeObject(imodFile, md);
if (ref.meta.initialize(gameVersion)) {
JFiles.writeObject(ref.imodPath, ref.meta);
modified = true;
}
ModSource selectedSource = null;
for (ModSource source : md.sources.keySet()) {
for (ModSource source : ref.meta.sources.keySet()) {
source.getUpdate(gameVersion);
if (!Files.exists(source.getJarPath())) source.download();
selectedSource = source;
}
if (selectedSource != null && Files.exists(modFile)) {
Files.delete(modFile);
Path newImod = imodFile.getParent().resolve(selectedSource.getShortName() + ModPath.EXT_IMOD);
Files.move(imodFile, newImod);
imodFile = newImod;
modified = true;
if (selectedSource != null) {
if (Files.exists(modFile)) {
Files.delete(modFile);
Path newImod = ref.imodPath.getParent().resolve(selectedSource.getShortName() + ModPath.EXT_IMOD);
Files.move(ref.imodPath, newImod);
ref.imodPath = newImod;
modified = true;
}
ref.jarPath = selectedSource.getJarPath();
}
if (modified) imodModified.accept(imodFile);
if (modified) ref.update();
}
private Optional<FabricModJson> getFmj(Path modJarDefault, ModDescription md) throws IOException, URISyntaxException {
private @Nullable FabricModJson getFmj(Path modJarDefault, ModMeta md) throws IOException, URISyntaxException {
if (!Files.exists(modJarDefault)) {
if (md.sources.isEmpty()) {
throw new FileNotFoundException("Mod " + modJarDefault.getFileName().toString() + " doesn't specify a source and has no file");
@ -95,9 +75,25 @@ public record FileScanTask(Path file, BiConsumer<Path, Mod> discovered,
modJarDefault = List.copyOf(md.sources.keySet()).get(0).getJarPath();
}
try (FileSystem fs = Utils.openZipFile(modJarDefault, false)) {
return Files.exists(fs.getPath("fabric.mod.json"))
? Optional.of(JFiles.readObject(fs.getPath("fabric.mod.json"), FabricModJson.class))
: Optional.empty();
Path fmjPath = fs.getPath("fabric.mod.json");
if (!Files.exists(fmjPath)) return null;
return JFiles.readObject(fmjPath, FabricModJson.class);
}
}
private static class MetadataRef {
public MetadataRef(Path imodPath, @Nullable Function<Path, ModMeta> defaultMeta) throws IOException {
this.imodPath = imodPath;
if (!Files.exists(imodPath) && defaultMeta != null) JFiles.writeObject(imodPath, defaultMeta.apply(imodPath));
if (Files.exists(imodPath)) update();
}
public Path imodPath;
public Path jarPath; // filled in from evaluateSources
public ModMeta meta;
public void update() throws IOException {
this.meta = JFiles.readObject(imodPath, ModMeta.class);
}
}
}

View File

@ -0,0 +1,136 @@
package io.gitlab.jfronny.inceptum.launcher.system.mds;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import org.jetbrains.annotations.Nullable;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;
import java.util.stream.Collectors;
public class MdsMod extends Mod {
private final ProtoInstance instance;
private final Path imodPath;
private final Path jarPath;
private final boolean managedJar;
private final ModMeta meta;
private final @Nullable FabricModJson fmj;
MdsMod(ProtoInstance instance, Path imodPath, Path jarPath, boolean managedJar, ModMeta meta, @Nullable FabricModJson fmj) {
this.instance = instance;
this.imodPath = imodPath;
this.jarPath = jarPath;
this.managedJar = managedJar;
this.meta = meta;
this.fmj = fmj;
}
@Override
public String getName() {
String fileName = imodPath.getFileName().toString();
if (fmj == null) return fileName;
String name = fmj.name == null ? fmj.id == null ? fileName : fmj.id : fmj.name;
if (fmj.version != null) name += ' ' + fmj.version;
return name;
}
@Override
public String[] getDescription() {
if (fmj != null && fmj.description != null) return fmj.description.split("\n");
else return new String[] {"No description is available", "You may need to wait for its metadata to be scanned"};
}
@Override
public boolean needsInject() {
return managedJar;
}
@Override
public Path getJarPath() {
return jarPath;
}
@Override
public Path getMetadataPath() {
return imodPath;
}
@Override
public void delete() throws IOException {
Files.delete(imodPath);
if (!managedJar) Files.delete(jarPath);
if (meta != null) {
for (Mod dependency : getDependencies()) dependency.removeDependent(this);
for (Mod dependent : getDependents()) dependent.removeDependency(this);
}
}
@Override
public Path update(ModSource update) throws IOException {
ModManager.DownloadMeta download = ModManager.download(update, imodPath, instance.mds);
Files.delete(imodPath);
download.write();
for (String dependency : meta.dependencies) {
if (!download.meta().dependencies.contains(dependency)) {
instance.mds.get(instance.modsDir.resolve(dependency)).removeDependent(this);
}
}
instance.mds.invalidate(this);
return download.metaFile();
}
@Override
public Set<Mod> getDependencies() {
return meta.dependencies.stream()
.map(instance.modsDir::resolve)
.map(instance.mds::get)
.collect(Collectors.toUnmodifiableSet());
}
@Override
public Set<Mod> getDependents() {
return meta.dependents.stream()
.map(instance.modsDir::resolve)
.map(instance.mds::get)
.collect(Collectors.toUnmodifiableSet());
}
@Override
public void removeDependency(Mod dependency) throws IOException {
meta.dependencies.remove(meta.dependencies.stream()
.filter(s -> dependency.equals(instance.mds.get(instance.modsDir.resolve(s))))
.findFirst()
.orElseThrow(FileNotFoundException::new));
write();
}
@Override
public void removeDependent(Mod dependent) throws IOException {
meta.dependents.remove(meta.dependents.stream()
.filter(s -> dependent.equals(instance.mds.get(instance.modsDir.resolve(s))))
.findFirst()
.orElseThrow(FileNotFoundException::new));
write();
if (!meta.explicit && meta.dependents.isEmpty()) delete();
}
@Override
public ModMeta getMetadata() {
return meta;
}
@Override
public boolean isEnabled() {
return ModPath.isEnabled(imodPath);
}
private void write() throws IOException {
JFiles.writeObject(imodPath, meta);
}
}

View File

@ -1,7 +1,9 @@
package io.gitlab.jfronny.inceptum.launcher.system.mds;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.noop.NoopMds;
import java.io.Closeable;
import java.io.IOException;
@ -11,9 +13,9 @@ import java.util.Set;
import java.util.function.BiConsumer;
public interface ModsDirScanner extends Closeable {
static ModsDirScanner get(Path modsDir, InstanceMeta instance) throws IOException {
if (Files.exists(modsDir)) return ModsDirScannerImpl.get(modsDir, instance);
return new NoopMds(instance.getMinecraftVersion());
static ModsDirScanner get(Path modsDir, InstanceMeta meta) throws IOException {
if (Files.exists(modsDir)) return ModsDirScannerImpl.get(modsDir, meta);
return new NoopMds(meta.getMinecraftVersion());
}
static void closeAll() {
@ -32,7 +34,15 @@ public interface ModsDirScanner extends Closeable {
void invalidate(Path path);
default void invalidate(Mod mod) {
invalidate(mod.getMetadataPath());
}
boolean hasScanned(Path path);
default boolean hasScanned(Mod mod) {
return hasScanned(mod.getMetadataPath());
}
void runOnce(BiConsumer<Path, Mod> discovered);
}

View File

@ -4,8 +4,8 @@ import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.R;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.util.ModPath;
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
import io.gitlab.jfronny.inceptum.launcher.system.mds.noop.NoopMod;
import java.io.IOException;
import java.nio.file.*;
@ -21,14 +21,12 @@ class ModsDirScannerImpl implements ModsDirScanner {
private final Map<Path, Mod> descriptions = new HashMap<>();
private final Set<Path> scannedPaths = new HashSet<>();
private final Thread th;
private final Path modsDir;
private final InstanceMeta instance;
private final ProtoInstance instance;
private final WatchService service;
private boolean disposed = false;
private ModsDirScannerImpl(Path modsDir, InstanceMeta instance) throws IOException {
this.modsDir = modsDir;
this.instance = instance;
this.instance = new ProtoInstance(modsDir, this, instance);
this.th = new Thread(this::scanTaskInternal, "mds-" + modsDir.getParent().getFileName());
this.service = FileSystems.getDefault().newWatchService();
modsDir.register(service, ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE);
@ -48,9 +46,9 @@ class ModsDirScannerImpl implements ModsDirScanner {
@Override
public boolean isComplete() {
if (!Files.isDirectory(modsDir)) return true;
if (!Files.isDirectory(instance.modsDir)) return true;
try {
for (Path path : JFiles.list(modsDir)) {
for (Path path : JFiles.list(instance.modsDir)) {
if (!descriptions.containsKey(path)) return false;
}
} catch (IOException e) {
@ -67,14 +65,14 @@ class ModsDirScannerImpl implements ModsDirScanner {
@Override
public String getGameVersion() {
return instance.getMinecraftVersion();
return instance.meta.getMinecraftVersion();
}
@Override
public Set<Mod> getMods() throws IOException {
Set<Mod> mods = new TreeSet<>();
if (Files.isDirectory(modsDir)) {
for (Path path : JFiles.list(modsDir)) {
if (Files.isDirectory(instance.modsDir)) {
for (Path path : JFiles.list(instance.modsDir)) {
if (ModPath.isImod(path) && Files.exists(ModPath.trimImod(path)))
continue;
mods.add(get(path));
@ -85,10 +83,8 @@ class ModsDirScannerImpl implements ModsDirScanner {
@Override
public Mod get(Path path) {
if (!descriptions.containsKey(path)) {
// not yet scanned
descriptions.put(path, new Mod(path));
}
if (!Files.isRegularFile(path)) return null;
if (!descriptions.containsKey(path)) return new NoopMod(path); // not yet scanned
return descriptions.get(path);
}
@ -112,36 +108,36 @@ class ModsDirScannerImpl implements ModsDirScanner {
@Override
public void runOnce(BiConsumer<Path, Mod> discovered) {
try {
if (!Files.isDirectory(modsDir)) {
if (!Files.isDirectory(instance.modsDir)) {
return;
}
Set<Future<?>> tasks = new HashSet<>();
String mc = instance.getMinecraftVersion();
String mc = instance.meta.getMinecraftVersion();
discovered = discovered.andThen((path, iwModDescription) -> {
scannedPaths.add(path);
descriptions.put(path, iwModDescription);
});
Set<Path> toScan;
if (descriptions.isEmpty()) {
toScan = Set.copyOf(JFiles.list(modsDir));
toScan = Set.copyOf(JFiles.list(instance.modsDir));
} else {
toScan = new HashSet<>();
WatchKey key = service.poll();
if (key != null) {
for (WatchEvent<?> event : key.pollEvents()) {
if (event.context() instanceof Path p) {
toScan.add(modsDir.resolve(p));
toScan.add(instance.modsDir.resolve(p));
}
}
if (!key.reset()) Utils.LOGGER.warn("Could not reset config watch key");
}
JFiles.listTo(modsDir, path -> {
JFiles.listTo(instance.modsDir, path -> {
if (!descriptions.containsKey(path))
toScan.add(path);
});
}
for (Path p : toScan) {
tasks.add(POOL.submit(new FileScanTask(p, discovered, mc)));
tasks.add(POOL.submit(new FileScanTask(instance, p, discovered, mc)));
}
for (Future<?> task : tasks) {
try {
@ -165,6 +161,6 @@ class ModsDirScannerImpl implements ModsDirScanner {
@Override
public void close() {
disposed = true;
SCANNERS.remove(modsDir);
SCANNERS.remove(instance.modsDir);
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.inceptum.launcher.system.mds;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import java.nio.file.Path;
public class ProtoInstance {
public final Path modsDir;
public final ModsDirScanner mds;
public final InstanceMeta meta;
public ProtoInstance(Path modsDir, ModsDirScanner mds, InstanceMeta meta) {
this.modsDir = modsDir;
this.mds = mds;
this.meta = meta;
}
}

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.inceptum.launcher.system.mds;
package io.gitlab.jfronny.inceptum.launcher.system.mds.noop;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import java.io.IOException;
import java.nio.file.Path;
@ -33,7 +34,7 @@ public record NoopMds(String gameVersion) implements ModsDirScanner {
@Override
public Mod get(Path path) {
return new Mod(path);
return new NoopMod(path);
}
@Override

View File

@ -0,0 +1,84 @@
package io.gitlab.jfronny.inceptum.launcher.system.mds.noop;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Set;
public class NoopMod extends Mod {
private final Path path;
private final ModMeta meta;
public NoopMod(Path path) {
this.path = path;
this.meta = ModMeta.of(path);
}
@Override
public String getName() {
return path.getFileName().toString();
}
@Override
public String[] getDescription() {
return new String[] {
"Noop mod",
"Any actions on this mod are unsupported"
};
}
@Override
public boolean needsInject() {
return false;
}
@Override
public Path getJarPath() {
return path;
}
@Override
public Path getMetadataPath() {
return path;
}
@Override
public void delete() throws IOException {
}
@Override
public Path update(ModSource update) throws IOException {
return path;
}
@Override
public Set<Mod> getDependencies() {
return Set.of();
}
@Override
public Set<Mod> getDependents() {
return Set.of();
}
@Override
public void removeDependency(Mod dependency) throws IOException {
}
@Override
public void removeDependent(Mod dependent) throws IOException {
}
@Override
public ModMeta getMetadata() {
return meta;
}
@Override
public boolean isEnabled() {
return true;
}
}

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.inceptum.launcher.system.install;
package io.gitlab.jfronny.inceptum.launcher.system.setup;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.system.instance.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.system.install;
package io.gitlab.jfronny.inceptum.launcher.system.setup;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

View File

@ -1,12 +1,12 @@
package io.gitlab.jfronny.inceptum.launcher.system.install;
package io.gitlab.jfronny.inceptum.launcher.system.setup;
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi;
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionsListInfo;
import io.gitlab.jfronny.inceptum.launcher.system.install.steps.*;
import io.gitlab.jfronny.inceptum.launcher.system.setup.steps.*;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import java.io.IOException;

View File

@ -1,10 +1,10 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.AssetIndex;
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import java.io.IOException;
import java.net.URISyntaxException;

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.commons.ComparableVersion;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.MojangFileDownload;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
import java.io.IOException;
import java.net.URISyntaxException;
@ -19,7 +19,7 @@ public class DownloadClientStep implements Step {
Path serverPath = MetaHolder.LIBRARIES_DIR.resolve("net/minecraft/server");
if (!Files.exists(clientPath)) Files.createDirectories(clientPath);
if (!Files.exists(serverPath)) Files.createDirectories(serverPath);
String minecraftVersion = InstanceMeta.getMinecraftVersion(info.version().id);
String minecraftVersion = GameVersionParser.getMinecraftVersion(info.version().id);
clientPath = clientPath.resolve(minecraftVersion + ".jar");
serverPath = serverPath.resolve(minecraftVersion + ".jar");
try {

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.common.Net;
import io.gitlab.jfronny.inceptum.launcher.api.McApi;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import java.io.IOException;
import java.net.URISyntaxException;

View File

@ -1,16 +1,14 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.common.api.GitlabApi;
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ArtifactInfo;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import io.gitlab.jfronny.inceptum.launcher.util.VersionInfoLibraryResolver;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.util.*;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import java.io.IOException;
import java.net.URISyntaxException;
@ -43,7 +41,7 @@ public class DownloadLibrariesStep implements Step {
if (artifact.isNative) {
currentState.updateStep("Extracting natives");
try (FileSystem libFs = Utils.openZipFile(path, false)) {
JFiles.copyRecursive(libFs.getPath("."), MetaHolder.NATIVES_DIR.resolve(InstanceMeta.getMinecraftVersion(version.id)));
JFiles.copyRecursive(libFs.getPath("."), MetaHolder.NATIVES_DIR.resolve(GameVersionParser.getMinecraftVersion(version.id)));
} catch (Throwable t) {
Files.delete(path);
throw new IOException("Could not extract native", t);

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import java.io.IOException;
import java.nio.file.Path;

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.instance.LoaderInfo;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
import java.io.IOException;
import java.nio.file.Files;
@ -33,6 +33,6 @@ public class SetupDirsStep implements Step {
if (!Files.exists(eulaTxt)) {
Files.writeString(eulaTxt, "eula=true");
}
Files.createDirectories(MetaHolder.NATIVES_DIR.resolve(InstanceMeta.getMinecraftVersion(info.version().id)));
Files.createDirectories(MetaHolder.NATIVES_DIR.resolve(GameVersionParser.getMinecraftVersion(info.version().id)));
}
}

View File

@ -1,11 +1,11 @@
package io.gitlab.jfronny.inceptum.launcher.system.install.steps;
package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.install.Step;
import io.gitlab.jfronny.inceptum.launcher.system.install.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.inceptum.launcher.util;
public class GameVersionParser {
private static final String FABRIC_PREFIX = "fabric-loader-";
public static boolean isFabric(String version) {
return version.startsWith(FABRIC_PREFIX);
}
public static String getMinecraftVersion(String version) {
return version.startsWith(FABRIC_PREFIX) ? version.substring(version.lastIndexOf('-') + 1) : version;
}
public static String getLoaderVersion(String version) {
return !isFabric(version) ? null : version.substring(FABRIC_PREFIX.length(), version.lastIndexOf('-'));
}
}

View File

@ -1,57 +0,0 @@
package io.gitlab.jfronny.inceptum.launcher.util;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModDescription;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Instance;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.rt.Mod;
import io.gitlab.jfronny.inceptum.launcher.system.mds.ModsDirScanner;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModDownload;
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class ModManager {
public static void delete(Instance instance, Mod md) throws IOException {
JFiles.deleteRecursive(md.path());
if (md.imod().isPresent() && Files.exists(md.imod().get())) Files.delete(md.imod().get());
if (md.mod().isPresent()) {
for (String dependency : md.mod().get().dependencies) {
Path dep = instance.modsDir().resolve(dependency);
Mod dmd = instance.mds().get(dep);
if (dmd.mod().isPresent()) {
dmd.mod().get().dependencies.remove(md.path().getFileName().toString());
if (dmd.mod().get().dependencies.isEmpty()) delete(instance, dmd);
else if (dmd.imod().isPresent()) JFiles.writeObject(dmd.imod().get(), dmd.mod().get());
}
}
}
}
public static DownloadMeta download(ModSource ms, Path metaFile, ModsDirScanner mds) throws IOException {
for (Mod value : mds.getMods()) {
if (value.mod().isEmpty()) continue;
for (ModSource source : value.mod().get().sources.keySet()) {
if (ms.equals(source)) {
return new DownloadMeta(new ModDownload(value.mod().get().sha1, value.mod().get().murmur2, value.path()), value.mod().get(), source, metaFile);
}
}
}
ModDownload md = ms.download();
ModDescription manifest = ModDescription.of(md.sha1(), md.murmur2(), ms, mds.getGameVersion());
for (ModSource dependency : ms.getDependencies(mds.getGameVersion())) {
DownloadMeta depMan = download(dependency, metaFile.getParent().resolve(dependency.getShortName() + ModPath.EXT_IMOD), mds);
depMan.description.dependents.add(md.file().getFileName().toString());
manifest.dependencies.add(depMan.download.file().getFileName().toString());
depMan.write();
}
return new DownloadMeta(md, manifest, ms, metaFile);
}
public record DownloadMeta(ModDownload download, ModDescription description, ModSource source, Path metaFile) {
public void write() throws IOException {
JFiles.writeObject(metaFile, description);
}
}
}

View File

@ -0,0 +1,9 @@
package io.gitlab.jfronny.inceptum.launcher.util;
public class Unchecked extends RuntimeException {
public final Exception exception;
public Unchecked(Exception exception) {
this.exception = exception;
}
}

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util.ignore;
package io.gitlab.jfronny.inceptum.launcher.util.gitignore;
import java.util.*;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util.ignore;
package io.gitlab.jfronny.inceptum.launcher.util.gitignore;
import java.util.List;
import java.util.function.Predicate;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util.ignore;
package io.gitlab.jfronny.inceptum.launcher.util.gitignore;
import java.io.IOException;
import java.io.UncheckedIOException;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util.ignore;
package io.gitlab.jfronny.inceptum.launcher.util.gitignore;
import java.util.function.Function;
import java.util.regex.*;

View File

@ -1,4 +1,4 @@
package io.gitlab.jfronny.inceptum.launcher.util.ignore;
package io.gitlab.jfronny.inceptum.launcher.util.gitignore;
public class Replacers {
public static final Replacer TRAILING_SPACES = new Replacer(

@ -1 +1 @@
Subproject commit fe0b2fdc3361a5a085a316b73e25aec635c50863
Subproject commit c93246e29670814079791a5ebe0e62a824cd52e9