feat: implement rudimentary mod loader
This commit is contained in:
parent
67bca8c9e0
commit
382122c32f
@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '1.0-SNAPSHOT'
|
id 'fabric-loom' version '1.5-SNAPSHOT'
|
||||||
id 'maven-publish'
|
id 'maven-publish'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ dependencies {
|
|||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
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-loader:${project.loader_version}"
|
||||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||||
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
|
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"
|
||||||
|
@ -14,6 +14,6 @@ modmenu_version=6.3.1
|
|||||||
|
|
||||||
project_version = 0.0.1-alpha
|
project_version = 0.0.1-alpha
|
||||||
project_name = mcscript
|
project_name = mcscript
|
||||||
project_group me.topchetoeu
|
project_group = me.topchetoeu
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
@ -17,8 +17,9 @@
|
|||||||
"fabricloader": ">=0.14.11",
|
"fabricloader": ">=0.14.11",
|
||||||
"fabric-api": "*",
|
"fabric-api": "*",
|
||||||
"minecraft": "~1.19.3",
|
"minecraft": "~1.19.3",
|
||||||
"modmenu": "~1.19.3",
|
|
||||||
"java": ">=17"
|
"java": ">=17"
|
||||||
},
|
},
|
||||||
"suggests": { }
|
"suggests": {
|
||||||
|
"modmenu": "*"
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ package me.topchetoeu.mcscript;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.core.engine.Context;
|
import me.topchetoeu.jscript.core.Context;
|
||||||
|
|
||||||
public interface EnvironmentFactory {
|
public interface EnvironmentFactory {
|
||||||
Iterable<String> dependancies();
|
Iterable<String> dependancies();
|
||||||
|
@ -1,141 +1,121 @@
|
|||||||
package me.topchetoeu.mcscript;
|
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.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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.File;
|
||||||
import me.topchetoeu.jscript.utils.filesystem.Filesystem;
|
import me.topchetoeu.mcscript.core.ModManager;
|
||||||
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 net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.ModInitializer;
|
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.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 {
|
public class McScript implements ModInitializer, ClientModInitializer {
|
||||||
private boolean openDev = false;
|
// private boolean openDev = false;
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger("jscript");
|
public static final Logger LOGGER = LoggerFactory.getLogger("jscript");
|
||||||
|
|
||||||
private void execute(int i, Environment env, Engine engine, String raw, MessageReceiver msg) {
|
// private void execute(int i, Environment env, Engine engine, String raw, MessageReceiver msg) {
|
||||||
try {
|
// try {
|
||||||
var res = engine.pushMsg(false, env, new Filename("repl", i + ".js"), raw, null).await();
|
// var res = engine.pushMsg(false, env, new Filename("repl", i + ".js"), raw, null).await();
|
||||||
msg.sendInfo(Values.toReadable(new Context(engine, env), res));
|
// msg.sendInfo(Values.toReadable(new Context(env), res));
|
||||||
}
|
// }
|
||||||
catch (RuntimeException e) {
|
// catch (RuntimeException e) {
|
||||||
msg.sendError(Values.errorToReadable(e, ""));
|
// msg.sendError(Values.errorToReadable(e, ""));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private Environment createEnv(String location, LineReader in, LineWriter out) {
|
// private Environment createEnv(String location, LineReader in, LineWriter out) {
|
||||||
var env = new Environment();
|
// var env = new Environment();
|
||||||
var inFile = File.ofLineReader(in);
|
// var inFile = File.ofLineReader(in);
|
||||||
var outFile = File.ofLineWriter(out);
|
// var outFile = File.ofLineWriter(out);
|
||||||
Internals.apply(env);
|
// Internals.apply(env);
|
||||||
|
|
||||||
var fs = new RootFilesystem(PermissionsProvider.get(env));
|
// var fs = new RootFilesystem(PermissionsProvider.get(env));
|
||||||
fs.protocols.put("std", new STDFilesystem().add("in", inFile).add("out", outFile));
|
// 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(PermissionsProvider.KEY, perms);
|
||||||
env.add(Filesystem.ENV_KEY, fs);
|
// env.add(Filesystem.KEY, fs);
|
||||||
|
|
||||||
env.global.define(null, "env", true, location);
|
// env.global.define(null, "env", true, location);
|
||||||
return env;
|
// return env;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override public void onInitialize() {
|
@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 -> {
|
// ServerLifecycleEvents.CLIENT_STARTED.register((client) -> {
|
||||||
engine.start();
|
// 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 -> {
|
// var engine = new Engine();
|
||||||
for (var line : value.split("\n", -1)) LOGGER.info(line);
|
|
||||||
});
|
|
||||||
|
|
||||||
var i = new int[1];
|
// ServerLifecycleEvents.SERVER_STARTING.register(server -> {
|
||||||
|
// engine.start();
|
||||||
|
|
||||||
server.getCommandManager().getDispatcher().register(CommandManager.literal("msc")
|
// var env = createEnv("SERVER", () -> null, value -> {
|
||||||
.then(CommandManager.argument("code", greedyString()).executes(c -> {
|
// for (var line : value.split("\n", -1)) LOGGER.info(line);
|
||||||
String str = getString(c, "code");
|
// });
|
||||||
var receiver = new ServerCommandMessageReceiver(c.getSource());
|
|
||||||
execute(i[0]++, env, engine, str, receiver);
|
// var i = new int[1];
|
||||||
return 1;
|
|
||||||
}))
|
// server.getCommandManager().getDispatcher().register(CommandManager.literal("msc")
|
||||||
);
|
// .then(CommandManager.argument("code", greedyString()).executes(c -> {
|
||||||
});
|
// String str = getString(c, "code");
|
||||||
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
|
// var receiver = new ServerCommandMessageReceiver(c.getSource());
|
||||||
engine.stop();
|
// execute(i[0]++, env, engine, str, receiver);
|
||||||
});
|
// return 1;
|
||||||
|
// }))
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
// ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
|
||||||
|
// engine.stop();
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
@net.fabricmc.api.Environment(EnvType.CLIENT)
|
@net.fabricmc.api.Environment(EnvType.CLIENT)
|
||||||
@Override public void onInitializeClient() {
|
@Override public void onInitializeClient() {
|
||||||
var dev = new DevScreen();
|
// var dev = new DevScreen();
|
||||||
var engine = new Engine();
|
// var engine = new Engine();
|
||||||
|
|
||||||
ClientLifecycleEvents.CLIENT_STARTED.register((client) -> {
|
ClientLifecycleEvents.CLIENT_STARTED.register((client) -> {
|
||||||
try {
|
// var i = new int[1];
|
||||||
Files.createDirectories(Path.of("scripts"));
|
// ChatMessageCallback.EVENT.register(args -> {
|
||||||
}
|
// if (args.message.startsWith("#")) {
|
||||||
catch (IOException e) { /* so be it */ }
|
// execute(i[0]++, env, engine, args.message.substring(1), receiver);
|
||||||
|
// args.cancelled = true;
|
||||||
var receiver = new ClientMessageReceiver();
|
// }
|
||||||
var env = createEnv("CLIENT", () -> null, value -> MinecraftClient.getInstance().player.sendMessage(Text.of(value)));
|
// });
|
||||||
engine.start();
|
// ClientTickEvents.END_CLIENT_TICK.register((_1) -> {
|
||||||
|
// if (openDev) {
|
||||||
var i = new int[1];
|
// client.setScreenAndRender(dev);
|
||||||
ChatMessageCallback.EVENT.register(args -> {
|
// openDev = false;
|
||||||
if (args.message.startsWith("#")) {
|
// }
|
||||||
execute(i[0]++, env, engine, args.message.substring(1), receiver);
|
// });
|
||||||
args.cancelled = true;
|
// ClientCommandRegistrationCallback.EVENT.register((disp, _1) -> {
|
||||||
}
|
// disp.register(ClientCommandManager.literal("dev")
|
||||||
});
|
// .executes(c -> {
|
||||||
ClientTickEvents.END_CLIENT_TICK.register((_1) -> {
|
// openDev = true;
|
||||||
if (openDev) {
|
// return 1;
|
||||||
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) -> {
|
// ClientLifecycleEvents.CLIENT_STOPPING.register((client) -> {
|
||||||
engine.stop();
|
// engine.stop();
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
src/java/me/topchetoeu/mcscript/core/Mod.java
Normal file
26
src/java/me/topchetoeu/mcscript/core/Mod.java
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
103
src/java/me/topchetoeu/mcscript/core/ModManager.java
Normal file
103
src/java/me/topchetoeu/mcscript/core/ModManager.java
Normal file
@ -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<Mod> 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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
package me.topchetoeu.mcscript.loader;
|
|
||||||
|
|
||||||
public interface ModLoader {
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user