Remove Lua scripting
While LuaJIT is blazing fast, Lua itself isn't that great of a language. I'd prefer to have a language with at least a native class structure. AngelScript commits coming soon.master
parent
745f53a731
commit
1a235adb40
|
@ -63,10 +63,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pie")
|
||||
endif()
|
||||
endif()
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# Fix LuaJIT failing to run on OS X
|
||||
link_libraries("-pagezero_size 10000 -image_base 100000000")
|
||||
endif()
|
||||
|
||||
message(">> Using ${CMAKE_BUILD_TYPE} build configuration")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -DDEBUG -g")
|
||||
|
@ -87,7 +83,6 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/ext/etc")
|
|||
find_package(glm QUIET)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(LuaJIT REQUIRED)
|
||||
|
||||
find_package(meiose REQUIRED)
|
||||
if(NOT MEIOSE_FOUND)
|
||||
|
@ -104,7 +99,6 @@ include_directories(BEFORE
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
${ETC_INCLUDE_DIRS}
|
||||
${MEIOSE_INCLUDE_DIR}
|
||||
${LUA_INCLUDE_DIR}
|
||||
${LZO_INCLUDE_DIRS}
|
||||
${ENET_INCLUDE_DIRS}
|
||||
${GLFW_INCLUDE_DIRS}
|
||||
|
@ -170,7 +164,6 @@ target_link_libraries(diggler
|
|||
${LIBS}
|
||||
${ETC_LIBRARIES}
|
||||
${MEIOSE_LIBRARY}
|
||||
${LUA_LIBRARY}
|
||||
${LZO_LIBRARIES}
|
||||
${ENET_LIBRARIES}
|
||||
${GLFW_LIBRARIES}
|
||||
|
@ -193,10 +186,6 @@ if(NOT WIN32 AND NOT MINGW)
|
|||
add_custom_command(TARGET diggler PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink "${PATH_TO_TOPDIR}/assets"
|
||||
"${PROJECT_BINARY_DIR}/assets")
|
||||
|
||||
add_custom_command(TARGET diggler PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/src/scripting/lua/api"
|
||||
"${PROJECT_BINARY_DIR}/assets/lua/ffi")
|
||||
endif()
|
||||
|
||||
#install(TARGETS digglerz RUNTIME DESTINATION bin)
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
local rtpath = digglerNative.gameLuaRuntimePath
|
||||
package.path = package.path .. ';' .. rtpath .. '/?.lua;' .. rtpath .. '/lds/?.lua'
|
||||
|
||||
ffi = require('ffi')
|
||||
io = require('io')
|
||||
debug = require('debug')
|
||||
local STP = require "StackTracePlus"
|
||||
debug.traceback = STP.stacktrace
|
||||
|
||||
diggler = {
|
||||
mods = {},
|
||||
modOverlays = {},
|
||||
modsById = {},
|
||||
|
||||
publicEnv = {},
|
||||
exportedFuncs = {}
|
||||
}
|
||||
|
||||
ffi.cdef[[
|
||||
struct Diggler_Game;
|
||||
|
||||
union PtrConvert {
|
||||
void *ptr;
|
||||
char str[sizeof(void*)];
|
||||
};
|
||||
]]
|
||||
do
|
||||
local cvt = ffi.new('union PtrConvert', {str = digglerNative.gameInstancePtrStr})
|
||||
diggler.gameInstance = ffi.cast('struct Diggler_Game*', cvt.ptr)
|
||||
end
|
||||
|
||||
function diggler.export(name, func)
|
||||
diggler.exportedFuncs[name] = func
|
||||
end
|
||||
|
||||
|
||||
package.loaded['diggler'] = diggler
|
||||
--package.loaded['lds'] = require('lds')
|
||||
|
||||
local function setoverlay(tab, orig)
|
||||
local mt = getmetatable(tab) or {}
|
||||
mt.__index = function (tab, key)
|
||||
if rawget(tab, key) ~= nil then
|
||||
return rawget(tab, key)
|
||||
else
|
||||
return orig[key]
|
||||
end
|
||||
end
|
||||
setmetatable(tab, mt)
|
||||
end
|
||||
|
||||
diggler.MODSTATUS = {
|
||||
UNAVAILABLE = 0,
|
||||
DISABLED = 1,
|
||||
ERRORED = 2,
|
||||
LOADED = 10,
|
||||
INITIALIZED = 20,
|
||||
DEINITIALIZED = 90,
|
||||
UNLOADED = 100
|
||||
}
|
||||
|
||||
local match = string.match
|
||||
local function trim(s)
|
||||
return match(s,'^()%s*$') and '' or match(s,'^%s*(.*%S)')
|
||||
end
|
||||
|
||||
diggler.modGlobalOverrides = {
|
||||
collectgarbage = function(opt, ...)
|
||||
if opt == 'count' or opt == 'collect' then
|
||||
return collectgarbage(opt)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
function diggler.loadModLua(path)
|
||||
local digglerOverlay = {}
|
||||
local packageOverlay = { ['path'] = path .. '/?.lua;' .. package.path }
|
||||
setoverlay(packageOverlay, package)
|
||||
setoverlay(digglerOverlay, diggler.publicEnv)
|
||||
local env = {
|
||||
package = packageOverlay,
|
||||
diggler = digglerOverlay,
|
||||
print = function (...)
|
||||
print("<init " .. path .. ">", ...)
|
||||
end,
|
||||
CurrentModPath = path
|
||||
}
|
||||
for k, v in pairs({
|
||||
require = function (module)
|
||||
if module == 'diggler' then
|
||||
return digglerOverlay
|
||||
end
|
||||
return require(module)
|
||||
end,
|
||||
dofile = function (name)
|
||||
local f, e = loadfile(name)
|
||||
if not f then error(e, 2) end
|
||||
setfenv(f, env)
|
||||
return f()
|
||||
end,
|
||||
loadfile = function (name)
|
||||
if name == nil then
|
||||
return
|
||||
end
|
||||
local f, e = loadfile(name)
|
||||
if f then
|
||||
setfenv(f, env)
|
||||
end
|
||||
return f, e
|
||||
end,
|
||||
loadstring = function (string, chunkname)
|
||||
local f = loadstring(string, chunkname)
|
||||
if f then
|
||||
setfenv(f, env)
|
||||
end
|
||||
return f
|
||||
end
|
||||
}) do
|
||||
env[k] = v
|
||||
end
|
||||
for k, v in pairs(diggler.modGlobalOverrides) do
|
||||
env[k] = v
|
||||
end
|
||||
env['_G'] = env
|
||||
setoverlay(env, _G)
|
||||
|
||||
local file = io.open(path .. '/mod.lua', "r")
|
||||
if file == nil then
|
||||
error("mod.lua not found")
|
||||
end
|
||||
local untrusted_code = file:read('*a')
|
||||
file:close()
|
||||
|
||||
if untrusted_code:byte(1) == 27 then error("binary bytecode prohibited") end
|
||||
local untrusted_function, message = loadstring(untrusted_code)
|
||||
if not untrusted_function then error(message) end
|
||||
setfenv(untrusted_function, env)
|
||||
local status, ret = pcall(untrusted_function)
|
||||
|
||||
--- Sanity checks
|
||||
if ret == nil then
|
||||
error("No mod table returned")
|
||||
end
|
||||
local fieldChecks = {'uuid', 'id', 'name', 'version', 'versionStr'}
|
||||
for _, field in ipairs(fieldChecks) do
|
||||
if ret[field] == nil then
|
||||
error(field .. " is nil")
|
||||
end
|
||||
end
|
||||
do -- UUID
|
||||
if type(ret.uuid) ~= 'string' then
|
||||
error("uuid isn't a string")
|
||||
end
|
||||
if ret.uuid:len() ~= 22 then
|
||||
error("uuid is of length " .. ret.uuid:len() .. ", expected 22")
|
||||
end
|
||||
local uuidInvalid = ret.uuid:match('[^a-zA-Z0-9+/]')
|
||||
if uuidInvalid ~= nil and uuidInvalid ~= "" then
|
||||
error("uuid contains invalid characters: " .. uuidInvalid)
|
||||
end
|
||||
end
|
||||
do -- ID
|
||||
if type(ret.id) ~= 'string' then
|
||||
error("id isn't a string")
|
||||
end
|
||||
if ret.id:len() == 0 or trim(ret.id):len() == 0 then
|
||||
error("id is empty")
|
||||
end
|
||||
if ret.id:match('%s') ~= nil then
|
||||
error("id contains whitespace")
|
||||
end
|
||||
local punct = ret.id:match('[^%a%d]')
|
||||
if punct ~= nil and punct ~= "" then
|
||||
error("id contains non-letter/non-digit characters: '" .. punct .. "'")
|
||||
end
|
||||
end
|
||||
do -- Version number
|
||||
if type(ret.version) ~= 'number' then
|
||||
error("version isn't a number")
|
||||
end
|
||||
end
|
||||
do -- Version string
|
||||
if type(ret.versionStr) ~= 'string' then
|
||||
error("versionStr isn't a string")
|
||||
end
|
||||
end
|
||||
|
||||
--- Setup actual mod environment
|
||||
env.CurrentMod = ret
|
||||
|
||||
diggler.modOverlays[ret.uuid] = {
|
||||
['env'] = env,
|
||||
['package'] = packageOverlay,
|
||||
['diggler'] = digglerOverlay
|
||||
}
|
||||
|
||||
env.print = function (...)
|
||||
print(env.CurrentMod.id..":", ...)
|
||||
end
|
||||
for name, func in pairs(diggler.exportedFuncs) do
|
||||
digglerOverlay[name] = function (...)
|
||||
func(env.CurrentMod, ...)
|
||||
end
|
||||
end
|
||||
|
||||
if status then
|
||||
return ret, nil
|
||||
end
|
||||
return status, ret
|
||||
end
|
||||
|
||||
function diggler.loadMod(path)
|
||||
local mod, err = diggler.loadModLua(path)
|
||||
if mod then
|
||||
if diggler.mods[mod.uuid] then
|
||||
error("Mod '" .. mod.id .. "' already loaded")
|
||||
end
|
||||
mod.status = diggler.MODSTATUS.LOADED
|
||||
diggler.mods[mod.uuid] = mod
|
||||
diggler.modsById[mod.id] = mod
|
||||
print("Loaded mod '" .. mod.name .. "' <" .. mod.uuid .. " " .. mod.id .. "> v" .. mod.versionStr .. " (" .. mod.version .. ")")
|
||||
return mod
|
||||
else
|
||||
print("Error loading mod: " .. err)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function diggler.initMod(mod)
|
||||
mod.init()
|
||||
mod.status = diggler.MODSTATUS.INITIALIZED
|
||||
end
|
||||
|
||||
function diggler.getMod(mod, id)
|
||||
return diggler.modsById[id]
|
||||
end
|
||||
diggler.export("getMod", diggler.getMod)
|
||||
|
||||
function diggler.getModByUuid(mod, uuid)
|
||||
return diggler.mods[uuid]
|
||||
end
|
||||
diggler.export("getMod", diggler.getMod)
|
||||
|
||||
--[[
|
||||
function diggler.registerBlock(mod, name, block)
|
||||
print("Calling registerBlock from mod " .. (mod and mod.id or "<none>"))
|
||||
end
|
||||
diggler.export("registerBlock", diggler.registerBlock)
|
||||
]]
|
||||
dofile(rtpath .. '/api/io.lua')
|
||||
dofile(rtpath .. '/api/registerBlock.lua')
|
||||
|
|
@ -1,415 +0,0 @@
|
|||
-- tables
|
||||
local _G = _G
|
||||
local string, io, debug, coroutine = string, io, debug, coroutine
|
||||
|
||||
-- functions
|
||||
local tostring, print, require = tostring, print, require
|
||||
local next, assert = next, assert
|
||||
local pcall, type, pairs, ipairs = pcall, type, pairs, ipairs
|
||||
local error = error
|
||||
|
||||
assert(debug, "debug table must be available at this point")
|
||||
|
||||
local io_open = io.open
|
||||
local string_gmatch = string.gmatch
|
||||
local string_sub = string.sub
|
||||
local table_concat = table.concat
|
||||
|
||||
local _M = {
|
||||
max_tb_output_len = 70 -- controls the maximum length of the 'stringified' table before cutting with ' (more...)'
|
||||
}
|
||||
|
||||
-- this tables should be weak so the elements in them won't become uncollectable
|
||||
local m_known_tables = { [_G] = "_G (global table)" }
|
||||
local function add_known_module(name, desc)
|
||||
local ok, mod = pcall(require, name)
|
||||
if ok then
|
||||
m_known_tables[mod] = desc
|
||||
end
|
||||
end
|
||||
|
||||
add_known_module("string", "string module")
|
||||
add_known_module("io", "io module")
|
||||
add_known_module("os", "os module")
|
||||
add_known_module("table", "table module")
|
||||
add_known_module("math", "math module")
|
||||
add_known_module("package", "package module")
|
||||
add_known_module("debug", "debug module")
|
||||
add_known_module("coroutine", "coroutine module")
|
||||
|
||||
-- lua5.2
|
||||
add_known_module("bit32", "bit32 module")
|
||||
-- luajit
|
||||
add_known_module("bit", "bit module")
|
||||
add_known_module("jit", "jit module")
|
||||
-- lua5.3
|
||||
if _VERSION >= "Lua 5.3" then
|
||||
add_known_module("utf8", "utf8 module")
|
||||
end
|
||||
|
||||
|
||||
local m_user_known_tables = {}
|
||||
|
||||
local m_known_functions = {}
|
||||
for _, name in ipairs{
|
||||
-- Lua 5.2, 5.1
|
||||
"assert",
|
||||
"collectgarbage",
|
||||
"dofile",
|
||||
"error",
|
||||
"getmetatable",
|
||||
"ipairs",
|
||||
"load",
|
||||
"loadfile",
|
||||
"next",
|
||||
"pairs",
|
||||
"pcall",
|
||||
"print",
|
||||
"rawequal",
|
||||
"rawget",
|
||||
"rawlen",
|
||||
"rawset",
|
||||
"require",
|
||||
"select",
|
||||
"setmetatable",
|
||||
"tonumber",
|
||||
"tostring",
|
||||
"type",
|
||||
"xpcall",
|
||||
|
||||
-- Lua 5.1
|
||||
"gcinfo",
|
||||
"getfenv",
|
||||
"loadstring",
|
||||
"module",
|
||||
"newproxy",
|
||||
"setfenv",
|
||||
"unpack",
|
||||
-- TODO: add table.* etc functions
|
||||
} do
|
||||
if _G[name] then
|
||||
m_known_functions[_G[name]] = name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local m_user_known_functions = {}
|
||||
|
||||
local function safe_tostring (value)
|
||||
local ok, err = pcall(tostring, value)
|
||||
if ok then return err else return ("<failed to get printable value>: '%s'"):format(err) end
|
||||
end
|
||||
|
||||
-- Private:
|
||||
-- Parses a line, looking for possible function definitions (in a very naïve way)
|
||||
-- Returns '(anonymous)' if no function name was found in the line
|
||||
local function ParseLine(line)
|
||||
assert(type(line) == "string")
|
||||
--print(line)
|
||||
local match = line:match("^%s*function%s+(%w+)")
|
||||
if match then
|
||||
--print("+++++++++++++function", match)
|
||||
return match
|
||||
end
|
||||
match = line:match("^%s*local%s+function%s+(%w+)")
|
||||
if match then
|
||||
--print("++++++++++++local", match)
|
||||
return match
|
||||
end
|
||||
match = line:match("^%s*local%s+(%w+)%s+=%s+function")
|
||||
if match then
|
||||
--print("++++++++++++local func", match)
|
||||
return match
|
||||
end
|
||||
match = line:match("%s*function%s*%(") -- this is an anonymous function
|
||||
if match then
|
||||
--print("+++++++++++++function2", match)
|
||||
return "(anonymous)"
|
||||
end
|
||||
return "(anonymous)"
|
||||
end
|
||||
|
||||
-- Private:
|
||||
-- Tries to guess a function's name when the debug info structure does not have it.
|
||||
-- It parses either the file or the string where the function is defined.
|
||||
-- Returns '?' if the line where the function is defined is not found
|
||||
local function GuessFunctionName(info)
|
||||
--print("guessing function name")
|
||||
if type(info.source) == "string" and info.source:sub(1,1) == "@" then
|
||||
local file, err = io_open(info.source:sub(2), "r")
|
||||
if not file then
|
||||
print("file not found: "..tostring(err)) -- whoops!
|
||||
return "?"
|
||||
end
|
||||
local line
|
||||
for _ = 1, info.linedefined do
|
||||
line = file:read("*l")
|
||||
end
|
||||
if not line then
|
||||
print("line not found") -- whoops!
|
||||
return "?"
|
||||
end
|
||||
return ParseLine(line)
|
||||
else
|
||||
local line
|
||||
local lineNumber = 0
|
||||
for l in string_gmatch(info.source, "([^\n]+)\n-") do
|
||||
lineNumber = lineNumber + 1
|
||||
if lineNumber == info.linedefined then
|
||||
line = l
|
||||
break
|
||||
end
|
||||
end
|
||||
if not line then
|
||||
print("line not found") -- whoops!
|
||||
return "?"
|
||||
end
|
||||
return ParseLine(line)
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- Dumper instances are used to analyze stacks and collect its information.
|
||||
--
|
||||
local Dumper = {}
|
||||
|
||||
Dumper.new = function(thread)
|
||||
local t = { lines = {} }
|
||||
for k,v in pairs(Dumper) do t[k] = v end
|
||||
|
||||
t.dumping_same_thread = (thread == coroutine.running())
|
||||
|
||||
-- if a thread was supplied, bind it to debug.info and debug.get
|
||||
-- we also need to skip this additional level we are introducing in the callstack (only if we are running
|
||||
-- in the same thread we're inspecting)
|
||||
if type(thread) == "thread" then
|
||||
t.getinfo = function(level, what)
|
||||
if t.dumping_same_thread and type(level) == "number" then
|
||||
level = level + 1
|
||||
end
|
||||
return debug.getinfo(thread, level, what)
|
||||
end
|
||||
t.getlocal = function(level, loc)
|
||||
if t.dumping_same_thread then
|
||||
level = level + 1
|
||||
end
|
||||
return debug.getlocal(thread, level, loc)
|
||||
end
|
||||
else
|
||||
t.getinfo = debug.getinfo
|
||||
t.getlocal = debug.getlocal
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
-- helpers for collecting strings to be used when assembling the final trace
|
||||
function Dumper:add (text)
|
||||
self.lines[#self.lines + 1] = text
|
||||
end
|
||||
function Dumper:add_f (fmt, ...)
|
||||
self:add(fmt:format(...))
|
||||
end
|
||||
function Dumper:concat_lines ()
|
||||
return table_concat(self.lines)
|
||||
end
|
||||
|
||||
---
|
||||
-- Private:
|
||||
-- Iterates over the local variables of a given function.
|
||||
--
|
||||
-- @param level The stack level where the function is.
|
||||
--
|
||||
function Dumper:DumpLocals (level)
|
||||
local prefix = "\t "
|
||||
local i = 1
|
||||
|
||||
if self.dumping_same_thread then
|
||||
level = level + 1
|
||||
end
|
||||
|
||||
local name, value = self.getlocal(level, i)
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
self:add("\tLocal variables:\r\n")
|
||||
while name do
|
||||
if type(value) == "number" then
|
||||
self:add_f("%s%s = number: %g\r\n", prefix, name, value)
|
||||
elseif type(value) == "boolean" then
|
||||
self:add_f("%s%s = boolean: %s\r\n", prefix, name, tostring(value))
|
||||
elseif type(value) == "string" then
|
||||
self:add_f("%s%s = string: %q\r\n", prefix, name, value)
|
||||
elseif type(value) == "userdata" then
|
||||
self:add_f("%s%s = %s\r\n", prefix, name, safe_tostring(value))
|
||||
elseif type(value) == "nil" then
|
||||
self:add_f("%s%s = nil\r\n", prefix, name)
|
||||
elseif type(value) == "table" then
|
||||
if m_known_tables[value] then
|
||||
self:add_f("%s%s = %s\r\n", prefix, name, m_known_tables[value])
|
||||
elseif m_user_known_tables[value] then
|
||||
self:add_f("%s%s = %s\r\n", prefix, name, m_user_known_tables[value])
|
||||
else
|
||||
local txt = "{"
|
||||
for k,v in pairs(value) do
|
||||
txt = txt..safe_tostring(k)..":"..safe_tostring(v)
|
||||
if #txt > _M.max_tb_output_len then
|
||||
txt = txt.." (more...)"
|
||||
break
|
||||
end
|
||||
if next(value, k) then txt = txt..", " end
|
||||
end
|
||||
self:add_f("%s%s = %s %s\r\n", prefix, name, safe_tostring(value), txt.."}")
|
||||
end
|
||||
elseif type(value) == "function" then
|
||||
local info = self.getinfo(value, "nS")
|
||||
local fun_name = info.name or m_known_functions[value] or m_user_known_functions[value]
|
||||
if info.what == "C" then
|
||||
self:add_f("%s%s = C %s\r\n", prefix, name, (fun_name and ("function: " .. fun_name) or tostring(value)))
|
||||
else
|
||||
local source = info.short_src
|
||||
if source:sub(2,7) == "string" then
|
||||
source = source:sub(9) -- uno más, por el espacio que viene (string "Baragent.Main", por ejemplo)
|
||||
end
|
||||
--for k,v in pairs(info) do print(k,v) end
|
||||
fun_name = fun_name or GuessFunctionName(info)
|
||||
self:add_f("%s%s = Lua function '%s' (defined at line %d of chunk %s)\r\n", prefix, name, fun_name, info.linedefined, source)
|
||||
end
|
||||
elseif type(value) == "thread" then
|
||||
self:add_f("%sthread %q = %s\r\n", prefix, name, tostring(value))
|
||||
end
|
||||
i = i + 1
|
||||
name, value = self.getlocal(level, i)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Public:
|
||||
-- Collects a detailed stack trace, dumping locals, resolving function names when they're not available, etc.
|
||||
-- This function is suitable to be used as an error handler with pcall or xpcall
|
||||
--
|
||||
-- @param thread An optional thread whose stack is to be inspected (defaul is the current thread)
|
||||
-- @param message An optional error string or object.
|
||||
-- @param level An optional number telling at which level to start the traceback (default is 1)
|
||||
--
|
||||
-- Returns a string with the stack trace and a string with the original error.
|
||||
--
|
||||
function _M.stacktrace(thread, message, level)
|
||||
if type(thread) ~= "thread" then
|
||||
-- shift parameters left
|
||||
thread, message, level = nil, thread, message
|
||||
end
|
||||
|
||||
thread = thread or coroutine.running()
|
||||
|
||||
level = level or 1
|
||||
|
||||
local dumper = Dumper.new(thread)
|
||||
|
||||
local original_error
|
||||
|
||||
if type(message) == "table" then
|
||||
dumper:add("an error object {\r\n")
|
||||
local first = true
|
||||
for k,v in pairs(message) do
|
||||
if first then
|
||||
dumper:add(" ")
|
||||
first = false
|
||||
else
|
||||
dumper:add(",\r\n ")
|
||||
end
|
||||
dumper:add(safe_tostring(k))
|
||||
dumper:add(": ")
|
||||
dumper:add(safe_tostring(v))
|
||||
end
|
||||
dumper:add("\r\n}")
|
||||
original_error = dumper:concat_lines()
|
||||
elseif type(message) == "string" then
|
||||
dumper:add(message)
|
||||
original_error = message
|
||||
end
|
||||
|
||||
dumper:add("\r\n")
|
||||
dumper:add[[
|
||||
Stack Traceback
|
||||
===============
|
||||
]]
|
||||
--print(error_message)
|
||||
|
||||
local level_to_show = level
|
||||
if dumper.dumping_same_thread then level = level + 1 end
|
||||
|
||||
local info = dumper.getinfo(level, "nSlf")
|
||||
while info do
|
||||
if info.what == "main" then
|
||||
if string_sub(info.source, 1, 1) == "@" then
|
||||
dumper:add_f("(%d) main chunk of file '%s' at line %d\r\n", level_to_show, string_sub(info.source, 2), info.currentline)
|
||||
else
|
||||
dumper:add_f("(%d) main chunk of %s at line %d\r\n", level_to_show, info.short_src, info.currentline)
|
||||
end
|
||||
elseif info.what == "C" then
|
||||
--print(info.namewhat, info.name)
|
||||
--for k,v in pairs(info) do print(k,v, type(v)) end
|
||||
local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name or tostring(info.func)
|
||||
dumper:add_f("(%d) %s C function '%s'\r\n", level_to_show, info.namewhat, function_name)
|
||||
--dumper:add_f("%s%s = C %s\r\n", prefix, name, (m_known_functions[value] and ("function: " .. m_known_functions[value]) or tostring(value)))
|
||||
elseif info.what == "tail" then
|
||||
--print("tail")
|
||||
--for k,v in pairs(info) do print(k,v, type(v)) end--print(info.namewhat, info.name)
|
||||
dumper:add_f("(%d) tail call\r\n", level_to_show)
|
||||
dumper:DumpLocals(level)
|
||||
elseif info.what == "Lua" then
|
||||
local source = info.short_src
|
||||
local function_name = m_user_known_functions[info.func] or m_known_functions[info.func] or info.name
|
||||
if source:sub(2, 7) == "string" then
|
||||
source = source:sub(9)
|
||||
end
|
||||
local was_guessed = false
|
||||
if not function_name or function_name == "?" then
|
||||
--for k,v in pairs(info) do print(k,v, type(v)) end
|
||||
function_name = GuessFunctionName(info)
|
||||
was_guessed = true
|
||||
end
|
||||
-- test if we have a file name
|
||||
local function_type = (info.namewhat == "") and "function" or info.namewhat
|
||||
if info.source and info.source:sub(1, 1) == "@" then
|
||||
dumper:add_f("(%d) Lua %s '%s' at file '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "")
|
||||
elseif info.source and info.source:sub(1,1) == '#' then
|
||||
dumper:add_f("(%d) Lua %s '%s' at template '%s:%d'%s\r\n", level_to_show, function_type, function_name, info.source:sub(2), info.currentline, was_guessed and " (best guess)" or "")
|
||||
else
|
||||
dumper:add_f("(%d) Lua %s '%s' at line %d of chunk '%s'\r\n", level_to_show, function_type, function_name, info.currentline, source)
|
||||
end
|
||||
dumper:DumpLocals(level)
|
||||
else
|
||||
dumper:add_f("(%d) unknown frame %s\r\n", level_to_show, info.what)
|
||||
end
|
||||
|
||||
level = level + 1
|
||||
level_to_show = level_to_show + 1
|
||||
info = dumper.getinfo(level, "nSlf")
|
||||
end
|
||||
|
||||
return dumper:concat_lines(), original_error
|
||||
end
|
||||
|
||||
--
|
||||
-- Adds a table to the list of known tables
|
||||
function _M.add_known_table(tab, description)
|
||||
if m_known_tables[tab] then
|
||||
error("Cannot override an already known table")
|
||||
end
|
||||
m_user_known_tables[tab] = description
|
||||
end
|
||||
|
||||
--
|
||||
-- Adds a function to the list of known functions
|
||||
function _M.add_known_function(fun, description)
|
||||
if m_known_functions[fun] then
|
||||
error("Cannot override an already known function")
|
||||
end
|
||||
m_user_known_functions[fun] = description
|
||||
end
|
||||
|
||||
return _M
|
|
@ -1,9 +0,0 @@
|
|||
diggler.io = {}
|
||||
|
||||
diggler.io.readFile = function(mod, path)
|
||||
local file = io.open(path, 'rb')
|
||||
if not file then return nil end
|
||||
local content = file:read('*a')
|
||||
file:close()
|
||||
return content
|
||||
end
|
|
@ -1,62 +0,0 @@
|
|||
ffi.cdef(diggler.io.readFile(nil, digglerNative.gameLuaRuntimePath .. '/ffi/content/BlockDef.code.h'))
|
||||
ffi.cdef(diggler.io.readFile(nil, digglerNative.gameLuaRuntimePath .. '/ffi/content/Registry.code.h'))
|
||||
|
||||
local registerBlock = function(mod, name, block)
|
||||
local app = block.appearance
|
||||
|
||||
local texturesCount = 0
|
||||
for _, _ in pairs(app.textures) do
|
||||
texturesCount = texturesCount + 1
|
||||
end
|
||||
local textures = ffi.new('struct Diggler_Content_BlockDef_appearance_texture[?]', texturesCount)
|
||||
local texids = {}
|
||||
do
|
||||
local i = 0
|
||||
for k, v in pairs(app.textures) do
|
||||
local tex = textures[i]
|
||||
local rpt = v['repeat']
|
||||
tex.name = k
|
||||
tex.path = v.path
|
||||
tex.repeatXdiv = (rpt and rpt.xdiv) or 1
|
||||
tex.repeatYdiv = (rpt and rpt.ydiv) or 1
|
||||
texids[k] = i
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local bdef = ffi.new('struct Diggler_Content_BlockDef', {
|
||||
appearance = {
|
||||
variabilty = 0,
|
||||
texturesCount = texturesCount,
|
||||
textures = textures,
|
||||
look = {
|
||||
type = 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
local cbdata = bdef.appearance.look.data.cube
|
||||
local sides = app.look.sides
|
||||
for k, v in pairs(sides) do
|
||||
if k == 'all' then
|
||||
for f = 0, 5 do
|
||||
cbdata.sides[f].texture = texids[v]
|
||||
end
|
||||
else
|
||||
local faceids = {
|
||||
xi = 0, ['x+'] = 0,
|
||||
xd = 1, ['x-'] = 1,
|
||||
yi = 2, ['y+'] = 2,
|
||||
yd = 3, ['y-'] = 3,
|
||||
zi = 4, ['z+'] = 4,
|
||||
zs = 5, ['z-'] = 5
|
||||
}
|
||||
if faceids[k] then
|
||||
cbdata.sides[faceids[k]].texture = texids[v]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ffi.C.Diggler_Content_Registry_registerBlock(diggler.gameInstance, name, bdef)
|
||||
end
|
||||
diggler.export("registerBlock", registerBlock)
|
|
@ -1,6 +0,0 @@
|
|||
local b64 = dofile('base64/mime_base64.lua')
|
||||
|
||||
return {
|
||||
encode = b64.base64_encode,
|
||||
decode = b64.base64_decode
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
--- MIME BASE64 Encoding and Decoding Routines
|
||||
-- Copyright 2013 Jeff Solinsky
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
|
||||
local escape = {}
|
||||
|
||||
local ffi = require'ffi'
|
||||
local bit = require'bit'
|
||||
local rshift = bit.rshift
|
||||
local lshift = bit.lshift
|
||||
local bor = bit.bor
|
||||
local band = bit.band
|
||||
local floor = math.floor
|
||||
|
||||
local mime64chars = ffi.new("uint8_t[64]",
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
|
||||
local mime64lookup = ffi.new("uint8_t[256]")
|
||||
ffi.fill(mime64lookup, 256, 0xFF)
|
||||
for i=0,63 do
|
||||
mime64lookup[mime64chars[i]]=i
|
||||
end
|
||||
|
||||
local u8arr= ffi.typeof'uint8_t[?]'
|
||||
local u8ptr=ffi.typeof'uint8_t*'
|
||||
|
||||
--- Base64 decode a string or a FFI char *.
|
||||
-- @param str (String or char*) Bytearray to decode.
|
||||
-- @param sz (Number) Length of string to decode, optional if str is a Lua string
|
||||
-- @return (String) Decoded string.
|
||||
function escape.base64_decode(str, sz)
|
||||
if (type(str)=="string") and (sz == nil) then sz=#str end
|
||||
local m64, b1 -- value 0 to 63, partial byte
|
||||
local bin_arr=ffi.new(u8arr, floor(bit.rshift(sz*3,2)))
|
||||
local mptr = ffi.cast(u8ptr,bin_arr) -- position in binary mime64 output array
|
||||
local bptr = ffi.cast(u8ptr,str)
|
||||
local i = 0
|
||||
while true do
|
||||
repeat
|
||||
if i >= sz then goto done end
|
||||
m64 = mime64lookup[bptr[i]]
|
||||
i=i+1
|
||||
until m64 ~= 0xFF -- skip non-mime characters like newlines
|
||||
b1=lshift(m64, 2)
|
||||
repeat
|
||||
if i >= sz then goto done end
|
||||
m64 = mime64lookup[bptr[i]]
|
||||
i=i+1
|
||||
until m64 ~= 0xFF -- skip non-mime characters like newlines
|
||||
mptr[0] = bor(b1,rshift(m64, 4)); mptr=mptr+1
|
||||
b1 = lshift(m64,4)
|
||||
repeat
|
||||
if i >= sz then goto done end
|
||||
m64 = mime64lookup[bptr[i]]
|
||||
i=i+1
|
||||
until m64 ~= 0xFF -- skip non-mime characters like newlines
|
||||
mptr[0] = bor(b1,rshift(m64, 2)); mptr=mptr+1
|
||||
b1 = lshift(m64,6)
|
||||
repeat
|
||||
if i >= sz then goto done end
|
||||
m64 = mime64lookup[bptr[i]]
|
||||
i=i+1
|
||||
until m64 ~= 0xFF -- skip non-mime characters like newlines
|
||||
mptr[0] = bor(b1, m64); mptr=mptr+1
|
||||
end
|
||||
::done::
|
||||
return ffi.string(bin_arr, (mptr-bin_arr))
|
||||
end
|
||||
|
||||
|
||||
local mime64shorts=ffi.new('uint16_t[4096]')
|
||||
for i=0,63 do
|
||||
for j=0,63 do
|
||||
local v
|
||||
if ffi.abi("le") then
|
||||
v=mime64chars[j]*256+mime64chars[i]
|
||||
else
|
||||
v=mime64chars[i]*256+mime64chars[j]
|
||||
end
|
||||
mime64shorts[i*64+j]=v
|
||||
end
|
||||
end
|
||||
|
||||
local u16arr = ffi.typeof"uint16_t[?]"
|
||||
local crlf16 = ffi.new("uint16_t[1]")
|
||||
if ffi.abi("le") then
|
||||
crlf16[0] = (0x0A*256)+0x0D
|
||||
else
|
||||
crlf16[0] = (0x0D*256)+0x0A
|
||||
end
|
||||
local eq=string.byte('=')
|
||||
--- Base64 encode binary data of a string or a FFI char *.
|
||||
-- @param str (String or char*) Bytearray to encode.
|
||||
-- @param sz (Number) Length of string to encode, optional if str is a Lua string
|
||||
-- @return (String) Encoded base64 string.
|
||||
function escape.base64_encode(str, sz)
|
||||
if (type(str)=="string") and (sz == nil) then sz=#str end
|
||||
local outlen = floor(sz*2/3)
|
||||
outlen = outlen + floor(outlen/19)+3
|
||||
local m64arr=ffi.new(u16arr,outlen)
|
||||
local l,p,v=0,0
|
||||
local bptr = ffi.cast(u8ptr,str)
|
||||
local c = 38 -- put a new line after every 76 characters
|
||||
local i,k=0,0
|
||||
::while_3bytes::
|
||||
if i+3>sz then goto break3 end
|
||||
v=bor(lshift(bptr[i],16),lshift(bptr[i+1],8),bptr[i+2])
|
||||
i=i+3
|
||||
::encode_last3::
|
||||
if c==k then
|
||||
m64arr[k]=crlf16[0]
|
||||
k=k+1
|
||||
c=k+38 -- 76 /2 = 38
|
||||
end
|
||||
m64arr[k]=mime64shorts[rshift(v,12)]
|
||||
m64arr[k+1]=mime64shorts[band(v,4095)]
|
||||
k=k+2
|
||||
goto while_3bytes
|
||||
::break3::
|
||||
if l>0 then
|
||||
-- Add trailing equal sign padding
|
||||
if l==1 then
|
||||
-- 1 byte encoded needs two trailing equal signs
|
||||
m64arr[k-1]=bor(lshift(eq,8),eq)
|
||||
else
|
||||
-- 2 bytes encoded needs one trailing equal sign
|
||||
(ffi.cast(u8ptr,m64arr))[lshift(k,1)-1]=eq
|
||||
end
|
||||
else
|
||||
l=sz-i -- get remaining len (1 or 2 bytes)
|
||||
if l>0 then
|
||||
v= lshift(bptr[i],16)
|
||||
if l==2 then v=bor(v,lshift(bptr[i+1],8)) end
|
||||
goto encode_last3
|
||||
end
|
||||
end
|
||||
return ffi.string(m64arr,lshift(k,1))
|
||||
end
|
||||
|
||||
return escape
|
|
@ -1 +0,0 @@
|
|||
Subproject commit e7480da28e507bed62e93ca7b5a1239cfb14d016
|
|
@ -1 +0,0 @@
|
|||
Subproject commit a05da803f659c57e9ce80045e358ada1897fddc0
|
|
@ -1 +0,0 @@
|
|||
Subproject commit d3b054dc48ab7428ea0020ea81e79688ad160fa1
|
|
@ -1,50 +0,0 @@
|
|||
# Locate LuaJIT library
|
||||
# This module defines
|
||||
# LUAJIT_FOUND, if false, do not try to link to Lua
|
||||
# LUA_INCLUDE_DIR, where to find lua.h
|
||||
# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
|
||||
#
|
||||
# This module is similar to FindLua51.cmake except that it finds LuaJit instead.
|
||||
|
||||
FIND_PATH(LUA_INCLUDE_DIR luajit.h
|
||||
HINTS
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES include/luajit-2.0 include/luajit-5_1-2.0 include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
)
|
||||
|
||||
FIND_LIBRARY(LUA_LIBRARY
|
||||
NAMES luajit-5.1
|
||||
HINTS
|
||||
$ENV{LUA_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
|
||||
IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h")
|
||||
FILE(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT .+\"")
|
||||
|
||||
STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
|
||||
UNSET(lua_version_str)
|
||||
ENDIF()
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJit
|
||||
REQUIRED_VARS LUA_LIBRARY LUA_INCLUDE_DIR
|
||||
VERSION_VAR LUA_VERSION_STRING)
|
||||
|
||||
MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY)
|
|
@ -6,7 +6,6 @@
|
|||
#include "gfx/Device.hpp"
|
||||
#include "render/gl/ProgramManager.hpp"
|
||||
#include "render/gl/Renderer.hpp"
|
||||
#include "scripting/lua/State.hpp"
|
||||
#include "ui/FontManager.hpp"
|
||||
#include "Audio.hpp"
|
||||
#include "GlobalProperties.hpp"
|
||||
|
@ -20,7 +19,6 @@ Game::Game() :
|
|||
U(nullptr),
|
||||
players(this),
|
||||
CR(nullptr),
|
||||
LS(nullptr),
|
||||
|
||||
S(nullptr),
|
||||
|
||||
|
@ -38,7 +36,6 @@ Game::Game() :
|
|||
void Game::init() {
|
||||
AM = std::make_unique<content::AssetManager>(this);
|
||||
MM = std::make_unique<content::ModManager>(this);
|
||||
LS = new scripting::lua::State(this);
|
||||
if (GlobalProperties::IsClient) {
|
||||
initClient();
|
||||
}
|
||||
|
@ -76,7 +73,6 @@ void Game::finalize() {
|
|||
if (GlobalProperties::IsServer) {
|
||||
finalizeServer();
|
||||
}
|
||||
delete LS; LS = nullptr;
|
||||
MM.reset();
|
||||
AM.reset();
|
||||
delete CR; CR = nullptr;
|
||||
|
|
|
@ -27,12 +27,6 @@ class ProgramManager;
|
|||
}
|
||||
}
|
||||
|
||||
namespace scripting {
|
||||
namespace lua {
|
||||
class State;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class FontManager;
|
||||
class Manager;
|
||||
|
@ -60,7 +54,6 @@ public:
|
|||
content::Registry *CR;
|
||||
ptr<content::AssetManager> AM;
|
||||
ptr<content::ModManager> MM;
|
||||
scripting::lua::State *LS;
|
||||
|
||||
// Server
|
||||
Server *S;
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include <thread>
|
||||
#include <sstream>
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
#include "Game.hpp"
|
||||
#include "network/msgtypes/BlockUpdate.hpp"
|
||||
#include "network/msgtypes/Chat.hpp"
|
||||
|
@ -16,7 +14,6 @@
|
|||
#include "network/msgtypes/PlayerUpdate.hpp"
|
||||
#include "network/Network.hpp"
|
||||
#include "network/NetHelper.hpp"
|
||||
#include "scripting/lua/State.hpp"
|
||||
#include "VersionInfo.hpp"
|
||||
#include "CaveGenerator.hpp"
|
||||
#include "util/Log.hpp"
|
||||
|
@ -355,7 +352,6 @@ Server::Server(Game &G, uint16 port) : G(G) {
|
|||
}
|
||||
|
||||
void Server::startInternals() {
|
||||
G.LS->initialize();
|
||||
}
|
||||
|
||||
// FIXME ugly ugly hack to keep it in mem
|
||||
|
@ -379,7 +375,6 @@ void Server::stop() {
|
|||
}
|
||||
|
||||
void Server::stopInternals() {
|
||||
G.LS->finalize();
|
||||
}
|
||||
|
||||
void Server::chunkUpdater(WorldRef WR, bool &continueUpdate) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
add_subdirectory("lua")
|
||||
# add_subdirectory("angelscript")
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
set(CSD ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
diggler_add_sources(
|
||||
${CSD}/api/content/Registry.cpp
|
||||
${CSD}/State.cpp
|
||||
)
|
|
@ -1,198 +0,0 @@
|
|||
#include "State.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
extern "C" {
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
#include <luajit.h>
|
||||
}
|
||||
|
||||
namespace diggler {
|
||||
namespace scripting {
|
||||
namespace lua {
|
||||
|
||||
static int wrap_exceptions(lua_State *L, lua_CFunction f) {
|
||||
try {
|
||||
return f(L);
|
||||
} catch (const char *s) {
|
||||
lua_pushstring(L, s);
|
||||
} catch (const std::exception &e) {
|
||||
lua_pushstring(L, e.what());
|
||||
} catch (...) {
|
||||
lua_pushliteral(L, "caught (...)");
|
||||
}
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
static std::string intpad(int i, int digits) {
|
||||
std::string ret(digits, ' ');
|
||||
bool neg = i < 0;
|
||||
if (neg) {
|
||||
i = -i;
|
||||
}
|
||||
for (int d = digits - 1; d > 0; --d) {
|
||||
if (i > 0) {
|
||||
ret[d] = '0' + (i % 10);
|
||||
i /= 10;
|
||||
} else if (neg) {
|
||||
ret[d] = '-';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string stackdump(lua_State* L) {
|
||||
std::ostringstream oss;
|
||||
int i, top = lua_gettop(L);
|
||||
oss << "Lua: " << top << " stack entries" << std::endl;
|
||||
for (i = 1; i <= top; i++) {
|
||||
int t = lua_type(L, i);
|
||||
switch (t) {
|
||||
case LUA_TSTRING:
|
||||
oss << intpad(i, 3) << " string: '" << lua_tostring(L, i) << "'" << std::endl;
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
oss << intpad(i, 3) << " bool: " << (lua_toboolean(L, i) ? "true" : "false") << std::endl;
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
oss << intpad(i, 3) << " number: " << lua_tonumber(L, i) << std::endl;
|
||||
break;
|
||||
default:
|
||||
oss << intpad(i, 3) << ' ' << lua_typename(L, t) << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
State::State(Game *G) :
|
||||
G(G),
|
||||
state(nullptr) {
|
||||
}
|
||||
|
||||
State::~State() {
|
||||
if (state != nullptr) {
|
||||
finalize();
|
||||
}
|
||||
}
|
||||
|
||||
void State::initialize() {
|
||||
state = luaL_newstate();
|
||||
|
||||
lua_pushlightuserdata(state, (void*) wrap_exceptions);
|
||||
luaJIT_setmode(state, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
|
||||
lua_pop(state, 1);
|
||||
|
||||
luaL_openlibs(state);
|
||||
|
||||
lua_pushstring(state, "DigglerGameInstance");
|
||||
lua_pushlightuserdata(state, G);
|
||||
lua_settable(state, LUA_REGISTRYINDEX);
|
||||
|
||||
lua_pushstring(state, "DigglerErrorHandler");
|
||||
lua_pushcfunction(state, handleLuaError);
|
||||
lua_settable(state, LUA_REGISTRYINDEX);
|
||||
|
||||
|
||||
lua_newtable(state);
|
||||
lua_pushlstring(state, reinterpret_cast<const char*>(&G), sizeof(G));
|
||||
lua_setfield(state, -2, "gameInstancePtrStr");
|
||||
lua_setglobal(state, "digglerNative");
|
||||
}
|
||||
|
||||
void State::finalize() {
|
||||
lua_close(state);
|
||||
state = nullptr;
|
||||
}
|
||||
|
||||
std::string State::traceback() {
|
||||
std::cout << stackdump(state);
|
||||
if (!lua_isstring(state, 1))
|
||||
return "";
|
||||
lua_getglobal(state, "debug");
|
||||
if (!lua_istable(state, -1)) {
|
||||
lua_pop(state, 1);
|
||||
return "";
|
||||
}
|
||||
lua_getfield(state, -1, "traceback");
|
||||
if (!lua_isfunction(state, -1)) {
|
||||
lua_pop(state, 2);
|
||||
return "";
|
||||
}
|
||||
lua_pushvalue(state, 1);
|
||||
lua_pushinteger(state, 2);
|
||||
lua_call(state, 2, 1);
|
||||
const char *err = lua_tostring(state, -1);
|
||||
return err ? err : "<no traceback>";
|
||||
}
|
||||
|
||||
int State::handleLuaError(lua_State *state) {
|
||||
lua_getfield(state, LUA_REGISTRYINDEX, "DigglerGameInstance");
|
||||
Game *G = static_cast<Game*>(lua_touserdata(state, -1));
|
||||
|
||||
G->LS->error = G->LS->traceback();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void State::setGameLuaRuntimePath(const std::string &path) {
|
||||
lua_getglobal(state, "digglerNative");
|
||||
lua_pushstring(state, path.c_str());
|
||||
lua_setfield(state, -2, "gameLuaRuntimePath");
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
|
||||
void State::dofile(const char *path) {
|
||||
int luaRet;
|
||||
lua_getfield(state, LUA_REGISTRYINDEX, "DigglerErrorHandler");
|
||||
if ((luaRet = luaL_loadfile(state, path))) {
|
||||
lua_remove(state, -2); // pop error handler
|
||||
if (hasError()) {
|
||||
std::string err(std::move(error));
|
||||
throw std::runtime_error(err);
|
||||
} else {
|
||||
throw std::runtime_error(traceback());
|
||||
}
|
||||
}
|
||||
if ((luaRet = lua_pcall(state, 0, 0, -2))) {
|
||||
lua_remove(state, -2); // pop error handler
|
||||
if (hasError()) {
|
||||
std::string err(std::move(error));
|
||||
throw std::runtime_error(err);
|
||||
} else {
|
||||
throw std::runtime_error(traceback());
|
||||
}
|
||||
}
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
|
||||
void State::dostring(const char *code) {
|
||||
int luaRet;
|
||||
lua_getfield(state, LUA_REGISTRYINDEX, "DigglerErrorHandler");
|
||||
if ((luaRet = luaL_loadstring(state, code))) {
|
||||
lua_remove(state, -2); // pop error handler
|
||||
if (hasError()) {
|
||||
std::string err(std::move(error));
|
||||
throw std::runtime_error(err);
|
||||
} else {
|
||||
throw std::runtime_error(traceback());
|
||||
}
|
||||
}
|
||||
if ((luaRet = lua_pcall(state, 0, 0, -2))) {
|
||||
lua_remove(state, -2); // pop error handler
|
||||
if (hasError()) {
|
||||
std::string err(std::move(error));
|
||||
throw std::runtime_error(err);
|
||||
} else {
|
||||
throw std::runtime_error(traceback());
|
||||
}
|
||||
}
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
#ifndef DIGGLER_SCRIPTING_LUA_STATE_HPP
|
||||
#define DIGGLER_SCRIPTING_LUA_STATE_HPP
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
}
|
||||
|
||||
#include "../../Game.hpp"
|
||||
|
||||
namespace diggler {
|
||||
namespace scripting {
|
||||
namespace lua {
|
||||
|
||||
class State {
|
||||
private:
|
||||
Game *G;
|
||||
|
||||
static int handleLuaError(lua_State*);
|
||||
std::string error;
|
||||
inline bool hasError() const {
|
||||
return error.size() > 0;
|
||||
}
|
||||
inline void clearError() {
|
||||
error.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
lua_State *state;
|
||||
|
||||
State(Game*);
|
||||
~State();
|
||||
|
||||
void initialize();
|
||||
void finalize();
|
||||
|
||||
std::string traceback();
|
||||
|
||||
void setGameLuaRuntimePath(const std::string &path);
|
||||
|
||||
void dofile(const char *path);
|
||||
inline void dofile(const std::string &path) {
|
||||
dofile(path.c_str());
|
||||
}
|
||||
|
||||
void dostring(const char *code);
|
||||
inline void dostring(const std::string &code) {
|
||||
dostring(code.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DIGGLER_SCRIPTING_LUA_STATE_HPP */
|
|
@ -1,23 +0,0 @@
|
|||
struct Diggler_Content_BlockDef {
|
||||
struct {
|
||||
int variabilty;
|
||||
int texturesCount;
|
||||
struct Diggler_Content_BlockDef_appearance_texture {
|
||||
const char *name, *path;
|
||||
uint8_t repeatXdiv, repeatYdiv;
|
||||
} *textures;
|
||||
struct {
|
||||
enum {
|
||||
LookType_Hidden = 0,
|
||||
LookType_Cube = 1
|
||||
} type;
|
||||
union {
|
||||
struct {
|
||||
struct {
|
||||
int texture;
|
||||
} sides[6];
|
||||
} cube;
|
||||
} data;
|
||||
} look;
|
||||
} appearance;
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef DIGGLER_SCRIPTING_LUA_API_CONTENT_BLOCK_DEF_H
|
||||
#define DIGGLER_SCRIPTING_LUA_API_CONTENT_BLOCK_DEF_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
#include "BlockDef.code.h"
|
||||
}
|
||||
|
||||
#endif /* DIGGLER_SCRIPTING_LUA_API_CONTENT_BLOCK_DEF_H */
|
|
@ -1,2 +0,0 @@
|
|||
void Diggler_Content_Registry_registerBlock(struct Diggler_Game*,
|
||||
const char *name, struct Diggler_Content_BlockDef*);
|
|
@ -1,62 +0,0 @@
|
|||
#include "Registry.h"
|
||||
|
||||
#include "BlockDef.h"
|
||||
#include "../../../../content/Registry.hpp"
|
||||
#include "../../../../Game.hpp"
|
||||
|
||||
using namespace diggler;
|
||||
|
||||
void Diggler_Content_Registry_registerBlock(struct Diggler_Game *cG,
|
||||
const char *name, struct Diggler_Content_BlockDef *cBdef) {
|
||||
using namespace content;
|
||||
Game &G = *reinterpret_cast<Game*>(cG);
|
||||
Registry::BlockRegistration br(G.CR->registerBlock(name));
|
||||
{ decltype(cBdef->appearance) &cApp = cBdef->appearance;
|
||||
decltype(br.def.appearance) &app = br.def.appearance;
|
||||
std::vector<decltype(app.textures)::iterator> textureIts;
|
||||
textureIts.reserve(cApp.texturesCount);
|
||||
for (int i = 0; i < cApp.texturesCount; ++i) {
|
||||
decltype(*cApp.textures) &cTex = cApp.textures[i];
|
||||
std::pair<decltype(app.textures)::iterator, bool> itPair =
|
||||
app.textures.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(cTex.name),
|
||||
std::forward_as_tuple());
|
||||
decltype(app.textures)::iterator &it = itPair.first;
|
||||
decltype(app.textures)::value_type::second_type &tex = it->second;
|
||||
tex.coord = G.CR->addTexture(cTex.name, cTex.path);
|
||||
cTex.repeatXdiv = cTex.repeatYdiv = 4;
|
||||
tex.repeat.xdiv = cTex.repeatXdiv;
|
||||
tex.repeat.ydiv = cTex.repeatYdiv;
|
||||
if (cTex.repeatXdiv > 1 || cTex.repeatYdiv > 1) {
|
||||
uint16 width = (tex.coord.u - tex.coord.x) / cTex.repeatXdiv,
|
||||
height = (tex.coord.v - tex.coord.y) / cTex.repeatYdiv;
|
||||
for (int16 y = cTex.repeatYdiv - 1; y >= 0; --y) {
|
||||
for (int16 x = cTex.repeatXdiv - 1; x >= 0; --x) {
|
||||
tex.divCoords.emplace_back(Util::TexturePacker::Coord {
|
||||
static_cast<uint16>(tex.coord.x + width * x),
|
||||
static_cast<uint16>(tex.coord.y + height * y),
|
||||
static_cast<uint16>(tex.coord.x + width * (x + 1)),
|
||||
static_cast<uint16>(tex.coord.y + height * (y + 1))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
textureIts.emplace_back(it);
|
||||
}
|
||||
{ decltype(cApp.look) &cLook = cApp.look;
|
||||
decltype(app.look) &look = app.look;
|
||||
using Type = BlockDef::Appearance::Look::Type;
|
||||
look.type = static_cast<Type>(cLook.type);
|
||||
switch (look.type) {
|
||||
case Type::Cube:
|
||||
for (int i = 0; i < 6 /* Math::Geometry::Cube::FaceCount */; ++i) {
|
||||
look.data.cube.sides[i].texture = textureIts.at(cLook.data.cube.sides[i].texture);
|
||||
}
|
||||
break;
|
||||
case Type::Hidden:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
br.commit();
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef DIGGLER_SCRIPTING_LUA_API_CONTENT_REGISTRY_H
|
||||
#define DIGGLER_SCRIPTING_LUA_API_CONTENT_REGISTRY_H
|
||||
|
||||
extern "C" {
|
||||
#include "Registry.code.h"
|
||||
}
|
||||
|
||||
#endif /* DIGGLER_SCRIPTING_LUA_API_CONTENT_REGISTRY_H */
|
|
@ -15,9 +15,6 @@
|
|||
#include "../ui/Text.hpp"
|
||||
#include "../util/Log.hpp"
|
||||
|
||||
// TODO: move elsewhere
|
||||
#include "../scripting/lua/State.hpp"
|
||||
|
||||
namespace diggler {
|
||||
|
||||
using Util::Log;
|
||||
|
@ -111,12 +108,6 @@ void ConnectingState::onLogicTick() {
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: move elsewhere
|
||||
G->LS->initialize();
|
||||
const std::string gameLuaRuntimePath(getAssetsDirectory() + "/lua");
|
||||
G->LS->setGameLuaRuntimePath(gameLuaRuntimePath);
|
||||
G->LS->dofile(gameLuaRuntimePath + "/Diggler.lua");
|
||||
|
||||
Log(Info, TAG) << "Joined as " << LP.name << '/' << LP.sessId;
|
||||
|
||||
W->setNextState(std::make_unique<GameState>(W));
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "../render/gl/FBO.hpp"
|
||||
#include "../render/gl/ProgramManager.hpp"
|
||||
#include "../render/Renderer.hpp"
|
||||
#include "../scripting/lua/State.hpp"
|
||||
#include "../Skybox.hpp"
|
||||
#include "../ui/FontManager.hpp"
|
||||
#include "../ui/Manager.hpp"
|
||||
|
@ -593,8 +592,6 @@ void GameState::onFrameTick() {
|
|||
void GameState::onStop() {
|
||||
net::OutMessage quit(net::MessageType::PlayerQuit);
|
||||
sendMsg(quit, net::Tfer::Rel);
|
||||
|
||||
G->LS->finalize();
|
||||
}
|
||||
|
||||
void GameState::gameLoop() {
|
||||
|
|
Loading…
Reference in New Issue