73 lines
2.3 KiB
Python
73 lines
2.3 KiB
Python
|
import re
|
||
|
import string
|
||
|
from random import choices
|
||
|
import miney
|
||
|
|
||
|
|
||
|
class Lua:
|
||
|
"""
|
||
|
Lua specific functions.
|
||
|
"""
|
||
|
def __init__(self, mt: miney.Minetest):
|
||
|
self.mt = mt
|
||
|
|
||
|
def run(self, lua_code: str, timeout: float = 10.0):
|
||
|
"""
|
||
|
Run load code on the minetest server.
|
||
|
|
||
|
:param lua_code: Lua code to run
|
||
|
:param timeout: How long to wait for a result
|
||
|
:return: The return value. Multiple values as a list.
|
||
|
"""
|
||
|
# generates nearly unique id's (under 1000 collisions in 10 million values)
|
||
|
result_id = ''.join(choices(string.ascii_lowercase + string.ascii_uppercase + string.digits, k=6))
|
||
|
|
||
|
self.mt.send({"lua": lua_code, "id": result_id})
|
||
|
|
||
|
try:
|
||
|
return self.mt.receive(result_id, timeout=timeout)
|
||
|
except miney.SessionReconnected:
|
||
|
# We rerun the code, cause he was dropped during reconnect
|
||
|
return self.run(lua_code, timeout=timeout)
|
||
|
|
||
|
def run_file(self, filename):
|
||
|
"""
|
||
|
Loads and runs Lua code from a file. This is useful for debugging, cause Minetest can throws errors with
|
||
|
correct line numbers. It's also easier usable with a Lua capable IDE.
|
||
|
|
||
|
:param filename:
|
||
|
:return:
|
||
|
"""
|
||
|
with open(filename, "r") as f:
|
||
|
return self.run(f.read())
|
||
|
|
||
|
def dumps(self, data) -> str:
|
||
|
"""
|
||
|
Convert python data type to a string with lua data type.
|
||
|
|
||
|
:param data: Python data
|
||
|
:return: Lua data
|
||
|
"""
|
||
|
# credits:
|
||
|
# https://stackoverflow.com/questions/54392760/serialize-a-dict-as-lua-table/54392761#54392761
|
||
|
if type(data) is str:
|
||
|
return '"{}"'.format(re.escape(data))
|
||
|
if type(data) in (int, float):
|
||
|
return '{}'.format(data)
|
||
|
if type(data) is bool:
|
||
|
return data and "true" or "false"
|
||
|
if type(data) is list:
|
||
|
l = "{"
|
||
|
l += ", ".join([self.dumps(item) for item in data])
|
||
|
l += "}"
|
||
|
return l
|
||
|
if type(data) is dict:
|
||
|
t = "{"
|
||
|
t += ", ".join(
|
||
|
[
|
||
|
'[\"{}\"]={}'.format(re.escape(k), self.dumps(v)) for k, v in data.items()
|
||
|
]
|
||
|
)
|
||
|
t += "}"
|
||
|
return t
|
||
|
raise ValueError("Unknown type {}".format(type(data)))
|