package com.isteinvids.untrusted.level;
import com.isteinvids.untrusted.Prim;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.BaseLib;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.VarArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
public class LuaLevel extends BaseLib {
private final LevelManager level;
public LuaLevel(LevelManager level) {
this.level = level;
}
private static LuaTable mazeToLuaTable(int[][] maze) {
LuaTable ret = new LuaTable();
for (int i = 0; i < maze.length; i++) {
LuaTable subret = new LuaTable();
for (int j = 0; j < maze[i].length; j++) {
subret.set(j + 1, valueOf(maze[i][j]));
}
ret.set(i + 1, subret);
}
return ret;
}
@Override
public LuaValue call(LuaValue modname, LuaValue env) {
LuaTable tc = new LuaTable();
tc.set("reset", new reset());
tc.set("addentity", new addentity());
tc.set("getentity", new getentity());
tc.set("additemtype", new additemtype());
tc.set("addtileproperty", new addtileproperty());
tc.set("getsize", new getsize());
tc.set("getwidth", new getwidth());
tc.set("getheight", new getheight());
tc.set("gettile", new gettile());
tc.set("settile", new settile());
tc.set("setlevelstatus", new setlevelstatus());
tc.set("resetlevelstatus", new resetlevelstatus());
tc.set("setbackground", new setbackground());
tc.set("validateAtLeastXObjects", new validateAtLeastXObjects());
tc.set("validateExactlyXManyObjects", new validateExactlyXManyObjects());
tc.set("maze", new TwoArgFunction() {
@Override
public LuaValue call(LuaValue lv, LuaValue lv1) {
return mazeToLuaTable(Prim.createMaze(lv.checkint(), lv1.checkint()));
}
});
env.set("level", tc);
return tc;
}
private class additemtype extends TwoArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b) {
//name, json, func
if (a.isstring() && b.istable()) {
LuaTable entityTable = b.checktable();
char chr = entityTable.get("symbol").toString().charAt(0);
int colour = entityTable.get("colour").checkint();
Item item = new Item(chr, colour);
level.addItemMapping(a.toString(), item);
}
return LuaValue.NIL;
}
}
private class getsize extends VarArgFunction {
@Override
public Varargs onInvoke(Varargs args) {
return varargsOf(valueOf(level.getWidth()), valueOf(level.getHeight()));
}
}
private class getwidth extends ZeroArgFunction {
@Override
public LuaValue call() {
return valueOf(level.getWidth());
}
}
private class getheight extends ZeroArgFunction {
@Override
public LuaValue call() {
return valueOf(level.getHeight());
}
}
private class validateAtLeastXObjects extends TwoArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b) {
if (a.isnumber() && b.isstring()) {
level.validateAtLeastXObjects(a.toint(), b.toString());
}
return LuaValue.NIL;
}
}
private class validateExactlyXManyObjects extends TwoArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b) {
if (a.isnumber() && b.isstring()) {
level.validateExactlyXManyObjects(a.toint(), b.toString());
}
return LuaValue.NIL;
}
}
private class addentity extends TwoArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b) {
//name, json, func
if (a.isstring() && b.istable()) {
LuaTable entityTable = b.checktable();
char chr = entityTable.get("symbol").toString().charAt(0);
Position pos = new Position(entityTable.get("position").get(1).checkint(), entityTable.get("position").get(2).checkint());
int colour = entityTable.get("colour").checkint();
boolean collidable = entityTable.get("collidable").checkboolean();
Entity ent = level.createEntity(a.toString(), new Entity(pos, chr, colour, collidable));
Varargs entTable = LuaLevel.this.luaEntityTable(a.toString(), ent);
final String[] events = new String[]{"behavior", "onEntityCollision"};
for (String ev : events) {
if (entityTable.get(ev) != NIL) {
level.addEntityEvent(ev, b.toString(), level.luaFuncToRunnable(entityTable.get(ev).checkfunction(), entTable));
}
}
}
return LuaValue.NIL;
}
}
private class getentity extends OneArgFunction {
@Override
public LuaValue call(LuaValue a) {
//name, json, func
if (a.isstring()) {
Entity ent = level.getEntity(a.toString());
if (ent != null) {
return luaEntityTable(a.toString(), ent);
}
}
return LuaValue.NIL;
}
}
private class addtileproperty extends TwoArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b) {
if (a.isstring() && b.istable()) {
String namee = a.toString();
LuaTable tileTable = b.checktable();
Tile tile = new Tile(tileTable);
level.addTileProperty(namee, tile);
final String[] events = new String[]{"onTileCollision"};
for (String ev : events) {
if (tileTable.get(ev) != NIL) {
level.addTilePropertyEvent(ev, a.toString(), level.luaFuncToRunnable(tileTable.get(ev).checkfunction()));
}
}
}
return LuaValue.NIL;
}
}
private class settile extends ThreeArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b, LuaValue c) {
if (a.isint() && b.isint() && c.isstring()) {
level.setTile(a.toint(), b.toint(), c.toString());
}
return LuaValue.NIL;
}
}
private class gettile extends TwoArgFunction {
@Override
public LuaValue call(LuaValue a, LuaValue b) {
if (a.isint() && b.isint()) {
return LuaString.valueOf(level.getTile(a.toint(), b.toint()));
}
return LuaValue.NIL;
}
}
private class setbackground extends OneArgFunction {
@Override
public LuaValue call(LuaValue a) {
if (a.isint()) {
level.backgroundColour = a.toint();
}
// System.out.println(a.isfunction());
// a.invoke();
return LuaValue.NIL;
}
}
private class reset extends OneArgFunction {
@Override
public LuaValue call(LuaValue a) {
level.resetLevelProperties();
if (a.isstring()) {
level.setLevelStatus(a.toString());
}
return LuaValue.NIL;
}
}
private class setlevelstatus extends OneArgFunction {
@Override
public LuaValue call(LuaValue a) {
if (a.isstring()) {
level.setLevelStatus(a.toString());
}
return LuaValue.NIL;
}
}
private class resetlevelstatus extends ZeroArgFunction {
@Override
public LuaValue call() {
level.resetLevelStatus();
return LuaValue.NIL;
}
}
private LuaTable luaEntityTable(final String entName, final Entity ent) {
LuaTable table = new LuaTable();
table.set("getname", new VarArgFunction() {
@Override
public Varargs invoke(Varargs vrgs) {
return LuaValue.valueOf(entName);
}
});
table.set("getposition", new VarArgFunction() {
@Override
public Varargs invoke(Varargs vrgs) {
return LuaMain.positionToTable(ent.position);//varargsOf(valueOf(ent.position.x), valueOf(ent.position.y));
}
});
table.set("moveTowards", new VarArgFunction() {
@Override
public Varargs invoke(Varargs vrgs) {
level.moveToward(ent.position, level.player.position);
return NIL;//varargsOf(valueOf(ent.position.x), valueOf(ent.position.y));
}
});
table.set("move", new VarArgFunction() {
@Override
public Varargs invoke(Varargs vrgs) {
level.moveEntity(vrgs.arg1().toString(), entName);
return NIL;
}
});
//do objectives
return table;
}
}