nearly successful loading

This commit is contained in:
moehreag 2024-05-13 20:38:57 +02:00
parent edd5f5fedc
commit 5f8ed35231
11 changed files with 132 additions and 40 deletions

3
.gitignore vendored
View file

@ -41,3 +41,6 @@ bin/
### Mac OS ### ### Mac OS ###
.DS_Store .DS_Store
.idea/ .idea/
minecraft/*
!minecraft/.gitkeep

View file

@ -4,15 +4,24 @@ plugins {
} }
group = "org.example" group = "org.example"
version = "1.0-SNAPSHOT" version = "0.0.1-SNAPSHOT"
repositories { repositories {
maven {
name = "Esnesnon Maven/Snapshots"
url = uri("https://maven-esnesnon.ecorous.org/snapshots")
}
maven {
name = "Esnesnon Maven/Releases"
url = uri("https://maven-esnesnon.ecorous.org/releases")
}
maven("https://maven.fabricmc.net/") maven("https://maven.fabricmc.net/")
maven("https://repo.spongepowered.org/maven") maven("https://repo.spongepowered.org/maven")
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation("org.ecorous.esnesnon:mojmap-patcher:1.0.0-SNAPSHOT")
implementation("net.fabricmc:sponge-mixin:0.13.4+mixin.0.8.5") implementation("net.fabricmc:sponge-mixin:0.13.4+mixin.0.8.5")
implementation("org.apache.logging.log4j:log4j-slf4j2-impl:3.0.0-beta2") implementation("org.apache.logging.log4j:log4j-slf4j2-impl:3.0.0-beta2")
implementation("org.apache.logging.log4j:log4j-api:3.0.0-beta2") implementation("org.apache.logging.log4j:log4j-api:3.0.0-beta2")

0
minecraft/.gitkeep Normal file
View file

View file

@ -0,0 +1,10 @@
package io.github.moehreag.nonsense.loader.api.mod;
public interface ModProperties {
String id();
String name();
}

View file

@ -0,0 +1,11 @@
package io.github.moehreag.nonsense.loader.api.mod;
import java.util.Map;
public interface ModProvider {
ModProperties properties();
Map<String, String> entrypoints();
}

View file

@ -16,6 +16,8 @@ import java.util.Map;
import io.github.moehreag.nonsense.loader.impl.mixin.NonsenseMixinService; import io.github.moehreag.nonsense.loader.impl.mixin.NonsenseMixinService;
import lombok.Getter; import lombok.Getter;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;
import org.spongepowered.asm.launch.MixinBootstrap; import org.spongepowered.asm.launch.MixinBootstrap;
import org.spongepowered.asm.service.IPropertyKey; import org.spongepowered.asm.service.IPropertyKey;
@ -35,6 +37,7 @@ public class Launcher {
private final Env env; private final Env env;
public static void run(String[] args, Env env) { public static void run(String[] args, Env env) {
Configurator.setRootLevel(Level.INFO); // TODO replace with actual log4j config
new Launcher(args, env); new Launcher(args, env);
} }
@ -56,7 +59,7 @@ public class Launcher {
Thread.currentThread().setContextClassLoader(targetClassLoader); Thread.currentThread().setContextClassLoader(targetClassLoader);
try { try {
MethodHandle ctor = MethodHandles.publicLookup().findStatic(targetClassLoader.findClass(LoaderImpl.class.getName()), "run", MethodType.methodType(void.class, String[].class, Env.class)); MethodHandle ctor = MethodHandles.publicLookup().findStatic(targetClassLoader.loadClass(LoaderImpl.class.getName()), "run", MethodType.methodType(void.class, String[].class, Env.class));
ctor.invoke(args, env); ctor.invoke(args, env);
} catch (Throwable e) { } catch (Throwable e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View file

@ -14,6 +14,7 @@ import io.github.moehreag.nonsense.loader.impl.plugin.NonsensePlugin;
import lombok.Getter; import lombok.Getter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
public class LoaderImpl implements Loader { public class LoaderImpl implements Loader {
@ -37,16 +38,19 @@ public class LoaderImpl implements Loader {
@Getter @Getter
private final Path gameDir, configDir, modsDir; private final Path gameDir, configDir, modsDir;
public LoaderImpl(String[] args, Env env) { private LoaderImpl(String[] args, Env env) {
instance = this;
System.out.println("info logging: "+ LOGGER.isEnabledForLevel(Level.INFO));
this.args = args; this.args = args;
this.env = env; this.env = env;
gameDir = Paths.get(getArgument("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(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);
@ -54,7 +58,8 @@ public class LoaderImpl implements Loader {
discoverPlugins(); discoverPlugins();
LOGGER.info("Launching...");
plugins.forEach(NonsensePlugin::run);
} }
public static void run(String[] args, Env env) { public static void run(String[] args, Env env) {
@ -62,12 +67,12 @@ public class LoaderImpl implements Loader {
throw new IllegalStateException("Loader was started multiple times!"); throw new IllegalStateException("Loader was started multiple times!");
} }
instance = new LoaderImpl(args, env); new LoaderImpl(args, env);
} }
private void discoverPlugins() { private void discoverPlugins() {
List<String> classes = new ArrayList<>(); List<String> classes = new ArrayList<>();
this.getClass().getClassLoader().resources(PLUGIN_SERVICE_FILE_LOCATION).forEach(url -> { this.getClass().getClassLoader().resources(PLUGIN_SERVICE_FILE_LOCATION).distinct().forEach(url -> {
try (InputStream inputStream = url.openStream()) { try (InputStream inputStream = url.openStream()) {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(classes::add); new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(classes::add);
} catch (IOException e) { } catch (IOException e) {
@ -75,6 +80,7 @@ public class LoaderImpl implements Loader {
throw new UncheckedIOException(e); throw new UncheckedIOException(e);
} }
}); });
LOGGER.info("Found plugins: \n{}", String.join("\t\n", classes));
classes.stream().map((String className) -> { classes.stream().map((String className) -> {
try { try {
@ -88,7 +94,7 @@ public class LoaderImpl implements Loader {
MethodHandle ctor = MethodHandles.publicLookup().findConstructor(c, MethodType.methodType(void.class)); MethodHandle ctor = MethodHandles.publicLookup().findConstructor(c, MethodType.methodType(void.class));
NonsensePlugin plugin = (NonsensePlugin) ctor.invoke(); NonsensePlugin plugin = (NonsensePlugin) ctor.invoke();
plugins.add(plugin); plugins.add(plugin);
plugin.init(); plugin.init(this);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
LOGGER.error("Failed to instantiate plugin: ", e); LOGGER.error("Failed to instantiate plugin: ", e);
@ -98,10 +104,18 @@ public class LoaderImpl implements Loader {
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){
String res = getArgument(name);
if (res.isEmpty()){
return other;
}
return res;
}
} }

View file

@ -0,0 +1,6 @@
package io.github.moehreag.nonsense.loader.impl.mod;
import io.github.moehreag.nonsense.loader.api.mod.ModProperties;
public record BuiltinModProperties(String id, String name) implements ModProperties {
}

View file

@ -0,0 +1,9 @@
package io.github.moehreag.nonsense.loader.impl.mod;
import java.util.Map;
import io.github.moehreag.nonsense.loader.api.mod.ModProperties;
import io.github.moehreag.nonsense.loader.api.mod.ModProvider;
public record BuiltinModProvider(ModProperties properties, Map<String, String> entrypoints) implements ModProvider {
}

View file

@ -1,21 +1,14 @@
package io.github.moehreag.nonsense.loader.impl.plugin; package io.github.moehreag.nonsense.loader.impl.plugin;
import io.github.moehreag.nonsense.loader.impl.Env; import io.github.moehreag.nonsense.loader.impl.LoaderImpl;
import java.util.Collections;
import java.util.Map;
public interface NonsensePlugin extends Runnable { public interface NonsensePlugin extends Runnable {
default Map<Env, String> getEntrypoints(){ default void run() {
return Collections.emptyMap();
}
default void run(){ }
} default void init(LoaderImpl loader) {
default void init(){ }
}
} }

View file

@ -1,42 +1,74 @@
package io.github.moehreag.nonsense.loader.impl.plugin.game; package io.github.moehreag.nonsense.loader.impl.plugin.game;
import io.github.moehreag.nonsense.loader.api.Loader;
import io.github.moehreag.nonsense.loader.impl.Discovery; import io.github.moehreag.nonsense.loader.impl.Discovery;
import io.github.moehreag.nonsense.loader.impl.Env;
import io.github.moehreag.nonsense.loader.impl.LoaderImpl; import io.github.moehreag.nonsense.loader.impl.LoaderImpl;
import io.github.moehreag.nonsense.loader.impl.plugin.NonsensePlugin; import io.github.moehreag.nonsense.loader.impl.plugin.NonsensePlugin;
import org.ecorous.esnesnon.mojmap_patcher.MojMapPatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.*; import java.nio.file.*;
import java.util.Map; import java.util.ArrayList;
import java.util.List;
public class Minecraft implements NonsensePlugin { public class Minecraft implements NonsensePlugin {
private static final Logger LOGGER = LoggerFactory.getLogger("Plugin/Minecraft");
private static final String[] MINECRAFT_CLASSES = new String[]{ private static 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/Main.class" "net/minecraft/server/main/Main.class"
}; };
@Override private final List<Path> mods = new ArrayList<>();
public Map<Env, String> getEntrypoints() { private String version;
return Map.of( private Path remappedGamePath;
Env.CLIENT, "net.minecraft.client.main.Main", private String foundMainClass;
Env.SERVER, "net.minecraft.server.main.Main"
);
}
@Override @Override
public void init() { public void init(LoaderImpl loader) {
version = loader.getArgument("version");
remappedGamePath = loader.getGameDir().resolve(".nonsense/remappedJars").resolve(version).resolve("game-"+version+"-remapped.jar");
if (!Files.exists(remappedGamePath)){
try {
Files.createDirectories(remappedGamePath.getParent());
} catch (IOException e) {
LOGGER.error("Failed to create directory", e);
}
}
mods.addAll(Discovery.find(loader.getModsDir(), path ->
version.equals(path.getFileName().toString()), path ->
path.getFileName().toString().endsWith(LoaderImpl.MOD_FILE_EXTENSION)));
if (!Files.exists(remappedGamePath)){
Path gameJar = findGame();
if (gameJar == null){
throw new IllegalStateException("Could not find game jar!");
}
try {
MojMapPatcher.run(version, gameJar, remappedGamePath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} }
private Path findGame() { private Path findGame() {
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 (!Files.exists(p) || Files.isDirectory(p)){
continue;
}
try (FileSystem fs = FileSystems.newFileSystem(p)) { try (FileSystem fs = FileSystems.newFileSystem(p)) {
for (String n : MINECRAFT_CLASSES) { for (String n : MINECRAFT_CLASSES) {
if (Files.exists(fs.getPath(n))){ if (Files.exists(fs.getPath(n))){
LOGGER.info("Found game: {}", p);
foundMainClass = n.substring(0, n.length()-6).replace("/", ".");
return p; return p;
} }
} }
@ -44,18 +76,20 @@ public class Minecraft implements NonsensePlugin {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
LOGGER.warn("Could not locate game!");
return null; return null;
} }
@Override @Override
public void run() { public void run() {
Discovery.find(Loader.getInstance().getModsDir(), path -> try {
LoaderImpl.getInstance().getArgument("version") LOGGER.info("Launching main class: {}", foundMainClass);
.equals(path.getFileName().toString()), path -> //Class<?> mainClass = Class.forName(foundMainClass);
path.getFileName().toString().endsWith(LoaderImpl.MOD_FILE_EXTENSION)) //MethodHandle main = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
.forEach(path -> { //main.invoke((Object)LoaderImpl.getInstance().getArgs());
// TODO collect mods } catch (Throwable e) {
// TODO load mods e.printStackTrace();
}); throw new RuntimeException(e);
}
} }
} }