format
This commit is contained in:
parent
e352bb835f
commit
e222633c13
|
@ -3,8 +3,8 @@ package dev.frogmc.frogloader.api.mod;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -116,9 +116,9 @@ public final class ModExtensions {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (value instanceof String s){
|
if (value instanceof String s) {
|
||||||
c.accept(s);
|
c.accept(s);
|
||||||
} else if (value instanceof Collection l){
|
} else if (value instanceof Collection l) {
|
||||||
((Collection<String>) l).forEach(c);
|
((Collection<String>) l).forEach(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ public interface ModProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this mod's paths
|
* Get this mod's paths
|
||||||
|
*
|
||||||
* @return Where this mod is loaded from
|
* @return Where this mod is loaded from
|
||||||
*/
|
*/
|
||||||
Collection<Path> paths();
|
Collection<Path> paths();
|
||||||
|
|
|
@ -3,13 +3,13 @@ package dev.frogmc.frogloader.api.plugin;
|
||||||
import dev.frogmc.frogloader.api.FrogLoader;
|
import dev.frogmc.frogloader.api.FrogLoader;
|
||||||
|
|
||||||
public interface FrogGamePlugin {
|
public interface FrogGamePlugin {
|
||||||
default void run() {
|
default void run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isApplicable() {
|
default boolean isApplicable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
default void init(FrogLoader loader) throws Exception {
|
default void init(FrogLoader loader) throws Exception {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,29 @@
|
||||||
package dev.frogmc.frogloader.api.plugin;
|
package dev.frogmc.frogloader.api.plugin;
|
||||||
|
|
||||||
import dev.frogmc.frogloader.api.mod.ModProperties;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import dev.frogmc.frogloader.api.mod.ModProperties;
|
||||||
|
|
||||||
public interface FrogModProvider {
|
public interface FrogModProvider {
|
||||||
String id();
|
String id();
|
||||||
|
|
||||||
default String loadDirectory() {
|
default String loadDirectory() {
|
||||||
return "mods";
|
return "mods";
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isApplicable() {
|
default boolean isApplicable() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isFileApplicable(Path path) {
|
default boolean isFileApplicable(Path path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
default void initMods(Collection<ModProperties> mods) {};
|
default void initMods(Collection<ModProperties> mods) {
|
||||||
|
}
|
||||||
|
|
||||||
default ModProperties loadMod(Path path) {
|
default ModProperties loadMod(Path path) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package dev.frogmc.frogloader.api.plugin;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import dev.frogmc.frogloader.api.FrogLoader;
|
import dev.frogmc.frogloader.api.FrogLoader;
|
||||||
import dev.frogmc.frogloader.api.mod.ModProperties;
|
import dev.frogmc.frogloader.api.mod.ModProperties;
|
||||||
|
|
|
@ -1,22 +1,5 @@
|
||||||
package dev.frogmc.frogloader.impl;
|
package dev.frogmc.frogloader.impl;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import dev.frogmc.frogloader.api.FrogLoader;
|
|
||||||
import dev.frogmc.frogloader.api.env.Env;
|
|
||||||
import dev.frogmc.frogloader.api.mod.ModProperties;
|
|
||||||
import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
|
|
||||||
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
|
|
||||||
import dev.frogmc.frogloader.api.plugin.FrogPlugin;
|
|
||||||
import dev.frogmc.frogloader.impl.gui.LoaderGui;
|
|
||||||
import dev.frogmc.frogloader.impl.launch.MixinClassLoader;
|
|
||||||
import dev.frogmc.frogloader.impl.mod.ModUtil;
|
|
||||||
import dev.frogmc.frogloader.impl.util.CrashReportGenerator;
|
|
||||||
import dev.frogmc.frogloader.impl.util.SystemProperties;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
|
@ -27,145 +10,161 @@ import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import dev.frogmc.frogloader.api.FrogLoader;
|
||||||
|
import dev.frogmc.frogloader.api.env.Env;
|
||||||
|
import dev.frogmc.frogloader.api.mod.ModProperties;
|
||||||
|
import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
|
||||||
|
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
|
||||||
|
import dev.frogmc.frogloader.impl.gui.LoaderGui;
|
||||||
|
import dev.frogmc.frogloader.impl.launch.MixinClassLoader;
|
||||||
|
import dev.frogmc.frogloader.impl.mod.ModUtil;
|
||||||
|
import dev.frogmc.frogloader.impl.util.CrashReportGenerator;
|
||||||
|
import dev.frogmc.frogloader.impl.util.SystemProperties;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||||
|
|
||||||
public class FrogLoaderImpl implements FrogLoader {
|
public class FrogLoaderImpl implements FrogLoader {
|
||||||
public static final String MOD_FILE_EXTENSION = ".frogmod";
|
public static final String MOD_FILE_EXTENSION = ".frogmod";
|
||||||
private static final boolean DEV_ENV = Boolean.getBoolean(SystemProperties.DEVELOPMENT);
|
private static final boolean DEV_ENV = Boolean.getBoolean(SystemProperties.DEVELOPMENT);
|
||||||
@Getter
|
@Getter
|
||||||
private static FrogLoaderImpl instance;
|
private static FrogLoaderImpl instance;
|
||||||
@Getter
|
@Getter
|
||||||
private final String[] args;
|
private final String[] args;
|
||||||
@Getter
|
@Getter
|
||||||
private final Env env;
|
private final Env env;
|
||||||
private final Logger LOGGER = LoggerFactory.getLogger("FrogLoader");
|
private final Logger LOGGER = LoggerFactory.getLogger("FrogLoader");
|
||||||
|
|
||||||
// @Getter
|
// @Getter
|
||||||
// private final List<FrogPlugin> plugins = new ArrayList<>();
|
// private final List<FrogPlugin> plugins = new ArrayList<>();
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Collection<FrogGamePlugin> gamePlugins = new ArrayList<>();
|
private final Collection<FrogGamePlugin> gamePlugins = new ArrayList<>();
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Collection<FrogModProvider> modProviders = new ArrayList<>();
|
private final Collection<FrogModProvider> modProviders = new ArrayList<>();
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Path gameDir, configDir, modsDir;
|
private final Path gameDir, configDir, modsDir;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final MixinClassLoader classloader;
|
private final MixinClassLoader classloader;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Gson gson = new Gson();
|
private final Gson gson = new Gson();
|
||||||
|
|
||||||
// Map<Provider ID, Map<Mod ID, ModProperties>>
|
// Map<Provider ID, Map<Mod ID, ModProperties>>
|
||||||
private Map<String, Map<String, ModProperties>> mods = new HashMap<>();
|
private final Map<String, Map<String, ModProperties>> mods = new HashMap<>();
|
||||||
// private Map<String, ModProperties> mods;
|
// private Map<String, ModProperties> mods;
|
||||||
private Collection<String> modIds = new ArrayList<>();
|
private Collection<String> modIds = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
private FrogLoaderImpl(String[] args, Env env) {
|
private FrogLoaderImpl(String[] args, Env env) {
|
||||||
instance = this;
|
instance = this;
|
||||||
this.classloader = (MixinClassLoader) this.getClass().getClassLoader();
|
this.classloader = (MixinClassLoader) this.getClass().getClassLoader();
|
||||||
this.args = args;
|
this.args = args;
|
||||||
this.env = env;
|
this.env = env;
|
||||||
|
|
||||||
gameDir = Paths.get(getArgumentOrElse("gameDir", "."));
|
gameDir = Paths.get(getArgumentOrElse("gameDir", "."));
|
||||||
configDir = gameDir.resolve("config");
|
configDir = gameDir.resolve("config");
|
||||||
modsDir = gameDir.resolve("mods");
|
modsDir = gameDir.resolve("mods");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(gameDir);
|
Files.createDirectories(gameDir);
|
||||||
Files.createDirectories(configDir);
|
Files.createDirectories(configDir);
|
||||||
Files.createDirectories(modsDir);
|
Files.createDirectories(modsDir);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.warn("Failed to create essential directories ", e);
|
LOGGER.warn("Failed to create essential directories ", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
discoverGamePlugins();
|
discoverGamePlugins();
|
||||||
discoverModProviders();
|
discoverModProviders();
|
||||||
advanceMixinState();
|
advanceMixinState();
|
||||||
modIds = collectModIds();
|
modIds = collectModIds();
|
||||||
LOGGER.info(ModUtil.getModList(getMods()));
|
LOGGER.info(ModUtil.getModList(getMods()));
|
||||||
LOGGER.info("Launching...");
|
LOGGER.info("Launching...");
|
||||||
gamePlugins.forEach(FrogGamePlugin::run);
|
gamePlugins.forEach(FrogGamePlugin::run);
|
||||||
modProviders.forEach(m -> m.initMods(mods.get(m.id()).values()));
|
modProviders.forEach(m -> m.initMods(mods.get(m.id()).values()));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LoaderGui.execReport(CrashReportGenerator.writeReport(t, getMods()), false);
|
LoaderGui.execReport(CrashReportGenerator.writeReport(t, getMods()), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static void run(String[] args, Env env) {
|
public static void run(String[] args, Env env) {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
throw new IllegalStateException("Loader was started multiple times!");
|
throw new IllegalStateException("Loader was started multiple times!");
|
||||||
}
|
}
|
||||||
|
|
||||||
new FrogLoaderImpl(args, env);
|
new FrogLoaderImpl(args, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void advanceMixinState() {
|
private void advanceMixinState() {
|
||||||
try {
|
try {
|
||||||
MethodHandle m = MethodHandles.privateLookupIn(MixinEnvironment.class, MethodHandles.lookup()).findStatic(MixinEnvironment.class, "gotoPhase", MethodType.methodType(void.class, MixinEnvironment.Phase.class));
|
MethodHandle m = MethodHandles.privateLookupIn(MixinEnvironment.class, MethodHandles.lookup()).findStatic(MixinEnvironment.class, "gotoPhase", MethodType.methodType(void.class, MixinEnvironment.Phase.class));
|
||||||
m.invoke(MixinEnvironment.Phase.INIT);
|
m.invoke(MixinEnvironment.Phase.INIT);
|
||||||
m.invoke(MixinEnvironment.Phase.DEFAULT);
|
m.invoke(MixinEnvironment.Phase.DEFAULT);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void discoverModProviders() {
|
private void discoverModProviders() {
|
||||||
LOGGER.info("Discovering mod providers...");
|
LOGGER.info("Discovering mod providers...");
|
||||||
ServiceLoader<FrogModProvider> loader = ServiceLoader.load(FrogModProvider.class);
|
ServiceLoader<FrogModProvider> loader = ServiceLoader.load(FrogModProvider.class);
|
||||||
loader.stream().map(ServiceLoader.Provider::get).forEach(p -> LOGGER.info("Found mod provider: " + p.getClass().getName()));
|
loader.stream().map(ServiceLoader.Provider::get).forEach(p -> LOGGER.info("Found mod provider: " + p.getClass().getName()));
|
||||||
FrogModProvider[] applicableProviders = ServiceLoader.load(FrogModProvider.class).stream().map(ServiceLoader.Provider::get).filter(FrogModProvider::isApplicable).toArray(FrogModProvider[]::new);
|
FrogModProvider[] applicableProviders = ServiceLoader.load(FrogModProvider.class).stream().map(ServiceLoader.Provider::get).filter(FrogModProvider::isApplicable).toArray(FrogModProvider[]::new);
|
||||||
|
|
||||||
for (FrogModProvider plugin : applicableProviders) {
|
for (FrogModProvider plugin : applicableProviders) {
|
||||||
try {
|
try {
|
||||||
LOGGER.info("Initialising mod provider: " + plugin.id());
|
LOGGER.info("Initialising mod provider: " + plugin.id());
|
||||||
Map<String, ModProperties> modsFromProvider = new HashMap<>();
|
Map<String, ModProperties> modsFromProvider = new HashMap<>();
|
||||||
Collection<Path> paths = Discovery.find(gameDir.resolve(plugin.loadDirectory()), p -> false, plugin::isFileApplicable);
|
Collection<Path> paths = Discovery.find(gameDir.resolve(plugin.loadDirectory()), p -> false, plugin::isFileApplicable);
|
||||||
paths.forEach(p -> {
|
paths.forEach(p -> {
|
||||||
LOGGER.info("Loading mod: " + p);
|
LOGGER.info("Loading mod: " + p);
|
||||||
try {
|
try {
|
||||||
ModProperties mod = plugin.loadMod(p);
|
ModProperties mod = plugin.loadMod(p);
|
||||||
modsFromProvider.put(mod.id(), mod);
|
modsFromProvider.put(mod.id(), mod);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.error("Error during mod initialisation: ", e);
|
LOGGER.error("Error during mod initialisation: ", e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
LOGGER.info("Loaded " + modsFromProvider.size() + " mods from provider: " + plugin.id());
|
LOGGER.info("Loaded " + modsFromProvider.size() + " mods from provider: " + plugin.id());
|
||||||
mods.put(plugin.id(), modsFromProvider);
|
mods.put(plugin.id(), modsFromProvider);
|
||||||
modIds.addAll(modsFromProvider.keySet());
|
modIds.addAll(modsFromProvider.keySet());
|
||||||
modProviders.add(plugin);
|
modProviders.add(plugin);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.error("Error during plugin initialisation: ", e);
|
LOGGER.error("Error during plugin initialisation: ", e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void discoverGamePlugins() {
|
private void discoverGamePlugins() {
|
||||||
LOGGER.info("Discovering game plugins...");
|
LOGGER.info("Discovering game plugins...");
|
||||||
ServiceLoader<FrogGamePlugin> loader = ServiceLoader.load(FrogGamePlugin.class);
|
ServiceLoader<FrogGamePlugin> loader = ServiceLoader.load(FrogGamePlugin.class);
|
||||||
loader.stream().map(ServiceLoader.Provider::get).forEach(p -> LOGGER.info("Found game plugin: " + p.getClass().getName()));
|
loader.stream().map(ServiceLoader.Provider::get).forEach(p -> LOGGER.info("Found game plugin: " + p.getClass().getName()));
|
||||||
FrogGamePlugin[] applicablePlugins = ServiceLoader.load(FrogGamePlugin.class).stream().map(ServiceLoader.Provider::get).filter(FrogGamePlugin::isApplicable).toArray(FrogGamePlugin[]::new);
|
FrogGamePlugin[] applicablePlugins = ServiceLoader.load(FrogGamePlugin.class).stream().map(ServiceLoader.Provider::get).filter(FrogGamePlugin::isApplicable).toArray(FrogGamePlugin[]::new);
|
||||||
if (applicablePlugins.length > 1) {
|
if (applicablePlugins.length > 1) {
|
||||||
throw new IllegalStateException("Multiple applicable game plugins found!");
|
throw new IllegalStateException("Multiple applicable game plugins found!");
|
||||||
} else if (applicablePlugins.length == 0) {
|
} else if (applicablePlugins.length == 0) {
|
||||||
throw new IllegalStateException("No applicable game plugin found!");
|
throw new IllegalStateException("No applicable game plugin found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FrogGamePlugin plugin : applicablePlugins) {
|
for (FrogGamePlugin plugin : applicablePlugins) {
|
||||||
try {
|
try {
|
||||||
plugin.init(this);
|
plugin.init(this);
|
||||||
gamePlugins.add(plugin);
|
gamePlugins.add(plugin);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOGGER.error("Error during plugin initialisation: ", e);
|
LOGGER.error("Error during plugin initialisation: ", e);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*private void discoverPlugins() {
|
/*private void discoverPlugins() {
|
||||||
|
@ -186,48 +185,48 @@ public class FrogLoaderImpl implements FrogLoader {
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public String getArgument(String name) {
|
public String getArgument(String name) {
|
||||||
for (int i = 0; i < args.length - 1; i += 2) {
|
for (int i = 0; i < args.length - 1; i += 2) {
|
||||||
if (args[i].equals("--" + name)) {
|
if (args[i].equals("--" + name)) {
|
||||||
return args[i + 1];
|
return args[i + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getArgumentOrElse(String name, String other) {
|
public String getArgumentOrElse(String name, String other) {
|
||||||
String res = getArgument(name);
|
String res = getArgument(name);
|
||||||
if (res.isEmpty()) {
|
if (res.isEmpty()) {
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDevelopment() {
|
public boolean isDevelopment() {
|
||||||
return DEV_ENV;
|
return DEV_ENV;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isModLoaded(String id) {
|
public boolean isModLoaded(String id) {
|
||||||
return modIds.contains(id);
|
return modIds.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ModProperties> getModProperties(String id) {
|
public Optional<ModProperties> getModProperties(String id) {
|
||||||
return mods.values().stream().flatMap(m -> m.values().stream()).filter(m -> m.id().equals(id)).findFirst();
|
return mods.values().stream().flatMap(m -> m.values().stream()).filter(m -> m.id().equals(id)).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*private Map<String, ModProperties> collectMods() {
|
/*private Map<String, ModProperties> collectMods() {
|
||||||
return plugins.stream().map(FrogPlugin::getMods).flatMap(Collection::stream).collect(Collectors.toMap(ModProperties::id, m -> m));
|
return plugins.stream().map(FrogPlugin::getMods).flatMap(Collection::stream).collect(Collectors.toMap(ModProperties::id, m -> m));
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
private Collection<String> collectModIds() {
|
private Collection<String> collectModIds() {
|
||||||
return mods.values().stream().flatMap(m -> m.keySet().stream()).collect(Collectors.toSet());
|
return mods.values().stream().flatMap(m -> m.keySet().stream()).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<ModProperties> getMods() {
|
public Collection<ModProperties> getMods() {
|
||||||
return mods.values().stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toSet());
|
return mods.values().stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class LoaderGui extends JFrame {
|
||||||
public static void execUnfulfilledDep(Path reportPath, ModDependencyResolver.UnfulfilledDependencyException ex, boolean keepRunning) {
|
public static void execUnfulfilledDep(Path reportPath, ModDependencyResolver.UnfulfilledDependencyException ex, boolean keepRunning) {
|
||||||
exec(gui -> {
|
exec(gui -> {
|
||||||
int count = ex.getDependencies().size();
|
int count = ex.getDependencies().size();
|
||||||
gui.setHeader("Found " + count + " problem"+(count > 1 ? "s" : ""));
|
gui.setHeader("Found " + count + " problem" + (count > 1 ? "s" : ""));
|
||||||
gui.addTab("Info", new UnfulfilledDepPage(ex));
|
gui.addTab("Info", new UnfulfilledDepPage(ex));
|
||||||
addReport(gui, reportPath);
|
addReport(gui, reportPath);
|
||||||
}, keepRunning);
|
}, keepRunning);
|
||||||
|
@ -85,7 +85,7 @@ public class LoaderGui extends JFrame {
|
||||||
public static void execBreakingDep(Path reportPath, ModDependencyResolver.BreakingModException ex, boolean keepRunning) {
|
public static void execBreakingDep(Path reportPath, ModDependencyResolver.BreakingModException ex, boolean keepRunning) {
|
||||||
exec(gui -> {
|
exec(gui -> {
|
||||||
int count = ex.getBreaks().size();
|
int count = ex.getBreaks().size();
|
||||||
gui.setHeader("Found " + count + " problem"+(count > 1 ? "s" : ""));
|
gui.setHeader("Found " + count + " problem" + (count > 1 ? "s" : ""));
|
||||||
gui.addTab("Info", new BreakingDepPage(ex));
|
gui.addTab("Info", new BreakingDepPage(ex));
|
||||||
addReport(gui, reportPath);
|
addReport(gui, reportPath);
|
||||||
}, keepRunning);
|
}, keepRunning);
|
||||||
|
|
|
@ -1,50 +1,50 @@
|
||||||
package dev.frogmc.frogloader.impl.gui.component;
|
package dev.frogmc.frogloader.impl.gui.component;
|
||||||
|
|
||||||
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.plaf.basic.BasicBorders;
|
import javax.swing.plaf.basic.BasicBorders;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class DependencyErrorEntry extends JPanel {
|
public class DependencyErrorEntry extends JPanel {
|
||||||
|
|
||||||
private final JPanel actions;
|
private final JPanel actions;
|
||||||
|
|
||||||
public DependencyErrorEntry(String description, ModDependencyResolver.VersionRange range, Color background, @Nullable String icon) {
|
public DependencyErrorEntry(String description, ModDependencyResolver.VersionRange range, Color background, @Nullable String icon) {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
|
|
||||||
setBorder(BasicBorders.getInternalFrameBorder());
|
setBorder(BasicBorders.getInternalFrameBorder());
|
||||||
|
|
||||||
Box text = Box.createVerticalBox();
|
Box text = Box.createVerticalBox();
|
||||||
text.setBorder(BorderFactory.createEmptyBorder());
|
text.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
JTextPane desc = new JTextPane();
|
JTextPane desc = new JTextPane();
|
||||||
desc.setContentType("text/html");
|
desc.setContentType("text/html");
|
||||||
desc.setEditable(false);
|
desc.setEditable(false);
|
||||||
desc.setBackground(background);
|
desc.setBackground(background);
|
||||||
desc.setText("<html>" + description.replace("<", "<").replace("\n", "<br>") + "</html>");
|
desc.setText("<html>" + description.replace("<", "<").replace("\n", "<br>") + "</html>");
|
||||||
text.add(desc);
|
text.add(desc);
|
||||||
|
|
||||||
add(text, BorderLayout.NORTH);
|
add(text, BorderLayout.NORTH);
|
||||||
|
|
||||||
this.actions = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
this.actions = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||||
add(this.actions, BorderLayout.SOUTH);
|
add(this.actions, BorderLayout.SOUTH);
|
||||||
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
URL location = getClass().getResource(icon);
|
URL location = getClass().getResource(icon);
|
||||||
|
|
||||||
if (location != null)
|
if (location != null)
|
||||||
add(new JLabel(new ImageIcon(location)), BorderLayout.WEST);
|
add(new JLabel(new ImageIcon(location)), BorderLayout.WEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAction(String label, ActionListener listener) {
|
public void addAction(String label, ActionListener listener) {
|
||||||
var button = new JButton(label);
|
var button = new JButton(label);
|
||||||
button.addActionListener(listener);
|
button.addActionListener(listener);
|
||||||
this.actions.add(button);
|
this.actions.add(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,54 @@
|
||||||
package dev.frogmc.frogloader.impl.gui.page;
|
package dev.frogmc.frogloader.impl.gui.page;
|
||||||
|
|
||||||
import dev.frogmc.frogloader.impl.gui.component.DependencyErrorEntry;
|
|
||||||
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import dev.frogmc.frogloader.impl.gui.component.DependencyErrorEntry;
|
||||||
|
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
|
||||||
|
|
||||||
public class BreakingDepPage extends JScrollPane {
|
public class BreakingDepPage extends JScrollPane {
|
||||||
|
|
||||||
public BreakingDepPage(ModDependencyResolver.BreakingModException ex) {
|
public BreakingDepPage(ModDependencyResolver.BreakingModException ex) {
|
||||||
getHorizontalScrollBar().setUnitIncrement(16);
|
getHorizontalScrollBar().setUnitIncrement(16);
|
||||||
getVerticalScrollBar().setUnitIncrement(16);
|
getVerticalScrollBar().setUnitIncrement(16);
|
||||||
|
|
||||||
Box list = Box.createVerticalBox();
|
Box list = Box.createVerticalBox();
|
||||||
|
|
||||||
ex.getBreaks().forEach(entry -> {
|
ex.getBreaks().forEach(entry -> {
|
||||||
String description =
|
String description =
|
||||||
"""
|
"""
|
||||||
Mod %s (%s) breaks with mod %s (%s) for versions matching range: %s (present: %s)
|
Mod %s (%s) breaks with mod %s (%s) for versions matching range: %s (present: %s)
|
||||||
Suggested Solution: Install %s of Mod %s (%s)
|
Suggested Solution: Install %s of Mod %s (%s)
|
||||||
""";
|
""";
|
||||||
|
|
||||||
description = description.formatted(
|
description = description.formatted(
|
||||||
entry.source().id(),
|
entry.source().id(),
|
||||||
entry.source().name(),
|
entry.source().name(),
|
||||||
entry.broken().id(),
|
entry.broken().id(),
|
||||||
entry.broken().name(),
|
entry.broken().name(),
|
||||||
entry.range().toString(" or "),
|
entry.range().toString(" or "),
|
||||||
entry.broken().version(),
|
entry.broken().version(),
|
||||||
entry.range()
|
entry.range()
|
||||||
.maxCompatible()
|
.maxCompatible()
|
||||||
.or(entry.range()::minCompatible)
|
.or(entry.range()::minCompatible)
|
||||||
.map(Objects::toString)
|
.map(Objects::toString)
|
||||||
.map(s -> "0.0.0".equals(s) ? "any version" : "version " + s)
|
.map(s -> "0.0.0".equals(s) ? "any version" : "version " + s)
|
||||||
.orElse("<unknown>"),
|
.orElse("<unknown>"),
|
||||||
entry.broken().id(),
|
entry.broken().id(),
|
||||||
entry.broken().name()
|
entry.broken().name()
|
||||||
);
|
);
|
||||||
|
|
||||||
DependencyErrorEntry result = new DependencyErrorEntry(
|
DependencyErrorEntry result = new DependencyErrorEntry(
|
||||||
description,
|
description,
|
||||||
entry.range(),
|
entry.range(),
|
||||||
list.getBackground(),
|
list.getBackground(),
|
||||||
entry.source().icon()
|
entry.source().icon()
|
||||||
);
|
);
|
||||||
list.add(result);
|
list.add(result);
|
||||||
});
|
});
|
||||||
setViewportView(list);
|
setViewportView(list);
|
||||||
SwingUtilities.invokeLater(() -> getViewport().setViewPosition(new Point()));
|
SwingUtilities.invokeLater(() -> getViewport().setViewPosition(new Point()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,24 +11,24 @@ import java.nio.file.Path;
|
||||||
|
|
||||||
public class ReportPage extends JScrollPane {
|
public class ReportPage extends JScrollPane {
|
||||||
|
|
||||||
public ReportPage(Path reportPath) {
|
public ReportPage(Path reportPath) {
|
||||||
getHorizontalScrollBar().setUnitIncrement(16);
|
getHorizontalScrollBar().setUnitIncrement(16);
|
||||||
getVerticalScrollBar().setUnitIncrement(16);
|
getVerticalScrollBar().setUnitIncrement(16);
|
||||||
|
|
||||||
JTextArea text = new JTextArea();
|
JTextArea text = new JTextArea();
|
||||||
text.setEditable(false);
|
text.setEditable(false);
|
||||||
text.setTabSize(2);
|
text.setTabSize(2);
|
||||||
try {
|
try {
|
||||||
text.setText(Files.readString(reportPath, StandardCharsets.UTF_8));
|
text.setText(Files.readString(reportPath, StandardCharsets.UTF_8));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
PrintWriter printer = new PrintWriter(writer);
|
PrintWriter printer = new PrintWriter(writer);
|
||||||
printer.printf("Could not load contents of %s:%n", reportPath);
|
printer.printf("Could not load contents of %s:%n", reportPath);
|
||||||
e.printStackTrace(printer);
|
e.printStackTrace(printer);
|
||||||
}
|
}
|
||||||
text.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8));
|
text.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8));
|
||||||
setViewportView(text);
|
setViewportView(text);
|
||||||
SwingUtilities.invokeLater(() -> getViewport().setViewPosition(new Point(0, 0)));
|
SwingUtilities.invokeLater(() -> getViewport().setViewPosition(new Point(0, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package dev.frogmc.frogloader.impl.gui.page;
|
package dev.frogmc.frogloader.impl.gui.page;
|
||||||
|
|
||||||
import dev.frogmc.frogloader.impl.gui.component.DependencyErrorEntry;
|
|
||||||
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
|
|
||||||
import dev.frogmc.frogloader.impl.util.PlatformUtil;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import dev.frogmc.frogloader.impl.gui.component.DependencyErrorEntry;
|
||||||
|
import dev.frogmc.frogloader.impl.mod.ModDependencyResolver;
|
||||||
|
import dev.frogmc.frogloader.impl.util.PlatformUtil;
|
||||||
|
|
||||||
public class UnfulfilledDepPage extends JScrollPane {
|
public class UnfulfilledDepPage extends JScrollPane {
|
||||||
|
|
||||||
public UnfulfilledDepPage(ModDependencyResolver.UnfulfilledDependencyException ex) {
|
public UnfulfilledDepPage(ModDependencyResolver.UnfulfilledDependencyException ex) {
|
||||||
|
@ -39,13 +39,13 @@ public class UnfulfilledDepPage extends JScrollPane {
|
||||||
}
|
}
|
||||||
description.append("\nSuggested Solution: Install ")
|
description.append("\nSuggested Solution: Install ")
|
||||||
.append(
|
.append(
|
||||||
entry
|
entry
|
||||||
.range()
|
.range()
|
||||||
.maxCompatible()
|
.maxCompatible()
|
||||||
.or(entry.range()::minCompatible)
|
.or(entry.range()::minCompatible)
|
||||||
.map(Objects::toString)
|
.map(Objects::toString)
|
||||||
.map(s -> "0.0.0".equals(s) ? "any version" : "version " + s)
|
.map(s -> "0.0.0".equals(s) ? "any version" : "version " + s)
|
||||||
.orElse("<unknown>")
|
.orElse("<unknown>")
|
||||||
)
|
)
|
||||||
.append(" of ");
|
.append(" of ");
|
||||||
if (entry.dependencyName() != null) {
|
if (entry.dependencyName() != null) {
|
||||||
|
@ -55,10 +55,10 @@ public class UnfulfilledDepPage extends JScrollPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
DependencyErrorEntry result = new DependencyErrorEntry(
|
DependencyErrorEntry result = new DependencyErrorEntry(
|
||||||
description.toString(),
|
description.toString(),
|
||||||
entry.range(),
|
entry.range(),
|
||||||
list.getBackground(),
|
list.getBackground(),
|
||||||
entry.source().icon()
|
entry.source().icon()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (entry.link() != null) {
|
if (entry.link() != null) {
|
||||||
|
|
|
@ -58,15 +58,15 @@ public class FrogLauncher {
|
||||||
new FrogLauncher(args, env);
|
new FrogLauncher(args, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putProperty(IPropertyKey key, Object value){
|
public void putProperty(IPropertyKey key, Object value) {
|
||||||
globalProperties.put(key, value);
|
globalProperties.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getProperty(IPropertyKey key){
|
public Object getProperty(IPropertyKey key) {
|
||||||
return globalProperties.get(key);
|
return globalProperties.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getProperty(IPropertyKey key, Object defaultValue){
|
public Object getProperty(IPropertyKey key, Object defaultValue) {
|
||||||
return globalProperties.getOrDefault(key, defaultValue);
|
return globalProperties.getOrDefault(key, defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,15 +14,15 @@ public class FrogGlobalPropertyService implements IGlobalPropertyService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other){
|
public boolean equals(Object other) {
|
||||||
if (other instanceof IPropertyKey k){
|
if (other instanceof IPropertyKey k) {
|
||||||
return name.equals(k.toString());
|
return name.equals(k.toString());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode(){
|
public int hashCode() {
|
||||||
return name.hashCode();
|
return name.hashCode();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,8 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.MultimapBuilder;
|
||||||
import dev.frogmc.frogloader.api.mod.ModDependencies;
|
import dev.frogmc.frogloader.api.mod.ModDependencies;
|
||||||
import dev.frogmc.frogloader.api.mod.ModProperties;
|
import dev.frogmc.frogloader.api.mod.ModProperties;
|
||||||
import dev.frogmc.frogloader.api.mod.SemVer;
|
import dev.frogmc.frogloader.api.mod.SemVer;
|
||||||
|
|
|
@ -49,8 +49,8 @@ public class ModPropertiesReader {
|
||||||
CommentedConfig props = PARSER.parse(in);
|
CommentedConfig props = PARSER.parse(in);
|
||||||
|
|
||||||
String url = in.toString();
|
String url = in.toString();
|
||||||
Path source = Path.of(url.substring(url.lastIndexOf(":")+1).split("!")[0]).toAbsolutePath();
|
Path source = Path.of(url.substring(url.lastIndexOf(":") + 1).split("!")[0]).toAbsolutePath();
|
||||||
if (!source.getFileName().toString().endsWith(".jar")){
|
if (!source.getFileName().toString().endsWith(".jar")) {
|
||||||
source = source.getParent();
|
source = source.getParent();
|
||||||
} else {
|
} else {
|
||||||
// TODO will this result in a memory leak?
|
// TODO will this result in a memory leak?
|
||||||
|
@ -96,7 +96,7 @@ public class ModPropertiesReader {
|
||||||
if (version == null || version.isEmpty())
|
if (version == null || version.isEmpty())
|
||||||
badProperties.add("frog.mod.version");
|
badProperties.add("frog.mod.version");
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
semVer = SemVerImpl.parse(version);
|
semVer = SemVerImpl.parse(version);
|
||||||
} catch (SemVerParseException e) {
|
} catch (SemVerParseException e) {
|
||||||
badProperties.add("frog.mod.version");
|
badProperties.add("frog.mod.version");
|
||||||
|
@ -186,11 +186,11 @@ public class ModPropertiesReader {
|
||||||
|
|
||||||
public InvalidModPropertiesException(String id, Collection<Path> sources, Collection<String> invalid) {
|
public InvalidModPropertiesException(String id, Collection<Path> sources, Collection<String> invalid) {
|
||||||
super(
|
super(
|
||||||
"Invalid properties for %s (%s) - invalid or missing values for: %s".formatted(
|
"Invalid properties for %s (%s) - invalid or missing values for: %s".formatted(
|
||||||
Objects.requireNonNullElse(id, "<unknown>"),
|
Objects.requireNonNullElse(id, "<unknown>"),
|
||||||
sources.stream().map(Path::toString).collect(Collectors.joining(", ")),
|
sources.stream().map(Path::toString).collect(Collectors.joining(", ")),
|
||||||
String.join(", ", invalid)
|
String.join(", ", invalid)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
this.invalid = invalid;
|
this.invalid = invalid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
package dev.frogmc.frogloader.impl.plugin.game.minecraft;
|
package dev.frogmc.frogloader.impl.plugin.game.minecraft;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.nio.file.*;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import dev.frogmc.frogloader.api.FrogLoader;
|
import dev.frogmc.frogloader.api.FrogLoader;
|
||||||
import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
|
import dev.frogmc.frogloader.api.plugin.FrogGamePlugin;
|
||||||
|
@ -9,113 +16,106 @@ import dev.frogmc.thyroxine.Thyroxine;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.MethodType;
|
|
||||||
import java.nio.file.*;
|
|
||||||
|
|
||||||
public class MinecraftGamePlugin implements FrogGamePlugin {
|
public class MinecraftGamePlugin implements FrogGamePlugin {
|
||||||
|
|
||||||
protected final String[] MINECRAFT_CLASSES = new String[]{
|
protected final String[] MINECRAFT_CLASSES = new String[]{
|
||||||
"net/minecraft/client/main/Main.class",
|
"net/minecraft/client/main/Main.class",
|
||||||
"net/minecraft/client/MinecraftApplet.class",
|
"net/minecraft/client/MinecraftApplet.class",
|
||||||
"net/minecraft/server/Main.class"
|
"net/minecraft/server/Main.class"
|
||||||
};
|
};
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger("Plugin/Minecraft");
|
private static final Logger LOGGER = LoggerFactory.getLogger("Plugin/Minecraft");
|
||||||
protected Path gamePath;
|
protected Path gamePath;
|
||||||
protected String foundMainClass;
|
protected String foundMainClass;
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
protected boolean checkLocation(Path jar) {
|
protected boolean checkLocation(Path jar) {
|
||||||
if (!Files.exists(jar) || Files.isDirectory(jar)) {
|
if (!Files.exists(jar) || Files.isDirectory(jar)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try (FileSystem fs = FileSystems.newFileSystem(jar)) {
|
try (FileSystem fs = FileSystems.newFileSystem(jar)) {
|
||||||
for (String n : MINECRAFT_CLASSES) {
|
for (String n : MINECRAFT_CLASSES) {
|
||||||
if (Files.exists(fs.getPath(n)) && n.contains(FrogLoaderImpl.getInstance().getEnv().getIdentifier())) {
|
if (Files.exists(fs.getPath(n)) && n.contains(FrogLoaderImpl.getInstance().getEnv().getIdentifier())) {
|
||||||
LOGGER.info("Found game: {}", jar);
|
LOGGER.info("Found game: {}", jar);
|
||||||
foundMainClass = n.substring(0, n.length() - 6).replace("/", ".");
|
foundMainClass = n.substring(0, n.length() - 6).replace("/", ".");
|
||||||
try {
|
try {
|
||||||
version = FrogLoaderImpl.getInstance().getGson().fromJson(Files.readString(fs.getPath("version.json")), JsonObject.class).get("id").getAsString();
|
version = FrogLoaderImpl.getInstance().getGson().fromJson(Files.readString(fs.getPath("version.json")), JsonObject.class).get("id").getAsString();
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
version = FrogLoaderImpl.getInstance().getArgument("version");
|
version = FrogLoaderImpl.getInstance().getArgument("version");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Path findGame() {
|
protected Path findGame() {
|
||||||
LOGGER.info("Locating game..");
|
LOGGER.info("Locating game..");
|
||||||
String jar = System.getProperty(SystemProperties.MINECRAFT_GAME_JAR);
|
String jar = System.getProperty(SystemProperties.MINECRAFT_GAME_JAR);
|
||||||
if (jar != null) {
|
if (jar != null) {
|
||||||
Path p = Paths.get(jar);
|
Path p = Paths.get(jar);
|
||||||
if (checkLocation(p)) {
|
if (checkLocation(p)) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String s : System.getProperty("java.class.path", "").split(File.pathSeparator)) {
|
for (String s : System.getProperty("java.class.path", "").split(File.pathSeparator)) {
|
||||||
Path p = Paths.get(s);
|
Path p = Paths.get(s);
|
||||||
if (checkLocation(p)) {
|
if (checkLocation(p)) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOGGER.warn("Could not locate game!");
|
LOGGER.warn("Could not locate game!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable() {
|
public boolean isApplicable() {
|
||||||
gamePath = findGame();
|
gamePath = findGame();
|
||||||
return gamePath != null;
|
return gamePath != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
if (foundMainClass != null) {
|
if (foundMainClass != null) {
|
||||||
LOGGER.info("Launching main class: {}", foundMainClass);
|
LOGGER.info("Launching main class: {}", foundMainClass);
|
||||||
Class<?> mainClass = Class.forName(foundMainClass);
|
Class<?> mainClass = Class.forName(foundMainClass);
|
||||||
MethodHandle main = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
MethodHandle main = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
main.invoke((Object) FrogLoaderImpl.getInstance().getArgs());
|
main.invoke((Object) FrogLoaderImpl.getInstance().getArgs());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.warn("Failed to locate main class!");
|
LOGGER.warn("Failed to locate main class!");
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(FrogLoader loader) throws Exception {
|
public void init(FrogLoader loader) throws Exception {
|
||||||
if (gamePath == null) {
|
if (gamePath == null) {
|
||||||
throw new IllegalStateException("Game not found!");
|
throw new IllegalStateException("Game not found!");
|
||||||
}
|
}
|
||||||
Path remappedGamePath = loader.getGameDir().resolve(".frogmc/remappedJars").resolve(version).resolve("game-" + version + "-remapped.jar");
|
Path remappedGamePath = loader.getGameDir().resolve(".frogmc/remappedJars").resolve(version).resolve("game-" + version + "-remapped.jar");
|
||||||
|
|
||||||
if (!Files.exists(remappedGamePath.getParent())) {
|
if (!Files.exists(remappedGamePath.getParent())) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(remappedGamePath.getParent());
|
Files.createDirectories(remappedGamePath.getParent());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.error("Failed to create directory", e);
|
LOGGER.error("Failed to create directory", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loader.isDevelopment()) {
|
if (!loader.isDevelopment()) {
|
||||||
if (!Files.exists(remappedGamePath)) {
|
if (!Files.exists(remappedGamePath)) {
|
||||||
Thyroxine.run(version, gamePath, remappedGamePath, true, false);
|
Thyroxine.run(version, gamePath, remappedGamePath, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var runtimePath = loader.isDevelopment() ? gamePath : remappedGamePath;
|
var runtimePath = loader.isDevelopment() ? gamePath : remappedGamePath;
|
||||||
FrogLoaderImpl.getInstance().getClassloader().addURL(runtimePath.toUri().toURL());
|
FrogLoaderImpl.getInstance().getClassloader().addURL(runtimePath.toUri().toURL());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,62 +1,61 @@
|
||||||
package dev.frogmc.frogloader.impl.plugin.mod;
|
package dev.frogmc.frogloader.impl.plugin.mod;
|
||||||
|
|
||||||
import dev.frogmc.frogloader.api.FrogLoader;
|
|
||||||
import dev.frogmc.frogloader.api.extensions.PreLaunchExtension;
|
|
||||||
import dev.frogmc.frogloader.api.mod.ModProperties;
|
|
||||||
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
|
|
||||||
import dev.frogmc.frogloader.impl.mod.ModPropertiesReader;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import dev.frogmc.frogloader.api.extensions.PreLaunchExtension;
|
||||||
|
import dev.frogmc.frogloader.api.mod.ModProperties;
|
||||||
|
import dev.frogmc.frogloader.api.plugin.FrogModProvider;
|
||||||
|
import dev.frogmc.frogloader.impl.mod.ModPropertiesReader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class FrogmodModProvider implements FrogModProvider {
|
public class FrogmodModProvider implements FrogModProvider {
|
||||||
|
|
||||||
Logger LOGGER = org.slf4j.LoggerFactory.getLogger("FrogModProvider");
|
Logger LOGGER = org.slf4j.LoggerFactory.getLogger("FrogModProvider");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String id() {
|
public String id() {
|
||||||
return "frogloader:frogmod";
|
return "frogloader:frogmod";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isApplicable() {
|
public boolean isApplicable() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFileApplicable(Path path) {
|
public boolean isFileApplicable(Path path) {
|
||||||
if (!path.toString().endsWith(".frogmod")) {
|
if (!path.toString().endsWith(".frogmod")) {
|
||||||
LOGGER.info("File {} is not a frogmod file", path.toString());
|
LOGGER.info("File {} is not a frogmod file", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try (FileSystem fs = FileSystems.newFileSystem(path)) {
|
try (FileSystem fs = FileSystems.newFileSystem(path)) {
|
||||||
return fs.getPath("frog.mod.toml").toFile().exists();
|
return fs.getPath("frog.mod.toml").toFile().exists();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.error("Error while checking file {}", path, e);
|
LOGGER.error("Error while checking file {}", path, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModProperties loadMod(Path path) {
|
public ModProperties loadMod(Path path) {
|
||||||
try (FileSystem fs = FileSystems.newFileSystem(path)) {
|
try (FileSystem fs = FileSystems.newFileSystem(path)) {
|
||||||
ModProperties prop = ModPropertiesReader.readFile(fs.getPath("frog.mod.toml").toUri().toURL()).orElseThrow(IOException::new);
|
ModProperties prop = ModPropertiesReader.readFile(fs.getPath("frog.mod.toml").toUri().toURL()).orElseThrow(IOException::new);
|
||||||
// prop.extensions().runIfPresent(PreLaunchExtension.ID, PreLaunchExtension.class, PreLaunchExtension::onPreLaunch);
|
// prop.extensions().runIfPresent(PreLaunchExtension.ID, PreLaunchExtension.class, PreLaunchExtension::onPreLaunch);
|
||||||
return prop;
|
return prop;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initMods(Collection<ModProperties> mods) {
|
public void initMods(Collection<ModProperties> mods) {
|
||||||
mods.forEach(mod -> {
|
mods.forEach(mod -> {
|
||||||
mod.extensions().runIfPresent(PreLaunchExtension.ID, PreLaunchExtension.class, PreLaunchExtension::onPreLaunch);
|
mod.extensions().runIfPresent(PreLaunchExtension.ID, PreLaunchExtension.class, PreLaunchExtension::onPreLaunch);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ public class PlatformUtil {
|
||||||
ProcessBuilder builder = new ProcessBuilder("bash", "-c", "wl-copy < " + path);
|
ProcessBuilder builder = new ProcessBuilder("bash", "-c", "wl-copy < " + path);
|
||||||
builder.start();
|
builder.start();
|
||||||
} else {
|
} else {
|
||||||
String data = Files.readString(path, StandardCharsets.UTF_8);
|
String data = Files.readString(path, StandardCharsets.UTF_8);
|
||||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(data), null);
|
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(data), null);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.error("Failed to copy contents of {}:", path, e);
|
LOGGER.error("Failed to copy contents of {}:", path, e);
|
||||||
|
|
Loading…
Reference in a new issue