feat: implement rudimentary mod loader
This commit is contained in:
parent
67bca8c9e0
commit
382122c32f
@ -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}"
|
||||
|
@ -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
|
||||
|
@ -17,8 +17,9 @@
|
||||
"fabricloader": ">=0.14.11",
|
||||
"fabric-api": "*",
|
||||
"minecraft": "~1.19.3",
|
||||
"modmenu": "~1.19.3",
|
||||
"java": ">=17"
|
||||
},
|
||||
"suggests": { }
|
||||
"suggests": {
|
||||
"modmenu": "*"
|
||||
}
|
||||
}
|
@ -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<String> dependancies();
|
||||
|
@ -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();
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
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