package com.nyrds.android.lua; /** * Created by mike on 16.06.2017. * This file is part of Remixed Pixel Dungeon. */ import com.nyrds.android.util.ModdingMode; import com.nyrds.android.util.TrackedRuntimeException; import com.nyrds.pixeldungeon.ml.EventCollector; import org.apache.commons.io.input.BOMInputStream; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.luaj.vm2.Globals; import org.luaj.vm2.LoadState; import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.compiler.LuaC; import org.luaj.vm2.lib.Bit32Lib; import org.luaj.vm2.lib.CoroutineLib; import org.luaj.vm2.lib.OneArgFunction; import org.luaj.vm2.lib.PackageLib; import org.luaj.vm2.lib.ResourceFinder; import org.luaj.vm2.lib.StringLib; import org.luaj.vm2.lib.TableLib; import org.luaj.vm2.lib.jse.CoerceJavaToLua; import org.luaj.vm2.lib.jse.JseBaseLib; import org.luaj.vm2.lib.jse.JseIoLib; import org.luaj.vm2.lib.jse.JseMathLib; import org.luaj.vm2.lib.jse.JseOsLib; import java.io.InputStream; import lombok.var; public class LuaEngine implements ResourceFinder { public static final String SCRIPTS_LIB_STORAGE = "scripts/lib/storage"; public static final String LUA_DATA = "luaData"; public static final LuaTable emptyTable = new LuaTable(); static private LuaEngine engine = new LuaEngine(); private Globals globals; public static void reset() { engine = new LuaEngine(); } public LuaValue call(String method) { return globals.get(method).call(); } public LuaValue call(String method, Object arg1) { try { LuaValue methodForData = globals.get(method); return methodForData.call(CoerceJavaToLua.coerce(arg1)); } catch (LuaError err) { reportLuaError(err); } return LuaValue.NIL; } @Nullable public static LuaTable moduleInstance(String module) { LuaValue luaModule = getEngine().call("dofile", module+".lua"); if(luaModule.istable()) { return luaModule.checktable(); } EventCollector.logException("failed to load instance of lua module: "+module); return null; } @Nullable public static LuaTable module(String module) { LuaValue luaModule = getEngine().call("require", module); if(luaModule.istable()) { return luaModule.checktable(); } EventCollector.logException("failed to load lua module: "+module); return null; } private class resLoader extends OneArgFunction { public LuaValue call(LuaValue x) { return LuaValue.valueOf(ModdingMode.getResource(x.tojstring())); } } public static LuaEngine getEngine() { return engine; } private LuaEngine() { globals = new Globals(); globals.load(new JseBaseLib()); globals.load(new PackageLib()); globals.load(new Bit32Lib()); globals.load(new TableLib()); globals.load(new StringLib()); globals.load(new CoroutineLib()); globals.load(new JseMathLib()); globals.load(new JseIoLib()); globals.load(new JseOsLib()); globals.load(new MultiDexLuajavaLib()); LoadState.install(globals); LuaC.install(globals); globals.finder = this; globals.set("loadResource", new resLoader()); } private void reportLuaError(LuaError err) { throw new TrackedRuntimeException(err); } public LuaTable require(String module) { return module(module); } public void runScriptFile(@NotNull String fileName) { try { globals.loadfile(fileName).call(); } catch (LuaError err) { reportLuaError(err); } } @Override public InputStream findResource(String filename) { return new BOMInputStream(ModdingMode.getInputStream(filename)); } static public void forEach(@NotNull LuaValue arg, LuaEntryAction action) { LuaTable tbl = arg.opttable(emptyTable); var k = LuaValue.NIL; while ( true ) { var n = tbl.next(k); if ( (k = n.arg1()).isnil() ) break; action.apply(k, n.arg(2)); } } }