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
Dorian Wouters 2018-09-09 16:06:22 +02:00
parent 745f53a731
commit 1a235adb40
No known key found for this signature in database
GPG Key ID: 6E9DA8063322434B
25 changed files with 1 additions and 1350 deletions

View File

@ -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)

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -1,6 +0,0 @@
local b64 = dofile('base64/mime_base64.lua')
return {
encode = b64.base64_encode,
decode = b64.base64_decode
}

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -1 +1 @@
add_subdirectory("lua")
# add_subdirectory("angelscript")

View File

@ -1,5 +0,0 @@
set(CSD ${CMAKE_CURRENT_SOURCE_DIR})
diggler_add_sources(
${CSD}/api/content/Registry.cpp
${CSD}/State.cpp
)

View File

@ -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);
}
}
}
}

View File

@ -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 */

View File

@ -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;
};

View File

@ -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 */

View File

@ -1,2 +0,0 @@
void Diggler_Content_Registry_registerBlock(struct Diggler_Game*,
const char *name, struct Diggler_Content_BlockDef*);

View File

@ -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();
}

View File

@ -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 */

View File

@ -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));

View File

@ -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() {