add back list capabilities to ModExtensionsImpl.runIfPresent
Some checks failed
Publish to snapshot maven / build (push) Failing after 1m15s

- format
This commit is contained in:
moehreag 2024-09-30 23:44:59 +02:00
parent cea4e8ea01
commit 3f53df3f83
15 changed files with 109 additions and 98 deletions

View file

@ -7,6 +7,7 @@ public class ModExtensionResolutionException extends Exception {
/** /**
* Instantiate this exception * Instantiate this exception
*
* @param message A message describing this exception * @param message A message describing this exception
*/ */
public ModExtensionResolutionException(String message) { public ModExtensionResolutionException(String message) {
@ -15,6 +16,7 @@ public class ModExtensionResolutionException extends Exception {
/** /**
* Instantiate this exception * Instantiate this exception
*
* @param cause The cause of this exception * @param cause The cause of this exception
*/ */
public ModExtensionResolutionException(Throwable cause) { public ModExtensionResolutionException(Throwable cause) {
@ -23,8 +25,9 @@ public class ModExtensionResolutionException extends Exception {
/** /**
* Instantiate this exception * Instantiate this exception
*
* @param message A message describing this exception * @param message A message describing this exception
* @param cause The cause of this exception * @param cause The cause of this exception
*/ */
public ModExtensionResolutionException(String message, Throwable cause) { public ModExtensionResolutionException(String message, Throwable cause) {
super(message, cause); super(message, cause);

View file

@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
/** /**
* Represents dependencies declared by a mod at runtime. * Represents dependencies declared by a mod at runtime.
*
* @see ModProperties * @see ModProperties
* @see ModExtensions * @see ModExtensions
*/ */
@ -30,7 +31,7 @@ public interface ModDependencies {
/** /**
* Dependency types to distinguish their variants. * Dependency types to distinguish their variants.
*/ */
public enum Type { enum Type {
/** /**
* Depend on another mod * Depend on another mod
*/ */

View file

@ -23,9 +23,8 @@ public interface ModExtensions {
* Get the value of the provided extension name. * Get the value of the provided extension name.
* *
* @param modId The mod ID this extension is stored under * @param modId The mod ID this extension is stored under
* @param key The extension name to query * @param key The extension name to query
* @param <T> The type of the value of this extension * @param <T> The type of the value of this extension
*
* @return The value of the extension, or null * @return The value of the extension, or null
*/ */
<T> T get(String modId, String key); <T> T get(String modId, String key);
@ -33,11 +32,10 @@ public interface ModExtensions {
/** /**
* Get the value of the provided extension name. * Get the value of the provided extension name.
* *
* @param modId The mod ID this extension is stored under * @param modId The mod ID this extension is stored under
* @param key The extension name to query * @param key The extension name to query
* @param defaultValue A default value * @param defaultValue A default value
* @param <T> The type of the value of this extension * @param <T> The type of the value of this extension
*
* @return The value of the extension, or the default value if it isn't present * @return The value of the extension, or the default value if it isn't present
*/ */
<T> T getOrDefault(String modId, String key, T defaultValue); <T> T getOrDefault(String modId, String key, T defaultValue);
@ -45,10 +43,10 @@ public interface ModExtensions {
/** /**
* Run the given action on this extension if it is present. * Run the given action on this extension if it is present.
* *
* @param modId The mod ID this extension is stored under * @param modId The mod ID this extension is stored under
* @param key The extension name to query * @param key The extension name to query
* @param action The action to run on the value of the extension if it is present * @param action The action to run on the value of the extension if it is present
* @param <T> The type of the value of this extension * @param <T> The type of the value of this extension
*/ */
<T> void runIfPresent(String modId, String key, Consumer<T> action); <T> void runIfPresent(String modId, String key, Consumer<T> action);
@ -62,12 +60,11 @@ public interface ModExtensions {
* to retrieve an instance of the provided class. Then the provided action is * to retrieve an instance of the provided class. Then the provided action is
* run on this object. * run on this object.
* *
* @param modId The mod ID this extension is stored under * @param modId The mod ID this extension is stored under
* @param key The name of the extension * @param key The name of the extension
* @param type The class type of the extension (The class the extension class is extending/implementing) * @param type The class type of the extension (The class the extension class is extending/implementing)
* @param action The action to run on the newly retrieved instance of the provided class * @param action The action to run on the newly retrieved instance of the provided class
* @param <T> The type of the class * @param <T> The type of the class
*
* @throws ModExtensionResolutionException If the reference could not be resolved * @throws ModExtensionResolutionException If the reference could not be resolved
*/ */
<T> void runIfPresent(String modId, String key, Class<T> type, Consumer<T> action) throws ModExtensionResolutionException; <T> void runIfPresent(String modId, String key, Class<T> type, Consumer<T> action) throws ModExtensionResolutionException;

View file

@ -4,9 +4,8 @@ import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import org.jetbrains.annotations.Nullable;
import dev.frogmc.frogloader.impl.mod.ModDependenciesImpl; import dev.frogmc.frogloader.impl.mod.ModDependenciesImpl;
import org.jetbrains.annotations.Nullable;
/** /**
* A mod's properties. This class represents a mod at runtime. * A mod's properties. This class represents a mod at runtime.

View file

@ -7,8 +7,9 @@ import org.jetbrains.annotations.NotNull;
/** /**
* A plugin responsible for loading a game. * A plugin responsible for loading a game.
* Only one of these may be loaded at a time. * Only one of these may be loaded at a time.
*
* @see ModProvider
* @see FrogLoader * @see FrogLoader
* @see ModProvider
*/ */
public interface GamePlugin { public interface GamePlugin {
/** /**
@ -21,6 +22,7 @@ public interface GamePlugin {
/** /**
* Whether this plugin is applicable to be loaded in the current environment. * Whether this plugin is applicable to be loaded in the current environment.
* Only one plugin may be applicable at a time. * Only one plugin may be applicable at a time.
*
* @return Whether this plugin is applicable to be loaded * @return Whether this plugin is applicable to be loaded
*/ */
default boolean isApplicable() { default boolean isApplicable() {
@ -29,6 +31,7 @@ public interface GamePlugin {
/** /**
* Initialize this plugin. * Initialize this plugin.
*
* @param loader The loader currently loading this plugin * @param loader The loader currently loading this plugin
* @throws Exception If an exception occurs during initialization. It will be handled by the loader. * @throws Exception If an exception occurs during initialization. It will be handled by the loader.
*/ */
@ -37,6 +40,7 @@ public interface GamePlugin {
/** /**
* Queries the version of the game of this plugin. * Queries the version of the game of this plugin.
*
* @return The version of the game loaded by this plugin * @return The version of the game loaded by this plugin
*/ */
@NotNull @NotNull
@ -44,6 +48,7 @@ public interface GamePlugin {
/** /**
* Get the mod embodying the game loaded by this plugin. * Get the mod embodying the game loaded by this plugin.
*
* @return A mod for the currently loaded game. May be null if no such mod shall be added. * @return A mod for the currently loaded game. May be null if no such mod shall be added.
*/ */
default ModProperties getGameMod() { default ModProperties getGameMod() {

View file

@ -6,12 +6,13 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.function.Consumer; import java.util.function.Consumer;
import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.FrogLoader; import dev.frogmc.frogloader.api.FrogLoader;
import dev.frogmc.frogloader.api.mod.ModProperties;
/** /**
* A provider for mods to be loaded. * A provider for mods to be loaded.
* @see FrogLoader *
* @see FrogLoader
* @see GamePlugin * @see GamePlugin
* @see ModProperties * @see ModProperties
*/ */
@ -19,12 +20,14 @@ public interface ModProvider {
/** /**
* Get the ID of this provider. Mods will be stored separated by their provider ID. * Get the ID of this provider. Mods will be stored separated by their provider ID.
*
* @return The ID of this provider * @return The ID of this provider
*/ */
String id(); String id();
/** /**
* The directory to search in for mods. This will be resolved relative to the game directory. * The directory to search in for mods. This will be resolved relative to the game directory.
*
* @return The name of the mods directory, relative to the game directory * @return The name of the mods directory, relative to the game directory
*/ */
default String loadDirectory() { default String loadDirectory() {
@ -33,6 +36,7 @@ public interface ModProvider {
/** /**
* Whether this provider is applicable to load in the current environment. * Whether this provider is applicable to load in the current environment.
*
* @return Whether this provider is applicable to load * @return Whether this provider is applicable to load
*/ */
default boolean isApplicable() { default boolean isApplicable() {
@ -41,6 +45,7 @@ public interface ModProvider {
/** /**
* Whether a mod file is valid to be loaded by this provider. * Whether a mod file is valid to be loaded by this provider.
*
* @param path The path to validate * @param path The path to validate
* @return Whether this path is valid to be loaded by this provider * @return Whether this path is valid to be loaded by this provider
* @see #isDirectoryApplicable(Path) * @see #isDirectoryApplicable(Path)
@ -53,9 +58,10 @@ public interface ModProvider {
/** /**
* Whether a directory (inside the path declared by this provider's mod directory) is valid to be queried for mods * Whether a directory (inside the path declared by this provider's mod directory) is valid to be queried for mods
* to be loaded by this provider. * to be loaded by this provider.
*
* @param path The directory to be validated * @param path The directory to be validated
* @return Whether this directory should be traversed further * @return Whether this directory should be traversed further
* @see #loadDirectory() * @see #loadDirectory()
* @see #isFileApplicable(Path) * @see #isFileApplicable(Path)
*/ */
default boolean isDirectoryApplicable(Path path) { default boolean isDirectoryApplicable(Path path) {
@ -64,6 +70,7 @@ public interface ModProvider {
/** /**
* This method will be invoked just before the game is launched. It may be used for a pre-launch entrypoint for mods. * This method will be invoked just before the game is launched. It may be used for a pre-launch entrypoint for mods.
*
* @param mods The mods loaded by this provider * @param mods The mods loaded by this provider
* @throws Exception If an exception occurs during pre-launch. It will be handled by the loader. * @throws Exception If an exception occurs during pre-launch. It will be handled by the loader.
*/ */
@ -75,7 +82,7 @@ public interface ModProvider {
* This method should also load any nested mods * This method should also load any nested mods
* <p>Note: This method also needs to add mods to the classpath for them to be loaded correctly. For this, a parameter is provided.</p> * <p>Note: This method also needs to add mods to the classpath for them to be loaded correctly. For this, a parameter is provided.</p>
* *
* @param modFiles The paths to be loaded by this provider * @param modFiles The paths to be loaded by this provider
* @param classpathAdder A consumer to easily add URLs to the classpath used to run the game on * @param classpathAdder A consumer to easily add URLs to the classpath used to run the game on
* @return Mods loaded by this provider * @return Mods loaded by this provider
* @throws Exception If an exception occurs during loading. It will be handled by the loader. * @throws Exception If an exception occurs during loading. It will be handled by the loader.

View file

@ -59,20 +59,6 @@ public class LoaderGui extends JFrame {
add(this.actions, BorderLayout.SOUTH); add(this.actions, BorderLayout.SOUTH);
} }
public void setHeader(String text) {
this.header.setText(text);
}
public void addTab(String name, Component component) {
this.tabbedPane.add(name, component);
}
public void addAction(String label, ActionListener listener) {
var button = new JButton(label);
button.addActionListener(listener);
this.actions.add(button, this.actions.getComponentCount() - 2);
}
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();
@ -135,4 +121,18 @@ public class LoaderGui extends JFrame {
System.exit(0); System.exit(0);
} }
public void setHeader(String text) {
this.header.setText(text);
}
public void addTab(String name, Component component) {
this.tabbedPane.add(name, component);
}
public void addAction(String label, ActionListener listener) {
var button = new JButton(label);
button.addActionListener(listener);
this.actions.add(button, this.actions.getComponentCount() - 2);
}
} }

View file

@ -34,7 +34,7 @@ public class DependencyErrorEntry extends JPanel {
add(top, BorderLayout.NORTH); add(top, BorderLayout.NORTH);
if (icon != null) { if (icon != null) {
URL location = getClass().getResource("/"+icon); URL location = getClass().getResource("/" + icon);
if (location != null) { if (location != null) {
try { try {

View file

@ -17,13 +17,11 @@ import org.spongepowered.asm.service.IPropertyKey;
public class FrogLauncher { public class FrogLauncher {
public static final int ASM_VERSION = Opcodes.ASM9; public static final int ASM_VERSION = Opcodes.ASM9;
private static final Map<IPropertyKey, Object> globalProperties = new HashMap<>();
@Getter @Getter
private static FrogLauncher instance; private static FrogLauncher instance;
@Getter @Getter
private final MixinClassLoader targetClassLoader; private final MixinClassLoader targetClassLoader;
private static final Map<IPropertyKey, Object> globalProperties = new HashMap<>();
@Getter @Getter
private final Env env; private final Env env;

View file

@ -13,8 +13,6 @@ public interface AsmTransformer {
AccessWidener::processClass AccessWidener::processClass
); );
ClassVisitor transform(ClassReader reader, ClassVisitor cv, String name);
static byte[] transform(byte[] clazz, String name) { static byte[] transform(byte[] clazz, String name) {
ClassReader reader = new ClassReader(clazz); ClassReader reader = new ClassReader(clazz);
ClassWriter writer = new ClassWriter(0); ClassWriter writer = new ClassWriter(0);
@ -28,4 +26,6 @@ public interface AsmTransformer {
reader.accept(cv, 0); reader.accept(cv, 0);
return writer.toByteArray(); return writer.toByteArray();
} }
ClassVisitor transform(ClassReader reader, ClassVisitor cv, String name);
} }

View file

@ -3,7 +3,6 @@ package dev.frogmc.frogloader.impl.mod;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import dev.frogmc.frogloader.api.mod.ModExtensions;
import dev.frogmc.frogloader.api.mod.ModProperties; import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.impl.SemVerParseException; import dev.frogmc.frogloader.impl.SemVerParseException;

View file

@ -64,14 +64,14 @@ public class ModDependencyResolver {
presentMods.forEach((s, modProperties) -> presentOrProvided.put(s, modProperties.version())); presentMods.forEach((s, modProperties) -> presentOrProvided.put(s, modProperties.version()));
provides.forEach((s, vers) -> provides.forEach((s, vers) ->
vers.forEach(ver -> { vers.forEach(ver -> {
if (presentMods.containsKey(s)) { if (presentMods.containsKey(s)) {
if (presentMods.get(s).version().compareTo(ver.version()) < 0) { if (presentMods.get(s).version().compareTo(ver.version()) < 0) {
presentOrProvided.replace(s, ver.version()); presentOrProvided.replace(s, ver.version());
} }
} else { } else {
presentOrProvided.put(s, ver.version()); presentOrProvided.put(s, ver.version());
} }
})); }));
// Step 2: look for breakage declarations // Step 2: look for breakage declarations
Collection<BreakingModException.Entry> breaks = new HashSet<>(); Collection<BreakingModException.Entry> breaks = new HashSet<>();

View file

@ -4,19 +4,14 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleProxies; import java.lang.invoke.MethodHandleProxies;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType; import java.lang.invoke.MethodType;
import java.lang.invoke.WrongMethodTypeException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Arrays; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import dev.frogmc.frogloader.api.exception.ModExtensionResolutionException; import dev.frogmc.frogloader.api.exception.ModExtensionResolutionException;
import dev.frogmc.frogloader.api.mod.ModExtensions; import dev.frogmc.frogloader.api.mod.ModExtensions;
@ -55,43 +50,53 @@ public class ModExtensionsImpl implements ModExtensions {
action.accept((T) value); action.accept((T) value);
} }
@SuppressWarnings("unchecked")
@Override @Override
public <T> void runIfPresent(String modId, String key, Class<T> type, Consumer<T> action) public <T> void runIfPresent(String modId, String key, Class<T> type, Consumer<T> action)
throws ModExtensionResolutionException { throws ModExtensionResolutionException {
String s = get(modId, key); Object o = get(modId, key);
if (s == null) if (o == null)
return; return;
T object; List<String> items = new ArrayList<>();
if (s.contains("::")) { if (o instanceof String) {
String[] parts = s.split("::", 2); items.add((String) o);
try { } else if (o instanceof Collection<?>) {
Class<?> extension = Class.forName(parts[0]); items.addAll((Collection<? extends String>) o);
object = (T) handleReference(extension, type, parts[1]);
} catch (ModExtensionResolutionException e) {
throw e;
} catch (Throwable e) {
throw new ModExtensionResolutionException(e);
}
} else {
try {
Class<?> extension = Class.forName(s);
if (!type.isAssignableFrom(extension))
throw new ModExtensionResolutionException(extension + " does not inherit from " + type);
object = (T) MethodHandles.lookup().findConstructor(extension, MethodType.methodType(void.class))
.invoke();
} catch (ModExtensionResolutionException e) {
throw e;
} catch (Throwable e) {
throw new ModExtensionResolutionException(e);
}
} }
if (object != null) { for (String s : items) {
action.accept(object); T object;
if (s.contains("::")) {
String[] parts = s.split("::", 2);
try {
Class<?> extension = Class.forName(parts[0]);
object = (T) handleReference(extension, type, parts[1]);
} catch (ModExtensionResolutionException e) {
throw e;
} catch (Throwable e) {
throw new ModExtensionResolutionException(e);
}
} else {
try {
Class<?> extension = Class.forName(s);
if (!type.isAssignableFrom(extension))
throw new ModExtensionResolutionException(extension + " does not inherit from " + type);
object = (T) MethodHandles.lookup().findConstructor(extension, MethodType.methodType(void.class))
.invoke();
} catch (ModExtensionResolutionException e) {
throw e;
} catch (Throwable e) {
throw new ModExtensionResolutionException(e);
}
}
if (object != null) {
action.accept(object);
}
} }
} }

View file

@ -8,16 +8,13 @@ import java.nio.file.FileSystems;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.electronwill.nightconfig.core.CommentedConfig; import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.electronwill.nightconfig.core.file.FileNotFoundAction; import com.electronwill.nightconfig.core.file.FileNotFoundAction;
import com.electronwill.nightconfig.toml.TomlParser; import com.electronwill.nightconfig.toml.TomlParser;
import dev.frogmc.frogloader.api.mod.ModDependencies; import dev.frogmc.frogloader.api.mod.ModDependencies;
import dev.frogmc.frogloader.api.mod.ModExtensions;
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;
import dev.frogmc.frogloader.impl.SemVerParseException; import dev.frogmc.frogloader.impl.SemVerParseException;

View file

@ -16,7 +16,6 @@ import java.util.stream.Collectors;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
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.mod.ModExtensions;
import dev.frogmc.frogloader.api.mod.ModProperties; import dev.frogmc.frogloader.api.mod.ModProperties;
import dev.frogmc.frogloader.api.plugin.GamePlugin; import dev.frogmc.frogloader.api.plugin.GamePlugin;
import dev.frogmc.frogloader.impl.FrogLoaderImpl; import dev.frogmc.frogloader.impl.FrogLoaderImpl;
@ -37,12 +36,12 @@ public class MinecraftGamePlugin implements GamePlugin {
protected static final String CALAMUS_META_URL = "https://meta.ornithemc.net/v3/versions/gen2/intermediary/%s"; protected static final String CALAMUS_META_URL = "https://meta.ornithemc.net/v3/versions/gen2/intermediary/%s";
protected static final String CALAMUS_MAVEN_URL = "https://maven.ornithemc.net/releases/%s"; protected static final String CALAMUS_MAVEN_URL = "https://maven.ornithemc.net/releases/%s";
private static final Logger LOGGER = LoggerFactory.getLogger("Plugin/Minecraft");
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");
protected Path gamePath; protected Path gamePath;
protected String foundMainClass; protected String foundMainClass;
private String version; private String version;
@ -144,15 +143,16 @@ public class MinecraftGamePlugin implements GamePlugin {
try { try {
mappings = MojmapProvider.get(version, remappedGamePath.resolveSibling("client-" + version + ".txt")) mappings = MojmapProvider.get(version, remappedGamePath.resolveSibling("client-" + version + ".txt"))
.flattenData().reverse(); .flattenData().reverse();
} catch (NullPointerException e) { // NPE is only thrown if the mappings for this version can't be found } catch (
NullPointerException e) { // NPE is only thrown if the mappings for this version can't be found
LOGGER.info("Mojmap is not available for version {}, using ornithe's calamus as a fallback!", version); LOGGER.info("Mojmap is not available for version {}, using ornithe's calamus as a fallback!", version);
Path file = remappedGamePath.resolveSibling("calamus-"+version+".tiny"); Path file = remappedGamePath.resolveSibling("calamus-" + version + ".tiny");
if (!Files.exists(file)) { if (!Files.exists(file)) {
String location = FrogLoaderImpl.getInstance().getGson().fromJson(HttpHelper.getString(String.format(CALAMUS_META_URL, version)), JsonArray.class) String location = FrogLoaderImpl.getInstance().getGson().fromJson(HttpHelper.getString(String.format(CALAMUS_META_URL, version)), JsonArray.class)
.get(0).getAsJsonObject().get("maven").getAsString(); .get(0).getAsJsonObject().get("maven").getAsString();
String[] groups = location.split(":"); String[] groups = location.split(":");
HttpHelper.download(String.format(CALAMUS_MAVEN_URL, HttpHelper.download(String.format(CALAMUS_MAVEN_URL,
location.replaceAll("[.:]", "/")+"/"+groups[1]+"-"+groups[2]+".jar"), location.replaceAll("[.:]", "/") + "/" + groups[1] + "-" + groups[2] + ".jar"),
file); file);
} }
mappings = TinyV2Parser.parse(Files.readString(file)).flattenData(); mappings = TinyV2Parser.parse(Files.readString(file)).flattenData();
@ -166,8 +166,8 @@ public class MinecraftGamePlugin implements GamePlugin {
} else { } else {
runtimePath = gamePath; runtimePath = gamePath;
LOGGER.error("No intermediary mappings found! The game will be launched obfuscated. Mods are likely to error! " + LOGGER.error("No intermediary mappings found! The game will be launched obfuscated. Mods are likely to error! " +
"You may need to specify the path of your mappings manually. " + "You may need to specify the path of your mappings manually. " +
"Use -D" + SystemProperties.INTERMEDIARY_MAPPINGS + " to specify a file!"); "Use -D" + SystemProperties.INTERMEDIARY_MAPPINGS + " to specify a file!");
} }
} catch (Exception e) { } catch (Exception e) {
throw new IllegalStateException("Failed to remap game: ", e); throw new IllegalStateException("Failed to remap game: ", e);