Make it not outright crash with 0xC0000005 or 0xC00000FD
This commit is contained in:
parent
9a958ecccb
commit
49d6cb0d89
@ -52,14 +52,14 @@ fun LuaThread.getLine2d(stackIndex: Int = -1): Line2d? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getVector2d(abs + 1)
|
val x = getVector2d()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getVector2d(abs + 1)
|
val y = getVector2d()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
@ -90,14 +90,14 @@ fun LuaThread.getVector2d(stackIndex: Int = -1): Vector2d? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getDouble(abs + 1)
|
val x = getDouble()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getDouble(abs + 1)
|
val y = getDouble()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
@ -128,14 +128,14 @@ fun LuaThread.getVector2f(stackIndex: Int = -1): Vector2f? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getFloat(abs + 1)
|
val x = getFloat()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getFloat(abs + 1)
|
val y = getFloat()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
@ -168,9 +168,9 @@ fun LuaThread.getVector2iOrAABB(stackIndex: Int = -1): Either<Vector2i, AABB>? {
|
|||||||
pop()
|
pop()
|
||||||
|
|
||||||
if (type == LuaType.NUMBER) {
|
if (type == LuaType.NUMBER) {
|
||||||
return Either.right(getAABB(stackIndex) ?: return null)
|
return Either.right(getAABB() ?: return null)
|
||||||
} else {
|
} else {
|
||||||
return Either.left(getVector2i(stackIndex) ?: return null)
|
return Either.left(getVector2i() ?: return null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,14 +223,14 @@ fun LuaThread.getVector2i(stackIndex: Int = -1): Vector2i? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getLong(abs + 1)
|
val x = getLong()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getLong(abs + 1)
|
val y = getLong()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
@ -262,28 +262,28 @@ fun LuaThread.getColor(stackIndex: Int = -1): RGBAColor? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getLong(abs + 1)
|
val x = getLong()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getLong(abs + 1)
|
val y = getLong()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
push(3)
|
push(3)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val z = getLong(abs + 1)
|
val z = getLong()
|
||||||
pop()
|
pop()
|
||||||
z ?: return null
|
z ?: return null
|
||||||
|
|
||||||
push(4)
|
push(4)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val w = getLong(abs + 1) ?: 255L
|
val w = getLong() ?: 255L
|
||||||
pop()
|
pop()
|
||||||
|
|
||||||
return RGBAColor(x.toInt(), y.toInt(), z.toInt(), w.toInt())
|
return RGBAColor(x.toInt(), y.toInt(), z.toInt(), w.toInt())
|
||||||
@ -313,28 +313,28 @@ fun LuaThread.getAABB(stackIndex: Int = -1): AABB? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getDouble(abs + 1)
|
val x = getDouble()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getDouble(abs + 1)
|
val y = getDouble()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
push(3)
|
push(3)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val z = getDouble(abs + 1)
|
val z = getDouble()
|
||||||
pop()
|
pop()
|
||||||
z ?: return null
|
z ?: return null
|
||||||
|
|
||||||
push(4)
|
push(4)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val w = getDouble(abs + 1)
|
val w = getDouble()
|
||||||
pop()
|
pop()
|
||||||
w ?: return null
|
w ?: return null
|
||||||
|
|
||||||
@ -343,10 +343,10 @@ fun LuaThread.getAABB(stackIndex: Int = -1): AABB? {
|
|||||||
|
|
||||||
fun LuaThread.ArgStack.nextAABB(position: Int = this.position++): AABB {
|
fun LuaThread.ArgStack.nextAABB(position: Int = this.position++): AABB {
|
||||||
if (position !in 1 ..this.top)
|
if (position !in 1 ..this.top)
|
||||||
throw IllegalArgumentException("bad argument #$position: RGBAColor expected, got nil")
|
throw IllegalArgumentException("bad argument #$position: AABB expected, got nil")
|
||||||
|
|
||||||
return lua.getAABB(position)
|
return lua.getAABB(position)
|
||||||
?: throw IllegalArgumentException("bad argument #$position: RGBAColor expected, got ${lua.typeAt(position)}")
|
?: throw IllegalArgumentException("bad argument #$position: AABB expected, got ${lua.typeAt(position)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LuaThread.ArgStack.nextOptionalAABB(position: Int = this.position++): AABB? {
|
fun LuaThread.ArgStack.nextOptionalAABB(position: Int = this.position++): AABB? {
|
||||||
@ -365,28 +365,28 @@ fun LuaThread.getAABBi(stackIndex: Int = -1): AABBi? {
|
|||||||
push(1)
|
push(1)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val x = getLong(abs + 1)
|
val x = getLong()
|
||||||
pop()
|
pop()
|
||||||
x ?: return null
|
x ?: return null
|
||||||
|
|
||||||
push(2)
|
push(2)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val y = getLong(abs + 1)
|
val y = getLong()
|
||||||
pop()
|
pop()
|
||||||
y ?: return null
|
y ?: return null
|
||||||
|
|
||||||
push(3)
|
push(3)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val z = getLong(abs + 1)
|
val z = getLong()
|
||||||
pop()
|
pop()
|
||||||
z ?: return null
|
z ?: return null
|
||||||
|
|
||||||
push(4)
|
push(4)
|
||||||
loadTableValue(abs)
|
loadTableValue(abs)
|
||||||
|
|
||||||
val w = getLong(abs + 1)
|
val w = getLong()
|
||||||
pop()
|
pop()
|
||||||
w ?: return null
|
w ?: return null
|
||||||
|
|
||||||
|
@ -5,11 +5,12 @@ import ru.dbotthepony.kstarbound.lua.userdata.LuaFuture
|
|||||||
import ru.dbotthepony.kstarbound.lua.userdata.LuaPathFinder
|
import ru.dbotthepony.kstarbound.lua.userdata.LuaPathFinder
|
||||||
import ru.dbotthepony.kstarbound.util.random.random
|
import ru.dbotthepony.kstarbound.util.random.random
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
|
import java.lang.ref.Cleaner.Cleanable
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import java.util.random.RandomGenerator
|
import java.util.random.RandomGenerator
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
class LuaSharedState(val handlesThread: LuaThread) : Closeable {
|
class LuaSharedState(val handlesThread: LuaThread, private val cleanable: Cleanable) : Closeable {
|
||||||
private val pendingFree = ConcurrentLinkedQueue<Int>()
|
private val pendingFree = ConcurrentLinkedQueue<Int>()
|
||||||
private val freeHandles = IntAVLTreeSet()
|
private val freeHandles = IntAVLTreeSet()
|
||||||
private var nextHandle = 0
|
private var nextHandle = 0
|
||||||
@ -25,10 +26,15 @@ class LuaSharedState(val handlesThread: LuaThread) : Closeable {
|
|||||||
var isValid = true
|
var isValid = true
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
fun ensureValid() {
|
||||||
|
check(isValid) { "Tried to use NULL LuaState!" }
|
||||||
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (!isValid) return
|
if (!isValid) return
|
||||||
isValid = false
|
isValid = false
|
||||||
namedHandles.clear()
|
namedHandles.clear()
|
||||||
|
cleanable.clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializeHandles(mainThread: LuaThread) {
|
fun initializeHandles(mainThread: LuaThread) {
|
||||||
@ -51,7 +57,7 @@ class LuaSharedState(val handlesThread: LuaThread) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun cleanup() {
|
fun cleanup() {
|
||||||
check(isValid) { "Shared state is no longer valid" }
|
ensureValid()
|
||||||
if (handlesInUse == 0) return
|
if (handlesInUse == 0) return
|
||||||
var handle = pendingFree.poll()
|
var handle = pendingFree.poll()
|
||||||
|
|
||||||
@ -67,7 +73,7 @@ class LuaSharedState(val handlesThread: LuaThread) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun allocateHandle(name: Any?): LuaHandle {
|
fun allocateHandle(name: Any?): LuaHandle {
|
||||||
check(isValid) { "Shared state is no longer valid" }
|
ensureValid()
|
||||||
require(name == null || name !in namedHandles) { "Named handle '$name' already exists" }
|
require(name == null || name !in namedHandles) { "Named handle '$name' already exists" }
|
||||||
handlesInUse++
|
handlesInUse++
|
||||||
|
|
||||||
@ -93,12 +99,12 @@ class LuaSharedState(val handlesThread: LuaThread) : Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getNamedHandle(key: Any): LuaHandle {
|
fun getNamedHandle(key: Any): LuaHandle {
|
||||||
check(isValid) { "Shared state is no longer valid" }
|
ensureValid()
|
||||||
return namedHandles[key] ?: throw NoSuchElementException("No such handle: $key")
|
return namedHandles[key] ?: throw NoSuchElementException("No such handle: $key")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findNamedHandle(key: Any): LuaHandle? {
|
fun findNamedHandle(key: Any): LuaHandle? {
|
||||||
check(isValid) { "Shared state is no longer valid" }
|
ensureValid()
|
||||||
return namedHandles[key]
|
return namedHandles[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,18 +56,18 @@ class LuaThread private constructor(
|
|||||||
CallContext.getCallContext(Type.SINT, arrayOf(Type.POINTER), CallingConvention.DEFAULT, false)
|
CallContext.getCallContext(Type.SINT, arrayOf(Type.POINTER), CallingConvention.DEFAULT, false)
|
||||||
)
|
)
|
||||||
|
|
||||||
this.cleanable = Cleaner.Cleanable {
|
|
||||||
LuaJNR.INSTANCE.lua_close(pointer)
|
|
||||||
panic.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
panic.setAutoRelease(false)
|
panic.setAutoRelease(false)
|
||||||
LuaJNR.INSTANCE.lua_atpanic(pointer, panic.address)
|
LuaJNR.INSTANCE.lua_atpanic(pointer, panic.address)
|
||||||
|
|
||||||
val handles = LuaJNR.INSTANCE.lua_newthread(pointer)
|
val handles = LuaJNR.INSTANCE.lua_newthread(pointer)
|
||||||
storeRef(LUA_REGISTRYINDEX)
|
LuaJNR.INSTANCE.luaL_ref(pointer, LUA_REGISTRYINDEX)
|
||||||
val handlesThread = LuaThread(handles, stringInterner)
|
val handlesThread = LuaThread(handles, stringInterner)
|
||||||
sharedState = LuaSharedState(handlesThread)
|
|
||||||
|
sharedState = LuaSharedState(handlesThread, {
|
||||||
|
LuaJNR.INSTANCE.lua_close(pointer)
|
||||||
|
panic.dispose()
|
||||||
|
})
|
||||||
|
|
||||||
sharedState.handlesThread.sharedState = sharedState
|
sharedState.handlesThread.sharedState = sharedState
|
||||||
|
|
||||||
push("__nils")
|
push("__nils")
|
||||||
@ -140,13 +140,11 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
if (cleanable != null) {
|
sharedState.close()
|
||||||
cleanable!!.clean()
|
|
||||||
sharedState.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val stackTop: Int get() {
|
val stackTop: Int get() {
|
||||||
|
sharedState.ensureValid()
|
||||||
val value = LuaJNR.INSTANCE.lua_gettop(this.pointer)
|
val value = LuaJNR.INSTANCE.lua_gettop(this.pointer)
|
||||||
check(value >= 0) { "Invalid stack top $value" }
|
check(value >= 0) { "Invalid stack top $value" }
|
||||||
return value
|
return value
|
||||||
@ -156,6 +154,7 @@ class LuaThread private constructor(
|
|||||||
* Converts the acceptable index idx into an equivalent absolute index (that is, one that does not depend on the stack size).
|
* Converts the acceptable index idx into an equivalent absolute index (that is, one that does not depend on the stack size).
|
||||||
*/
|
*/
|
||||||
fun absStackIndex(index: Int): Int {
|
fun absStackIndex(index: Int): Int {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
return index
|
return index
|
||||||
|
|
||||||
@ -173,6 +172,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun load(code: String, chunkName: String = "@main chunk") {
|
fun load(code: String, chunkName: String = "@main chunk") {
|
||||||
|
sharedState.ensureValid()
|
||||||
val bytes = code.toByteArray(charset = Charsets.UTF_8)
|
val bytes = code.toByteArray(charset = Charsets.UTF_8)
|
||||||
val buf = ByteBuffer.allocateDirect(bytes.size)
|
val buf = ByteBuffer.allocateDirect(bytes.size)
|
||||||
buf.order(ByteOrder.nativeOrder())
|
buf.order(ByteOrder.nativeOrder())
|
||||||
@ -319,6 +319,7 @@ class LuaThread private constructor(
|
|||||||
private var initCalled = false
|
private var initCalled = false
|
||||||
|
|
||||||
fun initScripts(callInit: Boolean = true): Boolean {
|
fun initScripts(callInit: Boolean = true): Boolean {
|
||||||
|
sharedState.ensureValid()
|
||||||
check(!initCalled) { "Already initialized scripts!" }
|
check(!initCalled) { "Already initialized scripts!" }
|
||||||
initCalled = true
|
initCalled = true
|
||||||
|
|
||||||
@ -362,10 +363,12 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun attach(script: AssetPath) {
|
fun attach(script: AssetPath) {
|
||||||
|
sharedState.ensureValid()
|
||||||
attach(script.fullPath)
|
attach(script.fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun attach(script: String) {
|
fun attach(script: String) {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (initCalled) {
|
if (initCalled) {
|
||||||
// minor hiccups during unpopulated script cache should be tolerable
|
// minor hiccups during unpopulated script cache should be tolerable
|
||||||
load(Starbound.readLuaScript(script).join(), "@$script")
|
load(Starbound.readLuaScript(script).join(), "@$script")
|
||||||
@ -392,6 +395,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getStringRaw(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): String? {
|
private fun getStringRaw(stackIndex: Int = -1, limit: Long = DEFAULT_STRING_LIMIT): String? {
|
||||||
|
sharedState.ensureValid()
|
||||||
require(limit <= Int.MAX_VALUE) { "Can't allocate string bigger than ${Int.MAX_VALUE} characters" }
|
require(limit <= Int.MAX_VALUE) { "Can't allocate string bigger than ${Int.MAX_VALUE} characters" }
|
||||||
val stack = MemoryStack.stackPush()
|
val stack = MemoryStack.stackPush()
|
||||||
val status = stack.mallocLong(1)
|
val status = stack.mallocLong(1)
|
||||||
@ -410,19 +414,19 @@ class LuaThread private constructor(
|
|||||||
return readBytes.toString(charset = Charsets.UTF_8)
|
return readBytes.toString(charset = Charsets.UTF_8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isCFunction(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_iscfunction(this.pointer, this.absStackIndex(stackIndex)) > 0
|
fun isCFunction(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return LuaJNR.INSTANCE.lua_iscfunction(this.pointer, this.absStackIndex(stackIndex)) > 0 }
|
||||||
fun isFunction(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.FUNCTION
|
fun isFunction(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.FUNCTION }
|
||||||
fun isInteger(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isinteger(this.pointer, this.absStackIndex(stackIndex)) > 0
|
fun isInteger(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return LuaJNR.INSTANCE.lua_isinteger(this.pointer, this.absStackIndex(stackIndex)) > 0 }
|
||||||
fun isLightUserdata(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.LIGHTUSERDATA
|
fun isLightUserdata(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.LIGHTUSERDATA }
|
||||||
fun isNil(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.NIL
|
fun isNil(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.NIL }
|
||||||
fun isNone(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.NONE
|
fun isNone(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.NONE }
|
||||||
fun isNoneOrNil(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex).let { it == LuaType.NIL || it == LuaType.NONE }
|
fun isNoneOrNil(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex).let { it == LuaType.NIL || it == LuaType.NONE } }
|
||||||
fun isNumber(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isnumber(this.pointer, this.absStackIndex(stackIndex)) > 0
|
fun isNumber(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return LuaJNR.INSTANCE.lua_isnumber(this.pointer, this.absStackIndex(stackIndex)) > 0 }
|
||||||
fun isString(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isstring(this.pointer, this.absStackIndex(stackIndex)) > 0
|
fun isString(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return LuaJNR.INSTANCE.lua_isstring(this.pointer, this.absStackIndex(stackIndex)) > 0 }
|
||||||
fun isTable(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.TABLE
|
fun isTable(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.TABLE }
|
||||||
fun isThread(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.THREAD
|
fun isThread(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.THREAD }
|
||||||
fun isUserdata(stackIndex: Int = -1): Boolean = LuaJNR.INSTANCE.lua_isuserdata(this.pointer, this.absStackIndex(stackIndex)) > 0
|
fun isUserdata(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return LuaJNR.INSTANCE.lua_isuserdata(this.pointer, this.absStackIndex(stackIndex)) > 0 }
|
||||||
fun isBoolean(stackIndex: Int = -1): Boolean = this.typeAt(stackIndex) == LuaType.BOOLEAN
|
fun isBoolean(stackIndex: Int = -1): Boolean { sharedState.ensureValid(); return this.typeAt(stackIndex) == LuaType.BOOLEAN }
|
||||||
|
|
||||||
fun getBoolean(stackIndex: Int = -1): Boolean? {
|
fun getBoolean(stackIndex: Int = -1): Boolean? {
|
||||||
if (!this.isBoolean(stackIndex))
|
if (!this.isBoolean(stackIndex))
|
||||||
@ -514,6 +518,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun typeAt(stackIndex: Int = -1): LuaType {
|
fun typeAt(stackIndex: Int = -1): LuaType {
|
||||||
|
sharedState.ensureValid()
|
||||||
return LuaType.valueOf(LuaJNR.INSTANCE.lua_type(this.pointer, stackIndex))
|
return LuaType.valueOf(LuaJNR.INSTANCE.lua_type(this.pointer, stackIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +602,7 @@ class LuaThread private constructor(
|
|||||||
push()
|
push()
|
||||||
val top = this.stackTop
|
val top = this.stackTop
|
||||||
|
|
||||||
while (LuaJNR.INSTANCE.lua_next(this.pointer, top - 1) != 0) {
|
while (LuaJNR.INSTANCE.lua_next(this.pointer, abs) != 0) {
|
||||||
val key = this.getJson(top, limit = limit)
|
val key = this.getJson(top, limit = limit)
|
||||||
val value = this.getJson(top + 1, limit = limit)
|
val value = this.getJson(top + 1, limit = limit)
|
||||||
|
|
||||||
@ -690,6 +695,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getObject(stackIndex: Int = -1): Any? {
|
fun getObject(stackIndex: Int = -1): Any? {
|
||||||
|
sharedState.ensureValid()
|
||||||
return LuaJNI.lua_tojobject(pointer.address(), stackIndex)
|
return LuaJNI.lua_tojobject(pointer.address(), stackIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,6 +791,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loadTableValue(stackIndex: Int = -2): LuaType {
|
fun loadTableValue(stackIndex: Int = -2): LuaType {
|
||||||
|
sharedState.ensureValid()
|
||||||
return LuaType.valueOf(LuaJNR.INSTANCE.lua_gettable(this.pointer, stackIndex))
|
return LuaType.valueOf(LuaJNR.INSTANCE.lua_gettable(this.pointer, stackIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,16 +857,19 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun pop(amount: Int = 1) {
|
fun pop(amount: Int = 1) {
|
||||||
|
sharedState.ensureValid()
|
||||||
require(amount >= 0) { "Invalid amount of values to pop: $amount" }
|
require(amount >= 0) { "Invalid amount of values to pop: $amount" }
|
||||||
if (amount == 0) return
|
if (amount == 0) return
|
||||||
LuaJNR.INSTANCE.lua_settop(this.pointer, -amount - 1)
|
LuaJNR.INSTANCE.lua_settop(this.pointer, -amount - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun storeGlobal(name: String) {
|
fun storeGlobal(name: String) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_setglobal(this.pointer, name)
|
LuaJNR.INSTANCE.lua_setglobal(this.pointer, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadGlobal(name: String): LuaType {
|
fun loadGlobal(name: String): LuaType {
|
||||||
|
sharedState.ensureValid()
|
||||||
return LuaType.valueOf(LuaJNR.INSTANCE.lua_getglobal(this.pointer, name))
|
return LuaType.valueOf(LuaJNR.INSTANCE.lua_getglobal(this.pointer, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1163,6 +1173,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun push(function: Fn, performanceCritical: Boolean) {
|
fun push(function: Fn, performanceCritical: Boolean) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNI.lua_pushcclosure(pointer.address()) {
|
LuaJNI.lua_pushcclosure(pointer.address()) {
|
||||||
closure(it, function, performanceCritical)
|
closure(it, function, performanceCritical)
|
||||||
}
|
}
|
||||||
@ -1213,6 +1224,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun ensureExtraCapacity(maxSize: Int): Boolean {
|
fun ensureExtraCapacity(maxSize: Int): Boolean {
|
||||||
|
sharedState.ensureValid()
|
||||||
return LuaJNR.INSTANCE.lua_checkstack(pointer, maxSize)
|
return LuaJNR.INSTANCE.lua_checkstack(pointer, maxSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1227,18 +1239,22 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun moveStackValuesOnto(other: LuaThread, amount: Int = 1) {
|
fun moveStackValuesOnto(other: LuaThread, amount: Int = 1) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_xmove(pointer, other.pointer, amount)
|
LuaJNR.INSTANCE.lua_xmove(pointer, other.pointer, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun push() {
|
fun push() {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_pushnil(this.pointer)
|
LuaJNR.INSTANCE.lua_pushnil(this.pointer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Long) {
|
fun push(value: Long) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_pushinteger(this.pointer, value)
|
LuaJNR.INSTANCE.lua_pushinteger(this.pointer, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Long?) {
|
fun push(value: Long?) {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
||||||
} else {
|
} else {
|
||||||
@ -1247,18 +1263,22 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Double) {
|
fun push(value: Double) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_pushnumber(this.pointer, value)
|
LuaJNR.INSTANCE.lua_pushnumber(this.pointer, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Float) {
|
fun push(value: Float) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_pushnumber(this.pointer, value.toDouble())
|
LuaJNR.INSTANCE.lua_pushnumber(this.pointer, value.toDouble())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Boolean) {
|
fun push(value: Boolean) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_pushboolean(this.pointer, if (value) 1 else 0)
|
LuaJNR.INSTANCE.lua_pushboolean(this.pointer, if (value) 1 else 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Double?) {
|
fun push(value: Double?) {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
||||||
} else {
|
} else {
|
||||||
@ -1267,6 +1287,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Float?) {
|
fun push(value: Float?) {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
||||||
} else {
|
} else {
|
||||||
@ -1275,6 +1296,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: Boolean?) {
|
fun push(value: Boolean?) {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
LuaJNR.INSTANCE.lua_pushnil(pointer)
|
||||||
} else {
|
} else {
|
||||||
@ -1283,6 +1305,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: String?) {
|
fun push(value: String?) {
|
||||||
|
sharedState.ensureValid()
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
push()
|
push()
|
||||||
} else {
|
} else {
|
||||||
@ -1291,10 +1314,12 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun push(value: LuaHandle) {
|
fun push(value: LuaHandle) {
|
||||||
|
sharedState.ensureValid()
|
||||||
value.push(this)
|
value.push(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pushObject(value: Any) {
|
fun pushObject(value: Any) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNI.lua_pushjobject(pointer.address(), value)
|
LuaJNI.lua_pushjobject(pointer.address(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1334,6 +1359,7 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun copy(fromIndex: Int, toIndex: Int) {
|
fun copy(fromIndex: Int, toIndex: Int) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_copy(pointer, fromIndex, toIndex)
|
LuaJNR.INSTANCE.lua_copy(pointer, fromIndex, toIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1352,18 +1378,22 @@ class LuaThread private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setTop(topIndex: Int) {
|
fun setTop(topIndex: Int) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_settop(pointer, topIndex)
|
LuaJNR.INSTANCE.lua_settop(pointer, topIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun storeRef(tableIndex: Int) {
|
fun storeRef(tableIndex: Int) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.luaL_ref(pointer, tableIndex)
|
LuaJNR.INSTANCE.luaL_ref(pointer, tableIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pushTable(arraySize: Int = 0, hashSize: Int = 0) {
|
fun pushTable(arraySize: Int = 0, hashSize: Int = 0) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_createtable(pointer, arraySize, hashSize)
|
LuaJNR.INSTANCE.lua_createtable(pointer, arraySize, hashSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTableValue(stackIndex: Int = -3) {
|
fun setTableValue(stackIndex: Int = -3) {
|
||||||
|
sharedState.ensureValid()
|
||||||
LuaJNR.INSTANCE.lua_settable(this.pointer, stackIndex)
|
LuaJNR.INSTANCE.lua_settable(this.pointer, stackIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,26 @@ sealed class LegacyWorldStorage() : WorldStorage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun saveEntities(pos: ChunkPos, entities: Collection<AbstractEntity>) {
|
override fun saveEntities(pos: ChunkPos, entities: Collection<AbstractEntity>) {
|
||||||
|
// since entities access their Lua state on save, we must collect everything before "unloading" them from memory
|
||||||
|
val uniques = HashMap<String, Vector2d>()
|
||||||
|
val entityData = ArrayList<FastByteArrayOutputStream>()
|
||||||
|
|
||||||
|
for (entity in entities) {
|
||||||
|
Starbound.legacyStoreJson {
|
||||||
|
val stream = FastByteArrayOutputStream()
|
||||||
|
val data = JsonObject()
|
||||||
|
entity.serialize(data)
|
||||||
|
VersionRegistry.make(entity.type.storeName, data).write(DataOutputStream(stream))
|
||||||
|
entityData.add(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
val uniqueID = entity.uniqueID.get()
|
||||||
|
|
||||||
|
if (uniqueID != null) {
|
||||||
|
uniques[uniqueID] = entity.position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val chunkX = pos.x
|
val chunkX = pos.x
|
||||||
val chunkY = pos.y
|
val chunkY = pos.y
|
||||||
@ -236,23 +256,11 @@ sealed class LegacyWorldStorage() : WorldStorage() {
|
|||||||
val streamEntities = DataOutputStream(BufferedOutputStream(DeflaterOutputStream(buffEntities)))
|
val streamEntities = DataOutputStream(BufferedOutputStream(DeflaterOutputStream(buffEntities)))
|
||||||
val streamUniques = DataOutputStream(BufferedOutputStream(DeflaterOutputStream(buffUniques)))
|
val streamUniques = DataOutputStream(BufferedOutputStream(DeflaterOutputStream(buffUniques)))
|
||||||
|
|
||||||
val uniques = HashMap<String, Vector2d>()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
streamEntities.writeVarInt(entities.size)
|
streamEntities.writeVarInt(entityData.size)
|
||||||
|
|
||||||
for (entity in entities) {
|
for (data in entityData) {
|
||||||
Starbound.legacyStoreJson {
|
streamEntities.write(data.array, 0, data.length)
|
||||||
val data = JsonObject()
|
|
||||||
entity.serialize(data)
|
|
||||||
VersionRegistry.make(entity.type.storeName, data).write(streamEntities)
|
|
||||||
}
|
|
||||||
|
|
||||||
val uniqueID = entity.uniqueID.get()
|
|
||||||
|
|
||||||
if (uniqueID != null) {
|
|
||||||
uniques[uniqueID] = entity.position
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
streamEntities.close()
|
streamEntities.close()
|
||||||
|
@ -264,31 +264,37 @@ class NativeLocalWorldStorage(file: File?) : WorldStorage() {
|
|||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
override fun saveEntities(pos: ChunkPos, entities: Collection<AbstractEntity>) {
|
override fun saveEntities(pos: ChunkPos, entities: Collection<AbstractEntity>) {
|
||||||
|
// since entities access their Lua state on save, we must collect everything before "unloading" them from memory
|
||||||
|
val storeData = JsonArray()
|
||||||
|
val uniques = ArrayList<Runnable>()
|
||||||
|
|
||||||
|
for (entity in entities) {
|
||||||
|
Starbound.storeJson {
|
||||||
|
val data = JsonObject()
|
||||||
|
entity.serialize(data)
|
||||||
|
storeData.add(VersionRegistry.make(entity.type.storeName, data).toJson())
|
||||||
|
|
||||||
|
if (entity.uniqueID.get() != null) {
|
||||||
|
uniques.add {
|
||||||
|
writeUniqueEntity.setString(1, entity.uniqueID.get())
|
||||||
|
writeUniqueEntity.setInt(2, pos.x)
|
||||||
|
writeUniqueEntity.setInt(3, pos.y)
|
||||||
|
writeUniqueEntity.setDouble(4, entity.position.x)
|
||||||
|
writeUniqueEntity.setDouble(5, entity.position.y)
|
||||||
|
|
||||||
|
writeUniqueEntity.execute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
executor.execute {
|
executor.execute {
|
||||||
entitiesSavepoint.execute {
|
entitiesSavepoint.execute {
|
||||||
clearUniqueEntities.setInt(1, pos.x)
|
clearUniqueEntities.setInt(1, pos.x)
|
||||||
clearUniqueEntities.setInt(2, pos.y)
|
clearUniqueEntities.setInt(2, pos.y)
|
||||||
clearUniqueEntities.execute()
|
clearUniqueEntities.execute()
|
||||||
|
|
||||||
val storeData = JsonArray()
|
uniques.forEach { it.run() }
|
||||||
|
|
||||||
for (entity in entities) {
|
|
||||||
Starbound.storeJson {
|
|
||||||
val data = JsonObject()
|
|
||||||
entity.serialize(data)
|
|
||||||
storeData.add(VersionRegistry.make(entity.type.storeName, data).toJson())
|
|
||||||
|
|
||||||
if (entity.uniqueID.get() != null) {
|
|
||||||
writeUniqueEntity.setString(1, entity.uniqueID.get())
|
|
||||||
writeUniqueEntity.setInt(2, pos.x)
|
|
||||||
writeUniqueEntity.setInt(3, pos.y)
|
|
||||||
writeUniqueEntity.setDouble(4, entity.position.x)
|
|
||||||
writeUniqueEntity.setDouble(5, entity.position.y)
|
|
||||||
|
|
||||||
writeUniqueEntity.execute()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeEntities.setInt(1, pos.x)
|
writeEntities.setInt(1, pos.x)
|
||||||
writeEntities.setInt(2, pos.y)
|
writeEntities.setInt(2, pos.y)
|
||||||
|
@ -231,7 +231,11 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk<ServerWorld, Server
|
|||||||
// bumpState(State.CAVE_LIQUID)
|
// bumpState(State.CAVE_LIQUID)
|
||||||
|
|
||||||
for (obj in world.storage.loadEntities(pos).await()) {
|
for (obj in world.storage.loadEntities(pos).await()) {
|
||||||
obj.joinWorld(world)
|
try {
|
||||||
|
obj.joinWorld(world)
|
||||||
|
} catch (err: Exception) {
|
||||||
|
LOGGER.error("Exception while spawning entity $obj in world", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bumpState(state)
|
bumpState(state)
|
||||||
|
@ -215,14 +215,13 @@ class ServerWorld private constructor(
|
|||||||
it.client.enqueueWarp(WarpAlias.Return)
|
it.client.enqueueWarp(WarpAlias.Return)
|
||||||
}
|
}
|
||||||
|
|
||||||
callUninitOnEntities()
|
|
||||||
|
|
||||||
if (!uncleanShutdown) {
|
if (!uncleanShutdown) {
|
||||||
saveMetadata()
|
saveMetadata()
|
||||||
storage.commit()
|
storage.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.close()
|
storage.close()
|
||||||
|
callUninitOnEntities()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,15 +253,50 @@ abstract class AbstractEntity : Comparable<AbstractEntity> {
|
|||||||
check(!world.entities.containsKey(entityID)) { "Duplicate entity ID: $entityID" }
|
check(!world.entities.containsKey(entityID)) { "Duplicate entity ID: $entityID" }
|
||||||
innerWorld = world
|
innerWorld = world
|
||||||
|
|
||||||
uniqueID.get()?.let {
|
try {
|
||||||
check(it !in world.uniqueEntities) { "Duplicate unique entity ID: $it" }
|
uniqueID.get()?.let {
|
||||||
world.uniqueEntities[it] = this
|
check(it !in world.uniqueEntities) { "Duplicate unique entity ID: $it" }
|
||||||
|
world.uniqueEntities[it] = this
|
||||||
|
}
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
if (world is ClientWorld) {
|
||||||
|
world.client.activeConnection?.freeEntityID(entityID)
|
||||||
|
}
|
||||||
|
|
||||||
|
innerWorld = null
|
||||||
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
world.entities[entityID] = this
|
world.entities[entityID] = this
|
||||||
world.entityList.add(this)
|
world.entityList.add(this)
|
||||||
spatialEntry = world.entityIndex.Entry(this)
|
spatialEntry = world.entityIndex.Entry(this)
|
||||||
onJoinWorld(world)
|
|
||||||
|
try {
|
||||||
|
onJoinWorld(world)
|
||||||
|
} catch (err: Throwable) {
|
||||||
|
try {
|
||||||
|
uninit(world)
|
||||||
|
} catch (err2: Exception) {
|
||||||
|
// should be harmless
|
||||||
|
err.addSuppressed(err2)
|
||||||
|
}
|
||||||
|
|
||||||
|
world.entities.remove(entityID)
|
||||||
|
world.entityList.remove(this)
|
||||||
|
spatialEntry!!.remove()
|
||||||
|
spatialEntry = null
|
||||||
|
|
||||||
|
uniqueID.get()?.let {
|
||||||
|
world.uniqueEntities.remove(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world is ClientWorld) {
|
||||||
|
world.client.activeConnection?.freeEntityID(entityID)
|
||||||
|
}
|
||||||
|
|
||||||
|
innerWorld = null
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
|
||||||
if (visibleToRemotes) {
|
if (visibleToRemotes) {
|
||||||
if (world is ClientWorld && !isRemote) {
|
if (world is ClientWorld && !isRemote) {
|
||||||
|
@ -8,6 +8,7 @@ import com.google.gson.JsonElement
|
|||||||
import com.google.gson.JsonNull
|
import com.google.gson.JsonNull
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
import ru.dbotthepony.kommons.gson.get
|
import ru.dbotthepony.kommons.gson.get
|
||||||
import ru.dbotthepony.kommons.gson.set
|
import ru.dbotthepony.kommons.gson.set
|
||||||
import ru.dbotthepony.kommons.util.Either
|
import ru.dbotthepony.kommons.util.Either
|
||||||
@ -404,9 +405,13 @@ class MonsterEntity(val variant: MonsterVariant, level: Double? = null) : ActorE
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
luaUpdate.update(delta) {
|
try {
|
||||||
luaMovement.clearControlsIfNeeded()
|
luaUpdate.update(delta) {
|
||||||
forceRegions.clear()
|
luaMovement.clearControlsIfNeeded()
|
||||||
|
forceRegions.clear()
|
||||||
|
}
|
||||||
|
} catch (err: Exception) {
|
||||||
|
LOGGER.error("Exception while ticking $this", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldDie) {
|
if (shouldDie) {
|
||||||
@ -429,4 +434,8 @@ class MonsterEntity(val variant: MonsterVariant, level: Double? = null) : ActorE
|
|||||||
override fun handleMessage(connection: Int, message: String, arguments: JsonArray): JsonElement? {
|
override fun handleMessage(connection: Int, message: String, arguments: JsonArray): JsonElement? {
|
||||||
return luaMessages.handle(message, connection == connectionID, arguments) ?: statusController.handleMessage(message, connection == connectionID, arguments)
|
return luaMessages.handle(message, connection == connectionID, arguments) ?: statusController.handleMessage(message, connection == connectionID, arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,12 @@ class StatusController(val entity: ActorEntity, val config: StatusControllerConf
|
|||||||
// provideStatusControllerBindings(this, lua) // provided through provideEntityBindings
|
// provideStatusControllerBindings(this, lua) // provided through provideEntityBindings
|
||||||
provideEntityBindings(entity, lua)
|
provideEntityBindings(entity, lua)
|
||||||
|
|
||||||
|
if (animator != null)
|
||||||
|
// FIXME: effect animator's animator is not set in stone because of legacy protocol
|
||||||
|
// god damn it
|
||||||
|
// But at least it shouldn't change in this context
|
||||||
|
provideAnimatorBindings(animator.animator, lua)
|
||||||
|
|
||||||
// TODO: Once we have brand new object-oriented Lua API, expose proper entity bindings here
|
// TODO: Once we have brand new object-oriented Lua API, expose proper entity bindings here
|
||||||
// TODO: Expose world bindings
|
// TODO: Expose world bindings
|
||||||
lua.initScripts()
|
lua.initScripts()
|
||||||
@ -261,13 +267,6 @@ class StatusController(val entity: ActorEntity, val config: StatusControllerConf
|
|||||||
} else {
|
} else {
|
||||||
animator = EffectAnimator(KOptional(config.primaryAnimationConfig.fullPath))
|
animator = EffectAnimator(KOptional(config.primaryAnimationConfig.fullPath))
|
||||||
animatorID = effectAnimators.add(animator)
|
animatorID = effectAnimators.add(animator)
|
||||||
|
|
||||||
// FIXME: effect animator's animator is not set in stone because of legacy protocol
|
|
||||||
// god damn it
|
|
||||||
// But at least it shouldn't change in this context
|
|
||||||
if (!entity.isRemote) {
|
|
||||||
provideAnimatorBindings(animator.animator, lua)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ function seqNode:run(delta, blackboard)
|
|||||||
self.calls = self.calls + 1
|
self.calls = self.calls + 1
|
||||||
local size = self.size
|
local size = self.size
|
||||||
local isSelector = self.isSelector
|
local isSelector = self.isSelector
|
||||||
`
|
|
||||||
while self.index <= size do
|
while self.index <= size do
|
||||||
local child = self.children[self.index]
|
local child = self.children[self.index]
|
||||||
local status = runAndReset(child, delta, blackboard)
|
local status = runAndReset(child, delta, blackboard)
|
||||||
|
@ -200,13 +200,13 @@ do
|
|||||||
error('require: script path must be absolute: ' .. path)
|
error('require: script path must be absolute: ' .. path)
|
||||||
end
|
end
|
||||||
|
|
||||||
if loadedScripts[path] then return unpack(loadedScripts[path]) end
|
if loadedScripts[path] then return table.unpack(loadedScripts[path]) end
|
||||||
local fn = __require(path)
|
local fn = __require(path)
|
||||||
|
|
||||||
if fn then
|
if fn then
|
||||||
local result = {fn(...)}
|
local result = {fn(...)}
|
||||||
loadedScripts[path] = result
|
loadedScripts[path] = result
|
||||||
return unpack(result)
|
return table.unpack(result)
|
||||||
else
|
else
|
||||||
print('Failed to require Lua script ' .. path)
|
print('Failed to require Lua script ' .. path)
|
||||||
loadedScripts[path] = {}
|
loadedScripts[path] = {}
|
||||||
@ -235,7 +235,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
low = 1
|
low = 1
|
||||||
high = tA
|
high = a
|
||||||
|
|
||||||
if high % 1.0 ~= 0.0 then
|
if high % 1.0 ~= 0.0 then
|
||||||
error('bad argument #1 to math.random: integer expected, got double', 2)
|
error('bad argument #1 to math.random: integer expected, got double', 2)
|
||||||
@ -249,8 +249,8 @@ do
|
|||||||
error('bad argument #2 to math.random: number expected, got ' .. tB, 2)
|
error('bad argument #2 to math.random: number expected, got ' .. tB, 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
low = tA
|
low = a
|
||||||
high = tB
|
high = b
|
||||||
|
|
||||||
if low % 1.0 ~= 0.0 then
|
if low % 1.0 ~= 0.0 then
|
||||||
error('bad argument #1 to math.random: integer expected, got double', 2)
|
error('bad argument #1 to math.random: integer expected, got double', 2)
|
||||||
@ -385,20 +385,4 @@ function mergeJson(base, with)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
string.__index = string
|
|
||||||
|
|
||||||
do
|
|
||||||
local sub = string.sub
|
|
||||||
|
|
||||||
function string:__index(key)
|
|
||||||
if type(key) == 'number' then
|
|
||||||
return sub(self, key, key)
|
|
||||||
else
|
|
||||||
return string[key]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable('', string)
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ for fnName, implName in pairs(regularQueryFunctions) do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
-- point + radius
|
-- point + radius
|
||||||
@ -190,7 +190,7 @@ for fnName, implName in pairs(regularQueryFunctions) do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -218,7 +218,7 @@ for fnName, implName in pairs(regularQueryFunctions) do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -244,7 +244,7 @@ for fnName, implName in pairs(regularQueryFunctions) do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -284,7 +284,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
-- point + radius
|
-- point + radius
|
||||||
@ -300,7 +300,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -333,7 +333,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -364,7 +364,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -423,7 +423,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
-- point + radius
|
-- point + radius
|
||||||
@ -439,7 +439,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -468,7 +468,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -495,7 +495,7 @@ do
|
|||||||
options.callScript,
|
options.callScript,
|
||||||
options.callScriptArgs or {},
|
options.callScriptArgs or {},
|
||||||
options.callScriptResult,
|
options.callScriptResult,
|
||||||
order(options.order, fullName),
|
order(options.order, fullName)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user