1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-22 17:37:38 +00:00

Allow ILuaAPIs to be exposed as a module

- cc.require now uses the internal _LOADED table to get the list of
   built-in globals. This fixes several globals not showing up on the
   list (e.g. utf8), and allows us to inject more modules from the Java
   side.

 - ILuaAPI now has a getModuleName() function. This is used to inject
   the API into the aforementioned _LOADED table, allowing it to be
   "require"d.
This commit is contained in:
Jonathan Coates
2024-02-05 18:53:24 +00:00
parent f26e443e81
commit 8db5c6bc3a
5 changed files with 73 additions and 13 deletions

View File

@@ -25,7 +25,6 @@ import org.squiddev.cobalt.lib.Bit32Lib;
import org.squiddev.cobalt.lib.CoreLibraries;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serial;
import java.nio.ByteBuffer;
@@ -49,7 +48,7 @@ public class CobaltLuaMachine implements ILuaMachine {
private @Nullable String eventFilter = null;
public CobaltLuaMachine(MachineEnvironment environment, InputStream bios) throws MachineException, IOException {
public CobaltLuaMachine(MachineEnvironment environment, InputStream bios) throws MachineException {
timeout = environment.timeout();
context = environment.context();
luaMethods = environment.luaMethods();
@@ -81,7 +80,7 @@ public class CobaltLuaMachine implements ILuaMachine {
globals.rawset("_CC_DEFAULT_SETTINGS", ValueFactory.valueOf(CoreConfig.defaultComputerSettings));
// Add default APIs
for (var api : environment.apis()) addAPI(globals, api);
for (var api : environment.apis()) addAPI(state, globals, api);
// And load the BIOS
var value = LoadState.load(state, bios, "@bios.lua", globals);
@@ -93,7 +92,7 @@ public class CobaltLuaMachine implements ILuaMachine {
timeout.addListener(timeoutListener);
}
private void addAPI(LuaTable globals, ILuaAPI api) {
private void addAPI(LuaState state, LuaTable globals, ILuaAPI api) throws LuaError {
// Add the methods of an API to the global table
var table = wrapLuaObject(api);
if (table == null) {
@@ -103,6 +102,9 @@ public class CobaltLuaMachine implements ILuaMachine {
var names = api.getNames();
for (var name : names) globals.rawset(name, table);
var moduleName = api.getModuleName();
if (moduleName != null) state.registry().getSubTable(Constants.LOADED).rawset(moduleName, table);
}
private void updateTimeout() {

View File

@@ -124,13 +124,22 @@ local function make_package(env, dir)
local package = {}
package.loaded = {
_G = _G,
bit32 = bit32,
coroutine = coroutine,
math = math,
package = package,
string = string,
table = table,
}
-- Copy everything from the global package table to this instance.
--
-- This table is an internal implementation detail - it is NOT intended to
-- be extended by user code.
local registry = debug.getregistry()
if registry and type(registry._LOADED) == "table" then
for k, v in next, registry._LOADED do
if type(k) == "string" then
package.loaded[k] = v
end
end
end
package.path = "?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua"
if turtle then
package.path = package.path .. ";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua"

View File

@@ -89,6 +89,16 @@ public class MethodTest {
x -> x.addApi(new ReturnFunction()), 50);
}
@Test
public void testModule() {
ComputerBootstrap.run(
"""
assert(require "test.module".func() == 123)
""",
x -> x.addApi(new IsModule()), 50);
}
public static class MainThread implements ILuaAPI, IPeripheral {
public final String thread = Thread.currentThread().getName();
@@ -206,7 +216,7 @@ public class MethodTest {
}
@Override
public MethodResult callMethod(ILuaContext context, int method, IArguments arguments) throws LuaException {
public MethodResult callMethod(ILuaContext context, int method, IArguments arguments) {
return MethodResult.of();
}
@@ -227,4 +237,21 @@ public class MethodTest {
return new String[]{ "func" };
}
}
public static class IsModule implements ILuaAPI {
@Override
public String[] getNames() {
return new String[0];
}
@Override
public @Nullable String getModuleName() {
return "test.module";
}
@LuaFunction
public final int func() {
return 123;
}
}
}

View File

@@ -15,6 +15,7 @@ import dan200.computercraft.core.computer.mainthread.MainThreadConfig;
import dan200.computercraft.core.filesystem.MemoryMount;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.test.core.computer.BasicEnvironment;
import org.intellij.lang.annotations.Language;
import org.junit.jupiter.api.Assertions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,7 +32,7 @@ public class ComputerBootstrap {
private static final int TPS = 20;
public static final int MAX_TIME = 10;
public static void run(String program, Consumer<Computer> setup, int maxTimes) {
public static void run(@Language("lua") String program, Consumer<Computer> setup, int maxTimes) {
var mount = new MemoryMount()
.addFile("test.lua", program)
.addFile("startup.lua", "assertion.assert(pcall(loadfile('test.lua', nil, _ENV))) os.shutdown()");
@@ -39,7 +40,7 @@ public class ComputerBootstrap {
run(mount, setup, maxTimes);
}
public static void run(String program, int maxTimes) {
public static void run(@Language("lua") String program, int maxTimes) {
run(program, x -> {
}, maxTimes);
}