mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-02-05 16:44:47 +08:00
Fix redownloading disabled mods for curse modpack
This commit is contained in:
parent
d655c9ec6b
commit
fb3ba220b6
@ -31,7 +31,6 @@ import org.jackhuang.hmcl.event.RefreshedVersionsEvent;
|
||||
import org.jackhuang.hmcl.game.HMCLCacheRepository;
|
||||
import org.jackhuang.hmcl.game.HMCLGameRepository;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.mod.ModManager;
|
||||
import org.jackhuang.hmcl.ui.WeakListenerHolder;
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
import org.jackhuang.hmcl.util.javafx.ImmediateObjectProperty;
|
||||
@ -52,7 +51,6 @@ import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
|
||||
public final class Profile implements Observable {
|
||||
private final WeakListenerHolder listenerHolder = new WeakListenerHolder();
|
||||
private final HMCLGameRepository repository;
|
||||
private final ModManager modManager;
|
||||
|
||||
private final StringProperty selectedVersion = new SimpleStringProperty();
|
||||
|
||||
@ -136,7 +134,6 @@ public final class Profile implements Observable {
|
||||
this.name = new ImmediateStringProperty(this, "name", name);
|
||||
gameDir = new ImmediateObjectProperty<>(this, "gameDir", initialGameDir);
|
||||
repository = new HMCLGameRepository(this, initialGameDir);
|
||||
modManager = new ModManager(repository);
|
||||
this.global.set(global == null ? new VersionSetting() : global);
|
||||
this.selectedVersion.set(selectedVersion);
|
||||
this.useRelativePath.set(useRelativePath);
|
||||
@ -166,10 +163,6 @@ public final class Profile implements Observable {
|
||||
return repository;
|
||||
}
|
||||
|
||||
public ModManager getModManager() {
|
||||
return modManager;
|
||||
}
|
||||
|
||||
public DefaultDependencyManager getDependency() {
|
||||
return new DefaultDependencyManager(repository, DownloadProviders.getDownloadProvider(), HMCLCacheRepository.REPOSITORY);
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ public final class ModListPage extends ListPage<ModItem> {
|
||||
|
||||
private JFXTabPane parentTab;
|
||||
private ModManager modManager;
|
||||
private String versionId;
|
||||
|
||||
public ModListPage() {
|
||||
setRefreshable(true);
|
||||
@ -52,41 +51,44 @@ public final class ModListPage extends ListPage<ModItem> {
|
||||
FXUtils.applyDragListener(this, it -> Arrays.asList("jar", "zip", "litemod").contains(FileUtils.getExtension(it)), mods -> {
|
||||
mods.forEach(it -> {
|
||||
try {
|
||||
modManager.addMod(versionId, it);
|
||||
modManager.addMod(it);
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to parse mod file " + it, e);
|
||||
}
|
||||
});
|
||||
loadMods(modManager, versionId);
|
||||
loadMods(modManager);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
loadMods(modManager, versionId);
|
||||
loadMods(modManager);
|
||||
}
|
||||
|
||||
public void loadVersion(Profile profile, String id) {
|
||||
loadMods(profile.getModManager(), id);
|
||||
loadMods(profile.getRepository().getModManager(id));
|
||||
}
|
||||
|
||||
public void loadMods(ModManager modManager, String versionId) {
|
||||
public void loadMods(ModManager modManager) {
|
||||
this.modManager = modManager;
|
||||
this.versionId = versionId;
|
||||
Task.of(variables -> {
|
||||
synchronized (ModListPage.this) {
|
||||
JFXUtilities.runInFX(() -> loadingProperty().set(true));
|
||||
|
||||
modManager.refreshMods(versionId);
|
||||
modManager.refreshMods();
|
||||
|
||||
// Surprisingly, if there are a great number of mods, this processing will cause a long UI pause,
|
||||
// constructing UI elements.
|
||||
// We must do this asynchronously.
|
||||
LinkedList<ModItem> list = new LinkedList<>();
|
||||
for (ModInfo modInfo : modManager.getMods(versionId)) {
|
||||
for (ModInfo modInfo : modManager.getMods()) {
|
||||
ModItem item = new ModItem(modInfo, i -> {
|
||||
modManager.removeMods(versionId, modInfo);
|
||||
loadMods(modManager, versionId);
|
||||
try {
|
||||
modManager.removeMods(modInfo);
|
||||
} catch (IOException ignore) {
|
||||
// Fail to remove mods if the game is running or the mod is absent.
|
||||
}
|
||||
loadMods(modManager);
|
||||
});
|
||||
modInfo.activeProperty().addListener((a, b, newValue) -> {
|
||||
if (newValue)
|
||||
@ -126,7 +128,7 @@ public final class ModListPage extends ListPage<ModItem> {
|
||||
Task.of(variables -> {
|
||||
for (File file : res) {
|
||||
try {
|
||||
modManager.addMod(versionId, file);
|
||||
modManager.addMod(file);
|
||||
succeeded.add(file.getName());
|
||||
} catch (Exception e) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to add mod " + file, e);
|
||||
@ -142,7 +144,7 @@ public final class ModListPage extends ListPage<ModItem> {
|
||||
if (!failed.isEmpty())
|
||||
prompt.add(i18n("mods.add.failed", String.join(", ", failed)));
|
||||
Controllers.dialog(String.join("\n", prompt), i18n("mods.add"));
|
||||
loadMods(modManager, versionId);
|
||||
loadMods(modManager);
|
||||
})).start();
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ package org.jackhuang.hmcl.game;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.event.*;
|
||||
import org.jackhuang.hmcl.mod.ModManager;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
import org.jackhuang.hmcl.util.ToStringBuilder;
|
||||
@ -366,6 +367,10 @@ public class DefaultGameRepository implements GameRepository {
|
||||
return getModpackConfiguration(version).exists();
|
||||
}
|
||||
|
||||
public ModManager getModManager(String version) {
|
||||
return new ModManager(this, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
|
@ -19,7 +19,7 @@ package org.jackhuang.hmcl.mod;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.download.DefaultDependencyManager;
|
||||
import org.jackhuang.hmcl.game.GameRepository;
|
||||
import org.jackhuang.hmcl.game.DefaultGameRepository;
|
||||
import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.*;
|
||||
@ -45,8 +45,8 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public final class CurseCompletionTask extends Task {
|
||||
|
||||
private final DefaultDependencyManager dependencyManager;
|
||||
private final GameRepository repository;
|
||||
private final DefaultGameRepository repository;
|
||||
private final ModManager modManager;
|
||||
private final String version;
|
||||
private CurseManifest manifest = null;
|
||||
private final List<Task> dependents = new LinkedList<>();
|
||||
@ -70,8 +70,8 @@ public final class CurseCompletionTask extends Task {
|
||||
* @param manifest the CurseForgeModpack manifest.
|
||||
*/
|
||||
public CurseCompletionTask(DefaultDependencyManager dependencyManager, String version, CurseManifest manifest) {
|
||||
this.dependencyManager = dependencyManager;
|
||||
this.repository = dependencyManager.getGameRepository();
|
||||
this.modManager = repository.getModManager(version);
|
||||
this.version = version;
|
||||
this.manifest = manifest;
|
||||
|
||||
@ -101,7 +101,6 @@ public final class CurseCompletionTask extends Task {
|
||||
return;
|
||||
|
||||
File root = repository.getVersionRoot(version);
|
||||
File run = repository.getRunDirectory(version);
|
||||
|
||||
AtomicBoolean flag = new AtomicBoolean(true);
|
||||
AtomicInteger finished = new AtomicInteger(0);
|
||||
@ -140,9 +139,9 @@ public final class CurseCompletionTask extends Task {
|
||||
|
||||
for (CurseManifestFile file : newManifest.getFiles())
|
||||
if (StringUtils.isNotBlank(file.getFileName())) {
|
||||
File dest = new File(run, "mods/" + file.getFileName());
|
||||
if (!dest.exists())
|
||||
dependencies.add(new FileDownloadTask(file.getUrl(), dest));
|
||||
if (!modManager.hasSimpleMod(file.getFileName())) {
|
||||
dependencies.add(new FileDownloadTask(file.getUrl(), modManager.getSimpleModPath(file.getFileName()).toFile()));
|
||||
}
|
||||
}
|
||||
|
||||
// Let this task fail if the curse manifest has not been completed.
|
||||
|
@ -114,7 +114,7 @@ public final class ForgeModMetadata {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public static ModInfo fromFile(File modFile) throws IOException, JsonParseException {
|
||||
public static ModInfo fromFile(ModManager modManager, File modFile) throws IOException, JsonParseException {
|
||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile.toPath())) {
|
||||
Path mcmod = fs.getPath("mcmod.info");
|
||||
if (Files.notExists(mcmod))
|
||||
@ -132,7 +132,7 @@ public final class ForgeModMetadata {
|
||||
authors = String.join(", ", metadata.getAuthorList());
|
||||
if (StringUtils.isBlank(authors))
|
||||
authors = metadata.getCredits();
|
||||
return new ModInfo(modFile, metadata.getName(), metadata.getDescription(),
|
||||
return new ModInfo(modManager, modFile, metadata.getName(), metadata.getDescription(),
|
||||
authors, metadata.getVersion(), metadata.getGameVersion(),
|
||||
StringUtils.isBlank(metadata.getUrl()) ? metadata.getUpdateUrl() : metadata.url);
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ public final class LiteModMetadata {
|
||||
return updateURI;
|
||||
}
|
||||
|
||||
public static ModInfo fromFile(File modFile) throws IOException, JsonParseException {
|
||||
public static ModInfo fromFile(ModManager modManager, File modFile) throws IOException, JsonParseException {
|
||||
try (ZipFile zipFile = new ZipFile(modFile)) {
|
||||
ZipEntry entry = zipFile.getEntry("litemod.json");
|
||||
if (entry == null)
|
||||
@ -116,7 +116,8 @@ public final class LiteModMetadata {
|
||||
LiteModMetadata metadata = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(zipFile.getInputStream(entry)), LiteModMetadata.class);
|
||||
if (metadata == null)
|
||||
throw new IOException("Mod " + modFile + " `litemod.json` is malformed.");
|
||||
return new ModInfo(modFile, metadata.getName(), metadata.getDescription(), metadata.getAuthor(), metadata.getVersion(), metadata.getGameVersion(), metadata.getUpdateURI());
|
||||
return new ModInfo(modManager, modFile, metadata.getName(), metadata.getDescription(), metadata.getAuthor(),
|
||||
metadata.getVersion(), metadata.getGameVersion(), metadata.getUpdateURI());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,10 @@ import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.javafx.ImmediateBooleanProperty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -31,7 +34,7 @@ import java.util.Objects;
|
||||
*/
|
||||
public final class ModInfo implements Comparable<ModInfo> {
|
||||
|
||||
private File file;
|
||||
private Path file;
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String authors;
|
||||
@ -41,16 +44,12 @@ public final class ModInfo implements Comparable<ModInfo> {
|
||||
private final String fileName;
|
||||
private final ImmediateBooleanProperty activeProperty;
|
||||
|
||||
public ModInfo(File file, String name) {
|
||||
this(file, name, "");
|
||||
public ModInfo(ModManager modManager, File file, String name, String description) {
|
||||
this(modManager, file, name, description, "", "", "", "");
|
||||
}
|
||||
|
||||
public ModInfo(File file, String name, String description) {
|
||||
this(file, name, description, "", "", "", "");
|
||||
}
|
||||
|
||||
public ModInfo(File file, String name, String description, String authors, String version, String gameVersion, String url) {
|
||||
this.file = file;
|
||||
public ModInfo(ModManager modManager, File file, String name, String description, String authors, String version, String gameVersion, String url) {
|
||||
this.file = file.toPath();
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.authors = authors;
|
||||
@ -58,26 +57,26 @@ public final class ModInfo implements Comparable<ModInfo> {
|
||||
this.gameVersion = gameVersion;
|
||||
this.url = url;
|
||||
|
||||
activeProperty = new ImmediateBooleanProperty(this, "active", !DISABLED_EXTENSION.equals(FileUtils.getExtension(file))) {
|
||||
activeProperty = new ImmediateBooleanProperty(this, "active", !modManager.isDisabled(file)) {
|
||||
@Override
|
||||
protected void invalidated() {
|
||||
File f = ModInfo.this.file.getAbsoluteFile(), newF;
|
||||
if (DISABLED_EXTENSION.equals(FileUtils.getExtension(f)))
|
||||
newF = new File(f.getParentFile(), FileUtils.getNameWithoutExtension(f));
|
||||
else
|
||||
newF = new File(f.getParentFile(), f.getName() + "." + DISABLED_EXTENSION);
|
||||
Path path = ModInfo.this.file.toAbsolutePath();
|
||||
|
||||
if (f.renameTo(newF))
|
||||
ModInfo.this.file = newF;
|
||||
else
|
||||
Logging.LOG.severe("Unable to rename file " + f + " to " + newF);
|
||||
try {
|
||||
if (get())
|
||||
ModInfo.this.file = modManager.enableMod(path);
|
||||
else
|
||||
ModInfo.this.file = modManager.disableMod(path);
|
||||
} catch (IOException e) {
|
||||
Logging.LOG.log(Level.SEVERE, "Unable to invert state of mod file " + path, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fileName = StringUtils.substringBeforeLast(isActive() ? file.getName() : FileUtils.getNameWithoutExtension(file), '.');
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
public Path getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
@ -135,48 +134,4 @@ public final class ModInfo implements Comparable<ModInfo> {
|
||||
public int hashCode() {
|
||||
return Objects.hash(getFileName());
|
||||
}
|
||||
|
||||
public static boolean isFileMod(File file) {
|
||||
String name = file.getName();
|
||||
if (isDisabled(file))
|
||||
name = FileUtils.getNameWithoutExtension(file);
|
||||
return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith(".litemod");
|
||||
}
|
||||
|
||||
public static ModInfo fromFile(File modFile) {
|
||||
File file = isDisabled(modFile) ? new File(modFile.getAbsoluteFile().getParentFile(), FileUtils.getNameWithoutExtension(modFile)) : modFile;
|
||||
String description, extension = FileUtils.getExtension(file);
|
||||
switch (extension) {
|
||||
case "zip":
|
||||
case "jar":
|
||||
try {
|
||||
return ForgeModMetadata.fromFile(modFile);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
try {
|
||||
return RiftModMetadata.fromFile(modFile);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
description = "";
|
||||
break;
|
||||
case "litemod":
|
||||
try {
|
||||
return LiteModMetadata.fromFile(modFile);
|
||||
} catch (Exception ignore) {
|
||||
description = "LiteLoader Mod";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("File " + modFile + " is not a mod file.");
|
||||
}
|
||||
return new ModInfo(modFile, FileUtils.getNameWithoutExtension(modFile), description);
|
||||
}
|
||||
|
||||
public static boolean isDisabled(File file) {
|
||||
return DISABLED_EXTENSION.equals(FileUtils.getExtension(file));
|
||||
}
|
||||
|
||||
public static final String DISABLED_EXTENSION = "disabled";
|
||||
}
|
||||
|
@ -18,50 +18,97 @@
|
||||
package org.jackhuang.hmcl.mod;
|
||||
|
||||
import org.jackhuang.hmcl.game.GameRepository;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.SimpleMultimap;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ModManager {
|
||||
private final GameRepository repository;
|
||||
private final SimpleMultimap<String, ModInfo> modCache = new SimpleMultimap<String, ModInfo>(HashMap::new, TreeSet::new);
|
||||
private final String id;
|
||||
private final TreeSet<ModInfo> modInfos = new TreeSet<>();
|
||||
|
||||
public ModManager(GameRepository repository) {
|
||||
private boolean loaded = false;
|
||||
|
||||
public ModManager(GameRepository repository, String id) {
|
||||
this.repository = repository;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void refreshMods(String id) {
|
||||
modCache.removeKey(id);
|
||||
File modsDirectory = new File(repository.getRunDirectory(id), "mods");
|
||||
Consumer<File> puter = modFile -> Lang.ignoringException(() -> modCache.put(id, ModInfo.fromFile(modFile)));
|
||||
Optional.ofNullable(modsDirectory.listFiles()).map(Arrays::stream).ifPresent(files -> files.forEach(modFile -> {
|
||||
if (modFile.isDirectory() && VersionNumber.isIntVersionNumber(modFile.getName())) {
|
||||
private Path getModsDirectory() {
|
||||
return repository.getRunDirectory(id).toPath().resolve("mods");
|
||||
}
|
||||
|
||||
private void addModInfo(File file) {
|
||||
try {
|
||||
modInfos.add(getModInfo(file));
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public ModInfo getModInfo(File modFile) {
|
||||
File file = isDisabled(modFile) ? new File(modFile.getAbsoluteFile().getParentFile(), FileUtils.getNameWithoutExtension(modFile)) : modFile;
|
||||
String description, extension = FileUtils.getExtension(file);
|
||||
switch (extension) {
|
||||
case "zip":
|
||||
case "jar":
|
||||
try {
|
||||
return ForgeModMetadata.fromFile(this, modFile);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
try {
|
||||
return RiftModMetadata.fromFile(this, modFile);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
description = "";
|
||||
break;
|
||||
case "litemod":
|
||||
try {
|
||||
return LiteModMetadata.fromFile(this, modFile);
|
||||
} catch (Exception ignore) {
|
||||
description = "LiteLoader Mod";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("File " + modFile + " is not a mod file.");
|
||||
}
|
||||
return new ModInfo(this, modFile, FileUtils.getNameWithoutExtension(modFile), description);
|
||||
}
|
||||
|
||||
public void refreshMods() throws IOException {
|
||||
modInfos.clear();
|
||||
for (Path subitem : Files.newDirectoryStream(getModsDirectory())) {
|
||||
if (Files.isDirectory(subitem) && VersionNumber.isIntVersionNumber(FileUtils.getName(subitem))) {
|
||||
// If the folder name is game version, forge will search mod in this subdirectory
|
||||
Optional.ofNullable(modFile.listFiles()).map(Arrays::stream).ifPresent(x -> x.forEach(puter));
|
||||
for (Path subsubitem : Files.newDirectoryStream(subitem))
|
||||
addModInfo(subsubitem.toFile());
|
||||
} else {
|
||||
puter.accept(modFile);
|
||||
addModInfo(subitem.toFile());
|
||||
}
|
||||
}));
|
||||
}
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
public Collection<ModInfo> getMods(String id) {
|
||||
if (!modCache.containsKey(id))
|
||||
refreshMods(id);
|
||||
return modCache.get(id);
|
||||
public Collection<ModInfo> getMods() throws IOException {
|
||||
if (!loaded)
|
||||
refreshMods();
|
||||
return modInfos;
|
||||
}
|
||||
|
||||
public void addMod(String id, File file) throws IOException {
|
||||
if (!ModInfo.isFileMod(file))
|
||||
public void addMod(File file) throws IOException {
|
||||
if (!isFileMod(file))
|
||||
throw new IllegalArgumentException("File " + file + " is not a valid mod file.");
|
||||
|
||||
if (!modCache.containsKey(id))
|
||||
refreshMods(id);
|
||||
if (!loaded)
|
||||
refreshMods();
|
||||
|
||||
File modsDirectory = new File(repository.getRunDirectory(id), "mods");
|
||||
if (!FileUtils.makeDirectory(modsDirectory))
|
||||
@ -70,12 +117,55 @@ public final class ModManager {
|
||||
File newFile = new File(modsDirectory, file.getName());
|
||||
FileUtils.copyFile(file, newFile);
|
||||
|
||||
modCache.put(id, ModInfo.fromFile(newFile));
|
||||
addModInfo(newFile);
|
||||
}
|
||||
|
||||
public boolean removeMods(String id, ModInfo... modInfos) {
|
||||
boolean result = Arrays.stream(modInfos).reduce(true, (acc, modInfo) -> acc && modInfo.getFile().delete(), Boolean::logicalAnd);
|
||||
refreshMods(id);
|
||||
return result;
|
||||
public void removeMods(ModInfo... modInfos) throws IOException {
|
||||
for (ModInfo modInfo : modInfos) {
|
||||
Files.deleteIfExists(modInfo.getFile());
|
||||
}
|
||||
refreshMods();
|
||||
}
|
||||
|
||||
public Path disableMod(Path file) throws IOException {
|
||||
Path disabled = file.getParent().resolve(StringUtils.addSuffix(FileUtils.getName(file), DISABLED_EXTENSION));
|
||||
if (Files.exists(file))
|
||||
Files.move(file, disabled, StandardCopyOption.REPLACE_EXISTING);
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public Path enableMod(Path file) throws IOException {
|
||||
Path enabled = file.getParent().resolve(StringUtils.removeSuffix(FileUtils.getName(file), DISABLED_EXTENSION));
|
||||
if (Files.exists(file))
|
||||
Files.move(file, enabled, StandardCopyOption.REPLACE_EXISTING);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public boolean isDisabled(File file) {
|
||||
return file.getPath().endsWith(DISABLED_EXTENSION);
|
||||
}
|
||||
|
||||
public boolean isFileMod(File file) {
|
||||
String name = file.getName();
|
||||
if (isDisabled(file))
|
||||
name = FileUtils.getNameWithoutExtension(file);
|
||||
return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith(".litemod");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if "mods" directory has mod file named "fileName" no matter the mod is disabled or not
|
||||
*
|
||||
* @param fileName name of the file whose existence is being checked
|
||||
* @return true if the file exists
|
||||
*/
|
||||
public boolean hasSimpleMod(String fileName) {
|
||||
return Files.exists(getModsDirectory().resolve(StringUtils.removeSuffix(fileName, DISABLED_EXTENSION)))
|
||||
|| Files.exists(getModsDirectory().resolve(StringUtils.addSuffix(fileName, DISABLED_EXTENSION)));
|
||||
}
|
||||
|
||||
public Path getSimpleModPath(String fileName) {
|
||||
return getModsDirectory().resolve(fileName);
|
||||
}
|
||||
|
||||
public static final String DISABLED_EXTENSION = ".disabled";
|
||||
}
|
||||
|
@ -60,14 +60,14 @@ public final class RiftModMetadata {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public static ModInfo fromFile(File modFile) throws IOException, JsonParseException {
|
||||
public static ModInfo fromFile(ModManager modManager, File modFile) throws IOException, JsonParseException {
|
||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile.toPath())) {
|
||||
Path mcmod = fs.getPath("riftmod.json");
|
||||
if (Files.notExists(mcmod))
|
||||
throw new IOException("File " + modFile + " is not a Forge mod.");
|
||||
RiftModMetadata metadata = JsonUtils.fromNonNullJson(IOUtils.readFullyAsString(Files.newInputStream(mcmod)), RiftModMetadata.class);
|
||||
String authors = metadata.getAuthors() == null ? "" : String.join(", ", metadata.getAuthors());
|
||||
return new ModInfo(modFile, metadata.getName(), "",
|
||||
return new ModInfo(modManager, modFile, metadata.getName(), "",
|
||||
authors, "", "", "");
|
||||
}
|
||||
}
|
||||
|
@ -146,6 +146,13 @@ public final class StringUtils {
|
||||
return prefix + str;
|
||||
}
|
||||
|
||||
public static String addSuffix(String str, String suffix) {
|
||||
if (str.endsWith(suffix))
|
||||
return str;
|
||||
else
|
||||
return str + suffix;
|
||||
}
|
||||
|
||||
public static String removePrefix(String str, String... prefixes) {
|
||||
for (String prefix : prefixes)
|
||||
if (str.startsWith(prefix))
|
||||
|
Loading…
Reference in New Issue
Block a user