mirror of
https://github.com/dragonfireclient/hydra-dragonfire.git
synced 2024-11-21 10:24:01 -05:00
205 lines
4.7 KiB
Lua
Executable file
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()
|