From 382122c32f6e05aea76e9eaf50777babb9349bd5 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Sun, 3 Mar 2024 23:15:30 +0200 Subject: [PATCH] feat: implement rudimentary mod loader --- build.gradle | 4 +- gradle.properties | 18 +- src/assets/fabric.mod.json | 5 +- .../mcscript/EnvironmentFactory.java | 2 +- src/java/me/topchetoeu/mcscript/McScript.java | 188 ++++++++---------- src/java/me/topchetoeu/mcscript/core/Mod.java | 26 +++ .../topchetoeu/mcscript/core/ModManager.java | 103 ++++++++++ .../topchetoeu/mcscript/loader/ModLoader.java | 5 - 8 files changed, 228 insertions(+), 123 deletions(-) create mode 100644 src/java/me/topchetoeu/mcscript/core/Mod.java create mode 100644 src/java/me/topchetoeu/mcscript/core/ModManager.java delete mode 100644 src/java/me/topchetoeu/mcscript/loader/ModLoader.java diff --git a/build.gradle b/build.gradle index 3397689..dccf764 100755 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.0-SNAPSHOT' + id 'fabric-loom' version '1.5-SNAPSHOT' id 'maven-publish' } @@ -13,7 +13,7 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - implementation 'com.github.topchetoeu:jscript:v0.8.7-beta' + implementation 'com.github.topchetoeu:jscript:v0.9.2-beta' modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" diff --git a/gradle.properties b/gradle.properties index dba254b..0c8ab04 100755 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,19 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx4G -org.gradle.parallel=true +org.gradle.jvmargs = -Xmx4G +org.gradle.parallel = true # Dependencies -minecraft_version=1.19.4 -yarn_mappings=1.19.4+build.2 -loader_version=0.15.3 -fabric_version=0.87.2+1.19.4 -modmenu_version=6.3.1 +minecraft_version = 1.19.4 +yarn_mappings = 1.19.4+build.2 +loader_version = 0.15.3 +fabric_version = 0.87.2+1.19.4 +modmenu_version = 6.3.1 # Project properties -project_version=0.0.1-alpha +project_version = 0.0.1-alpha project_name = mcscript -project_group me.topchetoeu +project_group = me.topchetoeu # Dependencies diff --git a/src/assets/fabric.mod.json b/src/assets/fabric.mod.json index 14b7a86..73c03a8 100755 --- a/src/assets/fabric.mod.json +++ b/src/assets/fabric.mod.json @@ -17,8 +17,9 @@ "fabricloader": ">=0.14.11", "fabric-api": "*", "minecraft": "~1.19.3", - "modmenu": "~1.19.3", "java": ">=17" }, - "suggests": { } + "suggests": { + "modmenu": "*" + } } \ No newline at end of file diff --git a/src/java/me/topchetoeu/mcscript/EnvironmentFactory.java b/src/java/me/topchetoeu/mcscript/EnvironmentFactory.java index 2f9725a..7332db2 100644 --- a/src/java/me/topchetoeu/mcscript/EnvironmentFactory.java +++ b/src/java/me/topchetoeu/mcscript/EnvironmentFactory.java @@ -2,7 +2,7 @@ package me.topchetoeu.mcscript; import java.util.Map; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; public interface EnvironmentFactory { Iterable dependancies(); diff --git a/src/java/me/topchetoeu/mcscript/McScript.java b/src/java/me/topchetoeu/mcscript/McScript.java index 995e584..c01a80e 100755 --- a/src/java/me/topchetoeu/mcscript/McScript.java +++ b/src/java/me/topchetoeu/mcscript/McScript.java @@ -1,141 +1,121 @@ package me.topchetoeu.mcscript; -import static com.mojang.brigadier.arguments.StringArgumentType.getString; -import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; - import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Engine; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.values.Values; -import me.topchetoeu.jscript.lib.Internals; import me.topchetoeu.jscript.utils.filesystem.File; -import me.topchetoeu.jscript.utils.filesystem.Filesystem; -import me.topchetoeu.jscript.utils.filesystem.LineReader; -import me.topchetoeu.jscript.utils.filesystem.LineWriter; -import me.topchetoeu.jscript.utils.filesystem.RootFilesystem; -import me.topchetoeu.jscript.utils.filesystem.STDFilesystem; -import me.topchetoeu.jscript.utils.permissions.PermissionsManager; -import me.topchetoeu.jscript.utils.permissions.PermissionsProvider; -import me.topchetoeu.mcscript.events.ChatMessageCallback; -import me.topchetoeu.mcscript.gui.DevScreen; +import me.topchetoeu.mcscript.core.ModManager; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.server.command.CommandManager; -import net.minecraft.text.Text; public class McScript implements ModInitializer, ClientModInitializer { - private boolean openDev = false; + // private boolean openDev = false; public static final Logger LOGGER = LoggerFactory.getLogger("jscript"); - private void execute(int i, Environment env, Engine engine, String raw, MessageReceiver msg) { - try { - var res = engine.pushMsg(false, env, new Filename("repl", i + ".js"), raw, null).await(); - msg.sendInfo(Values.toReadable(new Context(engine, env), res)); - } - catch (RuntimeException e) { - msg.sendError(Values.errorToReadable(e, "")); - } - } + // private void execute(int i, Environment env, Engine engine, String raw, MessageReceiver msg) { + // try { + // var res = engine.pushMsg(false, env, new Filename("repl", i + ".js"), raw, null).await(); + // msg.sendInfo(Values.toReadable(new Context(env), res)); + // } + // catch (RuntimeException e) { + // msg.sendError(Values.errorToReadable(e, "")); + // } + // } - private Environment createEnv(String location, LineReader in, LineWriter out) { - var env = new Environment(); - var inFile = File.ofLineReader(in); - var outFile = File.ofLineWriter(out); - Internals.apply(env); + // private Environment createEnv(String location, LineReader in, LineWriter out) { + // var env = new Environment(); + // var inFile = File.ofLineReader(in); + // var outFile = File.ofLineWriter(out); + // Internals.apply(env); - var fs = new RootFilesystem(PermissionsProvider.get(env)); - fs.protocols.put("std", new STDFilesystem().add("in", inFile).add("out", outFile)); + // var fs = new RootFilesystem(PermissionsProvider.get(env)); + // fs.protocols.put("std", new STDFilesystem().add("in", inFile).add("out", outFile)); - var perms = new PermissionsManager(); + // var perms = new PermissionsManager(); - env.add(PermissionsProvider.ENV_KEY, perms); - env.add(Filesystem.ENV_KEY, fs); + // env.add(PermissionsProvider.KEY, perms); + // env.add(Filesystem.KEY, fs); - env.global.define(null, "env", true, location); - return env; - } + // env.global.define(null, "env", true, location); + // return env; + // } @Override public void onInitialize() { - var engine = new Engine(); + var mods = new ModManager("mods", "mod-data"); + try { + mods.load(); + } + catch (IOException e) { + e.printStackTrace(); + } - ServerLifecycleEvents.SERVER_STARTING.register(server -> { - engine.start(); + // ServerLifecycleEvents.CLIENT_STARTED.register((client) -> { + // var receiver = new ClientMessageReceiver(); + // mods.setSTD(null, File.ofLineWriter(receiver::sendInfo), File.ofLineWriter(receiver::sendError)); + mods.setSTD(null, File.ofLineWriter(LOGGER::info), File.ofLineWriter(LOGGER::info)); + mods.start(); + // }); - var env = createEnv("SERVER", () -> null, value -> { - for (var line : value.split("\n", -1)) LOGGER.info(line); - }); + // var engine = new Engine(); - var i = new int[1]; + // ServerLifecycleEvents.SERVER_STARTING.register(server -> { + // engine.start(); + + // var env = createEnv("SERVER", () -> null, value -> { + // for (var line : value.split("\n", -1)) LOGGER.info(line); + // }); + + // var i = new int[1]; - server.getCommandManager().getDispatcher().register(CommandManager.literal("msc") - .then(CommandManager.argument("code", greedyString()).executes(c -> { - String str = getString(c, "code"); - var receiver = new ServerCommandMessageReceiver(c.getSource()); - execute(i[0]++, env, engine, str, receiver); - return 1; - })) - ); - }); - ServerLifecycleEvents.SERVER_STOPPED.register(server -> { - engine.stop(); - }); + // server.getCommandManager().getDispatcher().register(CommandManager.literal("msc") + // .then(CommandManager.argument("code", greedyString()).executes(c -> { + // String str = getString(c, "code"); + // var receiver = new ServerCommandMessageReceiver(c.getSource()); + // execute(i[0]++, env, engine, str, receiver); + // return 1; + // })) + // ); + // }); + // ServerLifecycleEvents.SERVER_STOPPED.register(server -> { + // engine.stop(); + // }); } @net.fabricmc.api.Environment(EnvType.CLIENT) @Override public void onInitializeClient() { - var dev = new DevScreen(); - var engine = new Engine(); + // var dev = new DevScreen(); + // var engine = new Engine(); ClientLifecycleEvents.CLIENT_STARTED.register((client) -> { - try { - Files.createDirectories(Path.of("scripts")); - } - catch (IOException e) { /* so be it */ } - - var receiver = new ClientMessageReceiver(); - var env = createEnv("CLIENT", () -> null, value -> MinecraftClient.getInstance().player.sendMessage(Text.of(value))); - engine.start(); - - var i = new int[1]; - ChatMessageCallback.EVENT.register(args -> { - if (args.message.startsWith("#")) { - execute(i[0]++, env, engine, args.message.substring(1), receiver); - args.cancelled = true; - } - }); - ClientTickEvents.END_CLIENT_TICK.register((_1) -> { - if (openDev) { - client.setScreenAndRender(dev); - openDev = false; - } - }); - ClientCommandRegistrationCallback.EVENT.register((disp, _1) -> { - disp.register(ClientCommandManager.literal("dev") - .executes(c -> { - openDev = true; - return 1; - }) - ); - }); + // var i = new int[1]; + // ChatMessageCallback.EVENT.register(args -> { + // if (args.message.startsWith("#")) { + // execute(i[0]++, env, engine, args.message.substring(1), receiver); + // args.cancelled = true; + // } + // }); + // ClientTickEvents.END_CLIENT_TICK.register((_1) -> { + // if (openDev) { + // client.setScreenAndRender(dev); + // openDev = false; + // } + // }); + // ClientCommandRegistrationCallback.EVENT.register((disp, _1) -> { + // disp.register(ClientCommandManager.literal("dev") + // .executes(c -> { + // openDev = true; + // return 1; + // }) + // ); + // }); }); - ClientLifecycleEvents.CLIENT_STOPPING.register((client) -> { - engine.stop(); - }); + // ClientLifecycleEvents.CLIENT_STOPPING.register((client) -> { + // engine.stop(); + // }); } } diff --git a/src/java/me/topchetoeu/mcscript/core/Mod.java b/src/java/me/topchetoeu/mcscript/core/Mod.java new file mode 100644 index 0000000..52d7507 --- /dev/null +++ b/src/java/me/topchetoeu/mcscript/core/Mod.java @@ -0,0 +1,26 @@ +package me.topchetoeu.mcscript.core; + +import me.topchetoeu.jscript.core.Engine; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.EventLoop; +import me.topchetoeu.jscript.utils.filesystem.RootFilesystem; + +public class Mod { + public final String name; + public final String author; + public final String version; + + public final Engine loop; + public final Environment environment; + public final RootFilesystem fs; + + public Mod(String name, String author, String version, Engine loop, Environment environment, RootFilesystem fs) { + this.name = name; + this.author = author; + this.version = version; + this.loop = loop; + this.fs = fs; + this.environment = environment; + this.environment.add(EventLoop.KEY, loop); + } +} \ No newline at end of file diff --git a/src/java/me/topchetoeu/mcscript/core/ModManager.java b/src/java/me/topchetoeu/mcscript/core/ModManager.java new file mode 100644 index 0000000..9b224d5 --- /dev/null +++ b/src/java/me/topchetoeu/mcscript/core/ModManager.java @@ -0,0 +1,103 @@ +package me.topchetoeu.mcscript.core; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import me.topchetoeu.jscript.common.Filename; +import me.topchetoeu.jscript.common.json.JSON; +import me.topchetoeu.jscript.core.Compiler; +import me.topchetoeu.jscript.core.Engine; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.EventLoop; +import me.topchetoeu.jscript.lib.Internals; +import me.topchetoeu.jscript.utils.JSCompiler; +import me.topchetoeu.jscript.utils.filesystem.File; +import me.topchetoeu.jscript.utils.filesystem.Filesystem; +import me.topchetoeu.jscript.utils.filesystem.PhysicalFilesystem; +import me.topchetoeu.jscript.utils.filesystem.RootFilesystem; +import me.topchetoeu.jscript.utils.filesystem.STDFilesystem; +import me.topchetoeu.jscript.utils.modules.ModuleRepo; +import me.topchetoeu.jscript.utils.modules.RootModuleRepo; +import me.topchetoeu.jscript.utils.permissions.PermissionsManager; +import me.topchetoeu.jscript.utils.permissions.PermissionsProvider; + +public class ModManager { + public final String codeFolder, dataFolder; + public final List mods = new ArrayList<>(); + + private void loadMod(String folder) throws IOException { + var filename = Path.of(folder, "manifest.json"); + if (!filename.toFile().exists() || !filename.toFile().isFile()) return; + + var rawManifest = new String(Files.readAllBytes(filename)); + var manifest = JSON.parse(Filename.fromFile(filename.toFile()), rawManifest).map(); + + var name = manifest.string("name"); + var version = manifest.string("version"); + var author = manifest.string("author"); + var main = manifest.string("main"); + var mainSrc = new String(Files.readAllBytes(Path.of(codeFolder.toString(), name, main))); + + var env = new Environment(); + var loop = new Engine(); + + var fs = new RootFilesystem(PermissionsProvider.get(env)); + fs.protocols.put("file", new PhysicalFilesystem(Path.of(dataFolder.toString(), name).toString())); + fs.protocols.put("code", new PhysicalFilesystem(Path.of(codeFolder.toString(), name).toString())); + + Files.createDirectories(Path.of(codeFolder.toString(), name)); + + var perms = new PermissionsManager(); + perms.add("jscript.file.read:**"); + perms.add("jscript.file.read:std://in"); + perms.add("jscript.file.write:std://out"); + perms.add("jscript.file.write:std://err"); + perms.add("jscript.file.write:file://**"); + + var modules = new RootModuleRepo(); + modules.repos.put("file", ModuleRepo.ofFilesystem(fs.protocols.get("code"))); + + Internals.apply(env); + env.add(EventLoop.KEY, loop); + env.add(Filesystem.KEY, fs); + env.add(PermissionsProvider.KEY, perms); + env.add(Compiler.KEY, new JSCompiler(env)); + + loop.pushMsg(false, env, new Filename("code", main), mainSrc, null); + + var mod = new Mod(name, author, version, loop, env, fs); + mods.add(mod); + } + + public void load() throws IOException { + for (var file : Files.list(Path.of(codeFolder)).collect(Collectors.toList())) { + if (!Files.isDirectory(file)) continue; + loadMod(file.toString()); + } + } + public void setSTD(File in, File out, File err) { + var std = new STDFilesystem(); + + std.add("in", in); + std.add("out", out); + std.add("err", err); + + for (var mod : mods) { + mod.fs.protocols.put("std", std); + } + } + public void start() { + for (var mod : mods) { + mod.loop.start(); + } + } + + public ModManager(String folder, String dataFolder) { + this.codeFolder = folder; + this.dataFolder = dataFolder; + } +} \ No newline at end of file diff --git a/src/java/me/topchetoeu/mcscript/loader/ModLoader.java b/src/java/me/topchetoeu/mcscript/loader/ModLoader.java deleted file mode 100644 index 2d96922..0000000 --- a/src/java/me/topchetoeu/mcscript/loader/ModLoader.java +++ /dev/null @@ -1,5 +0,0 @@ -package me.topchetoeu.mcscript.loader; - -public interface ModLoader { - -}