diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Conversions.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Conversions.kt index 06a5bc9f..66ee8e62 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Conversions.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/lua/Conversions.kt @@ -19,8 +19,13 @@ import ru.dbotthepony.kommons.io.writeSignedVarLong import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kstarbound.math.AABB import ru.dbotthepony.kommons.util.IStruct2d +import ru.dbotthepony.kommons.util.IStruct2f import ru.dbotthepony.kommons.util.IStruct2i +import ru.dbotthepony.kommons.util.IStruct3d +import ru.dbotthepony.kommons.util.IStruct3f import ru.dbotthepony.kommons.util.IStruct3i +import ru.dbotthepony.kommons.util.IStruct4d +import ru.dbotthepony.kommons.util.IStruct4f import ru.dbotthepony.kommons.util.IStruct4i import ru.dbotthepony.kstarbound.json.BinaryJsonReader import ru.dbotthepony.kstarbound.math.vector.Vector2d @@ -455,6 +460,68 @@ fun TableFactory.tableFrom(collection: Collection): Table { return alloc } +fun LuaState.getLine2d(stackIndex: Int = -1): Line2d? { + val abs = this.absStackIndex(stackIndex) + + if (!this.isTable(abs)) + return null + + push(1) + loadTableValue(abs) + + val x = getVector2d(abs + 1) + pop() + x ?: return null + + push(2) + loadTableValue(abs) + + val y = getVector2d(abs + 1) + pop() + y ?: return null + + return Line2d(x, y) +} + +fun LuaState.ArgStack.getLine2d(position: Int = this.position++): Line2d { + if (position !in 1 ..this.top) + throw IllegalArgumentException("Bad argument #$position: Line2d expected, got nil") + + return lua.getLine2d(position) + ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: Line2d expected, got ${lua.typeAt(position)}") +} + +fun LuaState.getVector2d(stackIndex: Int = -1): Vector2d? { + val abs = this.absStackIndex(stackIndex) + + if (!this.isTable(abs)) + return null + + push(1) + loadTableValue(abs) + + val x = getDouble(abs + 1) + pop() + x ?: return null + + push(2) + loadTableValue(abs) + + val y = getDouble(abs + 1) + pop() + y ?: return null + + return Vector2d(x, y) +} + +fun LuaState.ArgStack.getVector2d(position: Int = this.position++): Vector2d { + if (position !in 1 ..this.top) + throw IllegalArgumentException("Bad argument #$position: Vector2d expected, got nil") + + return lua.getVector2d(position) + ?: throw IllegalArgumentException("Lua code error: Bad argument #$position: Vector2d expected, got ${lua.typeAt(position)}") +} + fun LuaState.getVector2i(stackIndex: Int = -1): Vector2i? { val abs = this.absStackIndex(stackIndex) @@ -539,3 +606,111 @@ fun LuaState.push(value: IStruct2i) { push(y) setTableValue(table) } + +fun LuaState.push(value: IStruct4f) { + pushTable(arraySize = 4) + val table = stackTop + val (x, y, z, w) = value + + push(1) + push(x) + setTableValue(table) + + push(2) + push(y) + setTableValue(table) + + push(3) + push(z) + setTableValue(table) + + push(4) + push(w) + setTableValue(table) +} + +fun LuaState.push(value: IStruct3f) { + pushTable(arraySize = 3) + val table = stackTop + val (x, y, z) = value + + push(1) + push(x) + setTableValue(table) + + push(2) + push(y) + setTableValue(table) + + push(3) + push(z) + setTableValue(table) +} + +fun LuaState.push(value: IStruct2f) { + pushTable(arraySize = 2) + val table = stackTop + val (x, y) = value + + push(1) + push(x) + setTableValue(table) + + push(2) + push(y) + setTableValue(table) +} + +fun LuaState.push(value: IStruct4d) { + pushTable(arraySize = 4) + val table = stackTop + val (x, y, z, w) = value + + push(1) + push(x) + setTableValue(table) + + push(2) + push(y) + setTableValue(table) + + push(3) + push(z) + setTableValue(table) + + push(4) + push(w) + setTableValue(table) +} + +fun LuaState.push(value: IStruct3d) { + pushTable(arraySize = 3) + val table = stackTop + val (x, y, z) = value + + push(1) + push(x) + setTableValue(table) + + push(2) + push(y) + setTableValue(table) + + push(3) + push(z) + setTableValue(table) +} + +fun LuaState.push(value: IStruct2d) { + pushTable(arraySize = 2) + val table = stackTop + val (x, y) = value + + push(1) + push(x) + setTableValue(table) + + push(2) + push(y) + setTableValue(table) +} diff --git a/src/main/resources/scripts/global.lua b/src/main/resources/scripts/global.lua index c8fd7d5a..e7e39d83 100644 --- a/src/main/resources/scripts/global.lua +++ b/src/main/resources/scripts/global.lua @@ -2,9 +2,9 @@ -- why not use _ENV anyway lol self = self or {} -local LUA_HINT_NONE = 0 -local LUA_HINT_ARRAY = 1 -local LUA_HINT_OBJECT = 2 +LUA_HINT_NONE = 0 +LUA_HINT_ARRAY = 1 +LUA_HINT_OBJECT = 2 -- this replicates original engine code, but it shouldn't work in first place local function __newindex(self, key, value) @@ -43,6 +43,95 @@ function jarray() }) end +function jremove(self, key) + if type(self) ~= 'table' then error('bad argument #1 to jremove: table expected, got ' .. type(self), 2) end + local meta = getmetatable(self) + + if meta and meta.__nils then + meta.__nils[key] = true + end + + self[key] = nil +end + +function jsize(self) + if type(self) ~= 'table' then error('bad argument #1 to jsize: table expected, got ' .. type(self), 2) end + + local elemCount = 0 + local highestIndex = 0 + local hintList = false + + local meta = getmetatable(self) + + if meta then + if meta.__typehint == LUA_HINT_ARRAY then + hintList = true + end + + local nils = meta.__nils + + if nils ~= nil then + for k, v in pairs(nils) do + if type(k) == 'number' then + highestIndex = math.max(k, highestIndex) + else + hintList = false + end + + elemCount = elemCount + 1 + end + end + end + + for k, v in pairs(self) do + if type(k) == 'number' then + highestIndex = math.max(k, highestIndex) + else + hintList = false + end + + elemCount = elemCount + 1 + end + + if hintList then + return highestIndex + else + return elemCount + end +end + +function jresize(self, target) + if type(self) ~= 'table' then error('bad argument #1 to jresize: table expected, got ' .. type(self), 2) end + + local meta = getmetatable(self) + + if meta and meta.__nils then + local indices = {} + + for k, v in pairs(meta.__nils) do + if type(k) == 'number' and k % 1.0 == 0.0 and k > target then + table.insert(indices, k) + end + end + + for i, v in ipars(indices) do + meta.__nils[v] = nil + end + end + + local indices = {} + + for k, v in pairs(self) do + if type(k) == 'number' and k % 1.0 == 0.0 and k > target then + table.insert(indices, k) + end + end + + for i, v in ipars(indices) do + self[v] = nil + end +end + local __print = __print function print(...)