1
0
Fork 0
mirror of https://github.com/dragonfireclient/hydra-dragonfire.git synced 2024-11-21 10:24:01 -05:00
hydra-dragonfire/convert/read_mkauto.lua
2022-06-09 00:20:27 +02:00

205 lines
4.7 KiB
Lua
Executable file

#!/usr/bin/env lua
require("spec")
local readers = {
SliceByte = true,
Byte = true,
String = true,
SliceField = true,
Field = true,
Bool = true,
PointedThing = true,
}
local external = {
"[3]int16",
"AOID"
}
local function generate(name)
local fnname, index, child, childfn, childtype
local type = name
local open = name:find("%[")
local clos = name:find("%]")
if open == 1 then
index = name:sub(open + 1, clos - 1)
child = name:sub(clos + 1)
childfn, childtype = generate(child)
fnname = (index == "" and "Slice" or "Vec" .. index) .. childfn
type = "[" .. index .. "]" .. childtype
else
fnname = camel_case(name)
local c = name:sub(1, 1)
if c == c:upper() then
type = "mt." .. name
end
end
if not readers[fnname] then
local fun = "func Read" .. fnname .. "(l *lua.LState, val lua.LValue, ptr *" .. type .. ") {\n"
if child then
fun = fun .. "\tif val.Type() != lua.LTTable {\n\t\tpanic(\"invalid value for "
.. name .. ": must be a table\")\n\t}\n"
if index == "" then
fun = fun ..
[[
tbl := val.(*lua.LTable)
n := tbl.MaxN()
*ptr = make(]] .. type .. [[, n)
for i := range *ptr {
Read]] .. childfn .. [[(l, l.RawGetInt(tbl, i+1), &(*ptr)[i])
}
]]
else
local n = tonumber(index)
for i, v in ipairs({"x", "y", "z"}) do
if i > n then
break
end
fun = fun
.. "\tRead" .. childfn
.. "(l, l.GetField(val, \"" .. v .. "\"), &(*ptr)[" .. (i - 1) .. "])\n"
end
end
else
local is_float = type == "float32" or type == "float64"
fun = fun .. "\tif val.Type() != lua.LTNumber {\n\t\tpanic(\"invalid value for "
.. name .. ": must be a number\")\n\t}\n"
.. "\t*ptr = " .. type .. "("
.. (is_float and "" or "math.Round(float64(")
.. "val.(lua.LNumber)"
.. (is_float and "" or "))")
.. ")\n"
end
fun = fun .. "}\n\n"
readers[fnname] = fun
end
return fnname, type
end
for _, use in ipairs(external) do
generate(use)
end
local function signature(name, prefix, type)
local camel = camel_case(name)
return "func Read" .. camel .. "(l *lua.LState, val lua.LValue, ptr *" .. prefix .. camel .. ") {\n"
end
for name, fields in spairs(parse_spec("server/enum")) do
local camel = camel_case(name)
local fun = signature(name, "mt.")
local impl = ""
for _, var in ipairs(fields) do
local equals = "*ptr = mt." .. apply_prefix(fields, var) .. "\n"
if var == "no" then
fun = fun .. "\tif val.Type() == lua.LTNil {\n\t\t" .. equals .. "\t\treturn\n\t}\n"
else
impl = impl .. "\tcase \"" .. var .. "\":\n\t\t" .. equals
end
end
fun = fun
.. "\tif val.Type() != lua.LTString {\n\t\tpanic(\"invalid value for "
.. camel .. ": must be a string\")\n\t}\n"
.. "\tstr := string(val.(lua.LString))\n"
.. "\tswitch str {\n" .. impl
.. "\tdefault:\n\t\tpanic(\"invalid value for " .. name .. ": \" + str)\n\t}\n}\n\n"
readers[camel] = fun
end
for name, fields in spairs(parse_spec("server/flag")) do
local camel = camel_case(name)
local fun = signature(name, "mt.")
.. "\tif val.Type() != lua.LTTable {\n\t\tpanic(\"invalid value for "
.. camel .. ": must be a table\")\n\t}\n"
for _, var in ipairs(fields) do
fun = fun .. "\tif l.GetField(val, \"" .. var .. "\") == lua.LTrue {\n"
.. "\t\t*ptr = *ptr | mt." .. apply_prefix(fields, var) .. "\n\t}\n"
end
fun = fun .. "}\n\n"
readers[camel] = fun
end
local function fields_fromlua(fields, indent)
local impl = ""
for name, type in spairs(fields) do
impl = impl .. indent .. "Read" .. generate(type) .. "(l, l.GetField(val, \"" .. name .. "\"), &ptr."
.. camel_case(name) .. ")\n"
end
return impl
end
for name, fields in spairs(parse_spec("server/struct", true)) do
local camel = camel_case(name)
readers[camel] = signature(name, "mt.")
.. "\tif val.Type() != lua.LTTable {\n"
.. "\t\tpanic(\"invalid value for " .. camel .. ": must be a table\")\n\t}\n"
.. fields_fromlua(fields, "\t")
.. "}\n\n"
end
local pkt_impl = ""
for name, fields in spairs(parse_spec("server/pkt", true)) do
pkt_impl = pkt_impl
.. "\tcase \"" .. name .. "\"" .. "" .. ":\n"
.. "\t\tptr := &mt.ToSrv" .. camel_case(name) .. "{}\n"
if next(fields) then
pkt_impl = pkt_impl
.. "\t\tval := l.CheckTable(3)\n"
.. fields_fromlua(fields, "\t\t")
end
pkt_impl = pkt_impl
.. "\t\treturn ptr\n"
end
local funcs = ""
for _, fn in spairs(readers) do
if type(fn) == "string" then
funcs = funcs .. fn
end
end
local f = io.open("read_auto.go", "w")
f:write([[
// generated by read_mkauto.lua, DO NOT EDIT
package convert
import (
"github.com/dragonfireclient/mt"
"github.com/yuin/gopher-lua"
"math"
)
]] .. funcs .. [[
func ReadCmd(l *lua.LState) mt.Cmd {
str := l.CheckString(2)
switch str {
]] .. pkt_impl .. [[
}
panic("invalid packet type: " + str)
}
]])
f:close()