From fae336d1a2d613fd00640ed6ccbb9eb386086c82 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Tue, 31 May 2022 14:24:19 +0200 Subject: Add map component --- README.md | 2 +- builtin/base64.lua | 43 +++++++ builtin/escapes.lua | 2 +- builtin/vector.lua | 10 +- client.go | 2 + convert/push_auto.go | 270 +++++++++++++++++++++++--------------------- convert/push_mkauto.lua | 27 +++-- convert/push_static.go | 126 +++++++++++++++++---- convert/read_auto.go | 157 +++++++++++++------------- convert/read_mkauto.lua | 23 ++-- convert/read_static.go | 16 +-- convert/spec.lua | 5 +- convert/spec/casemap | 28 +++++ convert/spec/client/enum | 70 ++++++++++++ convert/spec/client/flag | 25 ++++ convert/spec/client/pkt | 276 +++++++++++++++++++++++++++++++++++++++++++++ convert/spec/client/struct | 43 +++++++ convert/spec/server/enum | 7 ++ convert/spec/server/flag | 12 ++ convert/spec/server/pkt | 63 +++++++++++ convert/spec/server/struct | 8 ++ doc/api.md | 1 + doc/client.md | 1 + doc/client_pkts.md | 2 +- doc/map.md | 13 +++ doc/server_pkts.md | 2 +- example/dump-traffic.lua | 44 +++++++- example/print-node.lua | 23 ++++ hydra.go | 5 + map.go | 116 +++++++++++++++++++ spec/casemap | 28 ----- spec/client/enum | 70 ------------ spec/client/flag | 19 ---- spec/client/pkt | 274 -------------------------------------------- spec/client/struct | 24 ---- spec/server/enum | 7 -- spec/server/flag | 12 -- spec/server/pkt | 63 ----------- spec/server/struct | 8 -- 39 files changed, 1153 insertions(+), 774 deletions(-) create mode 100644 builtin/base64.lua create mode 100644 convert/spec/casemap create mode 100644 convert/spec/client/enum create mode 100644 convert/spec/client/flag create mode 100644 convert/spec/client/pkt create mode 100644 convert/spec/client/struct create mode 100644 convert/spec/server/enum create mode 100644 convert/spec/server/flag create mode 100644 convert/spec/server/pkt create mode 100644 convert/spec/server/struct create mode 100644 doc/map.md create mode 100755 example/print-node.lua create mode 100644 map.go delete mode 100644 spec/casemap delete mode 100644 spec/client/enum delete mode 100644 spec/client/flag delete mode 100644 spec/client/pkt delete mode 100644 spec/client/struct delete mode 100644 spec/server/enum delete mode 100644 spec/server/flag delete mode 100644 spec/server/pkt delete mode 100644 spec/server/struct diff --git a/README.md b/README.md index 2b75b0d..275a6d5 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Only selected packets will be returned by `poll`, to avoid unnecessary conversio Poll will return early if the script is interrupted by a signal, one of the selected clients is disconnected or the configured timeout elapses. Additionally, different native components can be enabled per-client to manage state. -Currently only the `auth` component is available, but components like `map`, `objs`, `inv`, `pos`, `playerlist` etc. will be added in the future. +Currently `auth` and `map` components are available, and components like `objs`, `inv`, `pos`, `player_list` etc. will be added in the future. Components handle packets asynchronously, they will process them even if poll is not called. # Further Documentation diff --git a/builtin/base64.lua b/builtin/base64.lua new file mode 100644 index 0000000..5afa64a --- /dev/null +++ b/builtin/base64.lua @@ -0,0 +1,43 @@ +--[[ builtin/base64.lua ]]-- + +-- Taken from: http://lua-users.org/wiki/BaseSixtyFour with minor modifications + +-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss +-- licensed under the terms of the LGPL2 + +local base64 = {} +package.loaded.base64 = base64 + +-- character table string +local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + +-- encoding +function base64.encode(data) + return ((data:gsub('.', function(x) + local r,b='',x:byte() + for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end + return r; + end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) + if (#x < 6) then return '' end + local c=0 + for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end + return b:sub(c+1,c+1) + end)..({ '', '==', '=' })[#data%3+1]) +end + +-- decoding +function base64.decode(data) + data = string.gsub(data, '[^'..b..'=]', '') + return (data:gsub('.', function(x) + if (x == '=') then return '' end + local r,f='',(b:find(x)-1) + for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end + return r; + end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) + if (#x ~= 8) then return '' end + local c=0 + for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end + return string.char(c) + end)) +end + diff --git a/builtin/escapes.lua b/builtin/escapes.lua index 12ba174..e3ff161 100644 --- a/builtin/escapes.lua +++ b/builtin/escapes.lua @@ -2,7 +2,7 @@ -- code taken from minetest/builtin/common/misc_helpers.lua with modifications local escapes = {} -package.loaded["escapes"] = escapes +package.loaded.escapes = escapes escapes.ESCAPE_CHAR = string.char(0x1b) diff --git a/builtin/vector.lua b/builtin/vector.lua index eed368f..654a839 100644 --- a/builtin/vector.lua +++ b/builtin/vector.lua @@ -43,7 +43,10 @@ mt_vec2.__index = { assert(type(self.x) == "number") assert(type(self.y) == "number") return self - end + end, + round = function(self) + return vec2(math.round(self.x), math.round(self.y)) + end, } function vec2(a, b) @@ -91,7 +94,10 @@ mt_vec3.__index = { assert(type(self.y) == "number") assert(type(self.z) == "number") return self - end + end, + round = function(self) + return vec3(math.floor(self.x), math.floor(self.y), math.floor(self.z)) + end, } function vec3(a, b, c) diff --git a/client.go b/client.go index d27af33..13795e5 100644 --- a/client.go +++ b/client.go @@ -212,6 +212,8 @@ func l_client_enable(l *lua.LState) int { switch compname { case "auth": component = &Auth{} + case "map": + component = &Map{} default: panic("invalid component: " + compname) } diff --git a/convert/push_auto.go b/convert/push_auto.go index 282a5f5..beb30c2 100644 --- a/convert/push_auto.go +++ b/convert/push_auto.go @@ -6,7 +6,7 @@ import ( "github.com/yuin/gopher-lua" ) -func pushAnimType(l *lua.LState, val mt.AnimType) lua.LValue { +func PushAnimType(l *lua.LState, val mt.AnimType) lua.LValue { switch val { case mt.NoAnim: return lua.LNil @@ -19,7 +19,7 @@ func pushAnimType(l *lua.LState, val mt.AnimType) lua.LValue { return lua.LNil } -func pushChatMsgType(l *lua.LState, val mt.ChatMsgType) lua.LValue { +func PushChatMsgType(l *lua.LState, val mt.ChatMsgType) lua.LValue { switch val { case mt.RawMsg: return lua.LString("raw") @@ -34,7 +34,7 @@ func pushChatMsgType(l *lua.LState, val mt.ChatMsgType) lua.LValue { return lua.LNil } -func pushHotbarParam(l *lua.LState, val mt.HotbarParam) lua.LValue { +func PushHotbarParam(l *lua.LState, val mt.HotbarParam) lua.LValue { switch val { case mt.HotbarSize: return lua.LString("size") @@ -47,7 +47,7 @@ func pushHotbarParam(l *lua.LState, val mt.HotbarParam) lua.LValue { return lua.LNil } -func pushHUDField(l *lua.LState, val mt.HUDField) lua.LValue { +func PushHUDField(l *lua.LState, val mt.HUDField) lua.LValue { switch val { case mt.HUDPos: return lua.LString("pos") @@ -80,7 +80,7 @@ func pushHUDField(l *lua.LState, val mt.HUDField) lua.LValue { return lua.LNil } -func pushHUDType(l *lua.LState, val mt.HUDType) lua.LValue { +func PushHUDType(l *lua.LState, val mt.HUDType) lua.LValue { switch val { case mt.ImgHUD: return lua.LString("img") @@ -99,7 +99,7 @@ func pushHUDType(l *lua.LState, val mt.HUDType) lua.LValue { return lua.LNil } -func pushKickReason(l *lua.LState, val mt.KickReason) lua.LValue { +func PushKickReason(l *lua.LState, val mt.KickReason) lua.LValue { switch val { case mt.WrongPasswd: return lua.LString("wrong_passwd") @@ -132,7 +132,7 @@ func pushKickReason(l *lua.LState, val mt.KickReason) lua.LValue { return lua.LNil } -func pushModChanSig(l *lua.LState, val mt.ModChanSig) lua.LValue { +func PushModChanSig(l *lua.LState, val mt.ModChanSig) lua.LValue { switch val { case mt.JoinOK: return lua.LString("join_ok") @@ -151,7 +151,7 @@ func pushModChanSig(l *lua.LState, val mt.ModChanSig) lua.LValue { return lua.LNil } -func pushPlayerListUpdateType(l *lua.LState, val mt.PlayerListUpdateType) lua.LValue { +func PushPlayerListUpdateType(l *lua.LState, val mt.PlayerListUpdateType) lua.LValue { switch val { case mt.InitPlayers: return lua.LString("init") @@ -164,7 +164,7 @@ func pushPlayerListUpdateType(l *lua.LState, val mt.PlayerListUpdateType) lua.LV return lua.LNil } -func pushSoundSrcType(l *lua.LState, val mt.SoundSrcType) lua.LValue { +func PushSoundSrcType(l *lua.LState, val mt.SoundSrcType) lua.LValue { switch val { case mt.NoSrc: return lua.LNil @@ -177,86 +177,76 @@ func pushSoundSrcType(l *lua.LState, val mt.SoundSrcType) lua.LValue { return lua.LNil } -func pushAuthMethods(l *lua.LState, val mt.AuthMethods) lua.LValue { +func PushAuthMethods(l *lua.LState, val mt.AuthMethods) lua.LValue { tbl := l.NewTable() - if val&mt.LegacyPasswd != 0 { - l.SetField(tbl, "legacy_passwd", lua.LTrue) - } - if val&mt.SRP != 0 { - l.SetField(tbl, "srp", lua.LTrue) - } - if val&mt.FirstSRP != 0 { - l.SetField(tbl, "first_srp", lua.LTrue) - } + l.SetField(tbl, "legacy_passwd", lua.LBool(val&mt.LegacyPasswd != 0)) + l.SetField(tbl, "srp", lua.LBool(val&mt.SRP != 0)) + l.SetField(tbl, "first_srp", lua.LBool(val&mt.FirstSRP != 0)) return tbl } -func pushCSMRestrictionFlags(l *lua.LState, val mt.CSMRestrictionFlags) lua.LValue { +func PushCSMRestrictionFlags(l *lua.LState, val mt.CSMRestrictionFlags) lua.LValue { tbl := l.NewTable() - if val&mt.NoCSMs != 0 { - l.SetField(tbl, "no_csms", lua.LTrue) - } - if val&mt.NoChatMsgs != 0 { - l.SetField(tbl, "no_chat_msgs", lua.LTrue) - } - if val&mt.NoNodeDefs != 0 { - l.SetField(tbl, "no_node_defs", lua.LTrue) - } - if val&mt.LimitMapRange != 0 { - l.SetField(tbl, "limit_map_range", lua.LTrue) - } - if val&mt.NoPlayerList != 0 { - l.SetField(tbl, "no_player_list", lua.LTrue) - } + l.SetField(tbl, "no_csms", lua.LBool(val&mt.NoCSMs != 0)) + l.SetField(tbl, "no_chat_msgs", lua.LBool(val&mt.NoChatMsgs != 0)) + l.SetField(tbl, "no_node_defs", lua.LBool(val&mt.NoNodeDefs != 0)) + l.SetField(tbl, "limit_map_range", lua.LBool(val&mt.LimitMapRange != 0)) + l.SetField(tbl, "no_player_list", lua.LBool(val&mt.NoPlayerList != 0)) return tbl } -func pushHUDFlags(l *lua.LState, val mt.HUDFlags) lua.LValue { +func PushHUDFlags(l *lua.LState, val mt.HUDFlags) lua.LValue { tbl := l.NewTable() - if val&mt.ShowHotbar != 0 { - l.SetField(tbl, "hotbar", lua.LTrue) - } - if val&mt.ShowHealthBar != 0 { - l.SetField(tbl, "health_bar", lua.LTrue) - } - if val&mt.ShowCrosshair != 0 { - l.SetField(tbl, "crosshair", lua.LTrue) - } - if val&mt.ShowWieldedItem != 0 { - l.SetField(tbl, "wielded_item", lua.LTrue) - } - if val&mt.ShowBreathBar != 0 { - l.SetField(tbl, "breath_bar", lua.LTrue) - } - if val&mt.ShowMinimap != 0 { - l.SetField(tbl, "minimap", lua.LTrue) - } - if val&mt.ShowRadarMinimap != 0 { - l.SetField(tbl, "radar_minimap", lua.LTrue) - } + l.SetField(tbl, "hotbar", lua.LBool(val&mt.ShowHotbar != 0)) + l.SetField(tbl, "health_bar", lua.LBool(val&mt.ShowHealthBar != 0)) + l.SetField(tbl, "crosshair", lua.LBool(val&mt.ShowCrosshair != 0)) + l.SetField(tbl, "wielded_item", lua.LBool(val&mt.ShowWieldedItem != 0)) + l.SetField(tbl, "breath_bar", lua.LBool(val&mt.ShowBreathBar != 0)) + l.SetField(tbl, "minimap", lua.LBool(val&mt.ShowMinimap != 0)) + l.SetField(tbl, "radar_minimap", lua.LBool(val&mt.ShowRadarMinimap != 0)) + return tbl +} + +func PushMapBlkFlags(l *lua.LState, val mt.MapBlkFlags) lua.LValue { + tbl := l.NewTable() + l.SetField(tbl, "is_underground", lua.LBool(val&mt.BlkIsUnderground != 0)) + l.SetField(tbl, "day_night_diff", lua.LBool(val&mt.BlkDayNightDiff != 0)) + l.SetField(tbl, "light_expired", lua.LBool(val&mt.BlkLightExpired != 0)) + l.SetField(tbl, "not_generated", lua.LBool(val&mt.BlkNotGenerated != 0)) return tbl } -func pushHUD(l *lua.LState, val mt.HUD) lua.LValue { +func PushHUD(l *lua.LState, val mt.HUD) lua.LValue { tbl := l.NewTable() - l.SetField(tbl, "align", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Align[0]), lua.LNumber(val.Align[1])})) + l.SetField(tbl, "align", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Align[0]), lua.LNumber(val.Align[1])})) l.SetField(tbl, "dir", lua.LNumber(val.Dir)) l.SetField(tbl, "item", lua.LNumber(val.Item)) l.SetField(tbl, "name", lua.LString(string(val.Name))) l.SetField(tbl, "number", lua.LNumber(val.Number)) - l.SetField(tbl, "offset", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Offset[0]), lua.LNumber(val.Offset[1])})) - l.SetField(tbl, "pos", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1])})) - l.SetField(tbl, "scale", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Scale[0]), lua.LNumber(val.Scale[1])})) - l.SetField(tbl, "size", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Size[0]), lua.LNumber(val.Size[1])})) + l.SetField(tbl, "offset", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Offset[0]), lua.LNumber(val.Offset[1])})) + l.SetField(tbl, "pos", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1])})) + l.SetField(tbl, "scale", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Scale[0]), lua.LNumber(val.Scale[1])})) + l.SetField(tbl, "size", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Size[0]), lua.LNumber(val.Size[1])})) l.SetField(tbl, "text", lua.LString(string(val.Text))) l.SetField(tbl, "text_2", lua.LString(string(val.Text2))) - l.SetField(tbl, "type", pushHUDType(l, val.Type)) - l.SetField(tbl, "world_pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.WorldPos[0]), lua.LNumber(val.WorldPos[1]), lua.LNumber(val.WorldPos[2])})) + l.SetField(tbl, "type", PushHUDType(l, val.Type)) + l.SetField(tbl, "world_pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.WorldPos[0]), lua.LNumber(val.WorldPos[1]), lua.LNumber(val.WorldPos[2])})) l.SetField(tbl, "z_index", lua.LNumber(val.ZIndex)) return tbl } -func pushNode(l *lua.LState, val mt.Node) lua.LValue { +func PushMapBlk(l *lua.LState, val mt.MapBlk) lua.LValue { + tbl := l.NewTable() + l.SetField(tbl, "flags", PushMapBlkFlags(l, val.Flags)) + l.SetField(tbl, "lit_from", lua.LNumber(val.LitFrom)) + l.SetField(tbl, "node_metas", PushNodeMetas(l, val.NodeMetas)) + l.SetField(tbl, "param0", Push4096[mt.Content](l, val.Param0)) + l.SetField(tbl, "param1", Push4096[uint8](l, val.Param1)) + l.SetField(tbl, "param2", Push4096[uint8](l, val.Param2)) + return tbl +} + +func PushNode(l *lua.LState, val mt.Node) lua.LValue { tbl := l.NewTable() l.SetField(tbl, "param0", lua.LNumber(val.Param0)) l.SetField(tbl, "param1", lua.LNumber(val.Param1)) @@ -264,12 +254,29 @@ func pushNode(l *lua.LState, val mt.Node) lua.LValue { return tbl } -func pushTileAnim(l *lua.LState, val mt.TileAnim) lua.LValue { +func PushNodeMeta(l *lua.LState, val mt.NodeMeta) lua.LValue { + tbl := l.NewTable() + l.SetField(tbl, "fields", PushNodeMetaFields(l, val.Fields)) + l.SetField(tbl, "inv", PushInv(l, val.Inv)) + return tbl +} + +func PushTileAnim(l *lua.LState, val mt.TileAnim) lua.LValue { tbl := l.NewTable() - l.SetField(tbl, "aspect_ratio", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.AspectRatio[0]), lua.LNumber(val.AspectRatio[1])})) + l.SetField(tbl, "aspect_ratio", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.AspectRatio[0]), lua.LNumber(val.AspectRatio[1])})) l.SetField(tbl, "duration", lua.LNumber(val.Duration)) - l.SetField(tbl, "n_frames", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.NFrames[0]), lua.LNumber(val.NFrames[1])})) - l.SetField(tbl, "type", pushAnimType(l, val.Type)) + l.SetField(tbl, "n_frames", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.NFrames[0]), lua.LNumber(val.NFrames[1])})) + l.SetField(tbl, "type", PushAnimType(l, val.Type)) + return tbl +} + +func PushToolCaps(l *lua.LState, val mt.ToolCaps) lua.LValue { + tbl := l.NewTable() + l.SetField(tbl, "attack_cooldown", lua.LNumber(val.AttackCooldown)) + l.SetField(tbl, "dmg_groups", PushGroups(l, val.DmgGroups)) + l.SetField(tbl, "group_caps", PushGroupCaps(l, val.GroupCaps)) + l.SetField(tbl, "max_drop_lvl", lua.LNumber(val.MaxDropLvl)) + l.SetField(tbl, "punch_uses", lua.LNumber(val.PunchUses)) return tbl } @@ -405,49 +412,50 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { switch val := pkt.Cmd.(type) { case *mt.ToCltAcceptAuth: l.SetField(tbl, "map_seed", lua.LNumber(val.MapSeed)) - l.SetField(tbl, "player_pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.PlayerPos[0]), lua.LNumber(val.PlayerPos[1]), lua.LNumber(val.PlayerPos[2])})) + l.SetField(tbl, "player_pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.PlayerPos[0]), lua.LNumber(val.PlayerPos[1]), lua.LNumber(val.PlayerPos[2])})) l.SetField(tbl, "send_interval", lua.LNumber(val.SendInterval)) - l.SetField(tbl, "sudo_auth_methods", pushAuthMethods(l, val.SudoAuthMethods)) + l.SetField(tbl, "sudo_auth_methods", PushAuthMethods(l, val.SudoAuthMethods)) case *mt.ToCltAddHUD: - l.SetField(tbl, "hud", pushHUD(l, val.HUD)) + l.SetField(tbl, "hud", PushHUD(l, val.HUD)) l.SetField(tbl, "id", lua.LNumber(val.ID)) case *mt.ToCltAddNode: l.SetField(tbl, "keep_meta", lua.LBool(val.KeepMeta)) - l.SetField(tbl, "node", pushNode(l, val.Node)) - l.SetField(tbl, "pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) + l.SetField(tbl, "node", PushNode(l, val.Node)) + l.SetField(tbl, "pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) case *mt.ToCltAddParticleSpawner: - l.SetField(tbl, "acc", pushBox3(l, [2][3]lua.LNumber{{lua.LNumber(val.Acc[0][0]), lua.LNumber(val.Acc[0][1]), lua.LNumber(val.Acc[0][2])}, {lua.LNumber(val.Acc[1][0]), lua.LNumber(val.Acc[1][1]), lua.LNumber(val.Acc[1][2])}})) + l.SetField(tbl, "acc", PushBox3(l, [2][3]lua.LNumber{{lua.LNumber(val.Acc[0][0]), lua.LNumber(val.Acc[0][1]), lua.LNumber(val.Acc[0][2])}, {lua.LNumber(val.Acc[1][0]), lua.LNumber(val.Acc[1][1]), lua.LNumber(val.Acc[1][2])}})) l.SetField(tbl, "amount", lua.LNumber(val.Amount)) - l.SetField(tbl, "anim_params", pushTileAnim(l, val.AnimParams)) + l.SetField(tbl, "anim_params", PushTileAnim(l, val.AnimParams)) l.SetField(tbl, "ao_collision", lua.LBool(val.AOCollision)) l.SetField(tbl, "collide", lua.LBool(val.Collide)) l.SetField(tbl, "collision_rm", lua.LBool(val.CollisionRm)) l.SetField(tbl, "duration", lua.LNumber(val.Duration)) - l.SetField(tbl, "expiration_time", pushBox1(l, [2]lua.LNumber{lua.LNumber(val.ExpirationTime[0]), lua.LNumber(val.ExpirationTime[1])})) + l.SetField(tbl, "expiration_time", PushBox1(l, [2]lua.LNumber{lua.LNumber(val.ExpirationTime[0]), lua.LNumber(val.ExpirationTime[1])})) l.SetField(tbl, "glow", lua.LNumber(val.Glow)) l.SetField(tbl, "id", lua.LNumber(val.ID)) l.SetField(tbl, "node_param0", lua.LNumber(val.NodeParam0)) l.SetField(tbl, "node_param2", lua.LNumber(val.NodeParam2)) l.SetField(tbl, "node_tile", lua.LNumber(val.NodeTile)) - l.SetField(tbl, "pos", pushBox3(l, [2][3]lua.LNumber{{lua.LNumber(val.Pos[0][0]), lua.LNumber(val.Pos[0][1]), lua.LNumber(val.Pos[0][2])}, {lua.LNumber(val.Pos[1][0]), lua.LNumber(val.Pos[1][1]), lua.LNumber(val.Pos[1][2])}})) - l.SetField(tbl, "size", pushBox1(l, [2]lua.LNumber{lua.LNumber(val.Size[0]), lua.LNumber(val.Size[1])})) + l.SetField(tbl, "pos", PushBox3(l, [2][3]lua.LNumber{{lua.LNumber(val.Pos[0][0]), lua.LNumber(val.Pos[0][1]), lua.LNumber(val.Pos[0][2])}, {lua.LNumber(val.Pos[1][0]), lua.LNumber(val.Pos[1][1]), lua.LNumber(val.Pos[1][2])}})) + l.SetField(tbl, "size", PushBox1(l, [2]lua.LNumber{lua.LNumber(val.Size[0]), lua.LNumber(val.Size[1])})) l.SetField(tbl, "texture", lua.LString(string(val.Texture))) - l.SetField(tbl, "vel", pushBox3(l, [2][3]lua.LNumber{{lua.LNumber(val.Vel[0][0]), lua.LNumber(val.Vel[0][1]), lua.LNumber(val.Vel[0][2])}, {lua.LNumber(val.Vel[1][0]), lua.LNumber(val.Vel[1][1]), lua.LNumber(val.Vel[1][2])}})) + l.SetField(tbl, "vel", PushBox3(l, [2][3]lua.LNumber{{lua.LNumber(val.Vel[0][0]), lua.LNumber(val.Vel[0][1]), lua.LNumber(val.Vel[0][2])}, {lua.LNumber(val.Vel[1][0]), lua.LNumber(val.Vel[1][1]), lua.LNumber(val.Vel[1][2])}})) l.SetField(tbl, "vertical", lua.LBool(val.Vertical)) case *mt.ToCltAddPlayerVel: - l.SetField(tbl, "vel", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Vel[0]), lua.LNumber(val.Vel[1]), lua.LNumber(val.Vel[2])})) + l.SetField(tbl, "vel", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Vel[0]), lua.LNumber(val.Vel[1]), lua.LNumber(val.Vel[2])})) case *mt.ToCltBlkData: - l.SetField(tbl, "blkpos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Blkpos[0]), lua.LNumber(val.Blkpos[1]), lua.LNumber(val.Blkpos[2])})) + l.SetField(tbl, "blk", PushMapBlk(l, val.Blk)) + l.SetField(tbl, "blkpos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Blkpos[0]), lua.LNumber(val.Blkpos[1]), lua.LNumber(val.Blkpos[2])})) case *mt.ToCltBreath: l.SetField(tbl, "breath", lua.LNumber(val.Breath)) case *mt.ToCltChangeHUD: if val.Field == mt.HUDAlign { - l.SetField(tbl, "align", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Align[0]), lua.LNumber(val.Align[1])})) + l.SetField(tbl, "align", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Align[0]), lua.LNumber(val.Align[1])})) } if val.Field == mt.HUDDir { l.SetField(tbl, "dir", lua.LNumber(val.Dir)) } - l.SetField(tbl, "field", pushHUDField(l, val.Field)) + l.SetField(tbl, "field", PushHUDField(l, val.Field)) l.SetField(tbl, "id", lua.LNumber(val.ID)) if val.Field == mt.HUDItem { l.SetField(tbl, "item", lua.LNumber(val.Item)) @@ -459,13 +467,13 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "number", lua.LNumber(val.Number)) } if val.Field == mt.HUDOffset { - l.SetField(tbl, "offset", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Offset[0]), lua.LNumber(val.Offset[1])})) + l.SetField(tbl, "offset", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Offset[0]), lua.LNumber(val.Offset[1])})) } if val.Field == mt.HUDPos { - l.SetField(tbl, "pos", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1])})) + l.SetField(tbl, "pos", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1])})) } if val.Field == mt.HUDSize { - l.SetField(tbl, "size", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Size[0]), lua.LNumber(val.Size[1])})) + l.SetField(tbl, "size", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Size[0]), lua.LNumber(val.Size[1])})) } if val.Field == mt.HUDText { l.SetField(tbl, "text", lua.LString(string(val.Text))) @@ -474,7 +482,7 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "text_2", lua.LString(string(val.Text2))) } if val.Field == mt.HUDWorldPos { - l.SetField(tbl, "world_pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.WorldPos[0]), lua.LNumber(val.WorldPos[1]), lua.LNumber(val.WorldPos[2])})) + l.SetField(tbl, "world_pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.WorldPos[0]), lua.LNumber(val.WorldPos[1]), lua.LNumber(val.WorldPos[2])})) } if val.Field == mt.HUDZIndex { l.SetField(tbl, "z_index", lua.LNumber(val.ZIndex)) @@ -483,19 +491,19 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "sender", lua.LString(string(val.Sender))) l.SetField(tbl, "text", lua.LString(string(val.Text))) l.SetField(tbl, "timestamp", lua.LNumber(val.Timestamp)) - l.SetField(tbl, "type", pushChatMsgType(l, val.Type)) + l.SetField(tbl, "type", PushChatMsgType(l, val.Type)) case *mt.ToCltCloudParams: - l.SetField(tbl, "ambient_color", pushColor(l, val.AmbientColor)) + l.SetField(tbl, "ambient_color", PushColor(l, val.AmbientColor)) l.SetField(tbl, "density", lua.LNumber(val.Density)) - l.SetField(tbl, "diffuse_color", pushColor(l, val.DiffuseColor)) + l.SetField(tbl, "diffuse_color", PushColor(l, val.DiffuseColor)) l.SetField(tbl, "height", lua.LNumber(val.Height)) - l.SetField(tbl, "speed", pushVec2(l, [2]lua.LNumber{lua.LNumber(val.Speed[0]), lua.LNumber(val.Speed[1])})) + l.SetField(tbl, "speed", PushVec2(l, [2]lua.LNumber{lua.LNumber(val.Speed[0]), lua.LNumber(val.Speed[1])})) l.SetField(tbl, "thickness", lua.LNumber(val.Thickness)) case *mt.ToCltCSMRestrictionFlags: - l.SetField(tbl, "flags", pushCSMRestrictionFlags(l, val.Flags)) + l.SetField(tbl, "flags", PushCSMRestrictionFlags(l, val.Flags)) l.SetField(tbl, "map_range", lua.LNumber(val.MapRange)) case *mt.ToCltDeathScreen: - l.SetField(tbl, "point_at", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.PointAt[0]), lua.LNumber(val.PointAt[1]), lua.LNumber(val.PointAt[2])})) + l.SetField(tbl, "point_at", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.PointAt[0]), lua.LNumber(val.PointAt[1]), lua.LNumber(val.PointAt[2])})) l.SetField(tbl, "point_cam", lua.LBool(val.PointCam)) case *mt.ToCltDelParticleSpawner: l.SetField(tbl, "id", lua.LNumber(val.ID)) @@ -505,8 +513,8 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "len", lua.LNumber(val.Len)) l.SetField(tbl, "name", lua.LString(string(val.Name))) case *mt.ToCltEyeOffset: - l.SetField(tbl, "first", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.First[0]), lua.LNumber(val.First[1]), lua.LNumber(val.First[2])})) - l.SetField(tbl, "third", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Third[0]), lua.LNumber(val.Third[1]), lua.LNumber(val.Third[2])})) + l.SetField(tbl, "first", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.First[0]), lua.LNumber(val.First[1]), lua.LNumber(val.First[2])})) + l.SetField(tbl, "third", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Third[0]), lua.LNumber(val.Third[1]), lua.LNumber(val.Third[2])})) case *mt.ToCltFadeSound: l.SetField(tbl, "gain", lua.LNumber(val.Gain)) l.SetField(tbl, "id", lua.LNumber(val.ID)) @@ -518,7 +526,7 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "multiplier", lua.LBool(val.Multiplier)) l.SetField(tbl, "transition_time", lua.LNumber(val.TransitionTime)) case *mt.ToCltHello: - l.SetField(tbl, "auth_methods", pushAuthMethods(l, val.AuthMethods)) + l.SetField(tbl, "auth_methods", PushAuthMethods(l, val.AuthMethods)) l.SetField(tbl, "compression", lua.LNumber(val.Compression)) l.SetField(tbl, "proto_ver", lua.LNumber(val.ProtoVer)) l.SetField(tbl, "serialize_ver", lua.LNumber(val.SerializeVer)) @@ -526,8 +534,8 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { case *mt.ToCltHP: l.SetField(tbl, "hp", lua.LNumber(val.HP)) case *mt.ToCltHUDFlags: - l.SetField(tbl, "flags", pushHUDFlags(l, val.Flags)) - l.SetField(tbl, "mask", pushHUDFlags(l, val.Mask)) + l.SetField(tbl, "flags", PushHUDFlags(l, val.Flags)) + l.SetField(tbl, "mask", PushHUDFlags(l, val.Mask)) case *mt.ToCltInv: l.SetField(tbl, "inv", lua.LString(string(val.Inv))) case *mt.ToCltInvFormspec: @@ -536,18 +544,18 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { if val.Reason == mt.Custom || val.Reason == mt.Shutdown || val.Reason == mt.Crash { l.SetField(tbl, "custom", lua.LString(string(val.Custom))) } - l.SetField(tbl, "reason", pushKickReason(l, val.Reason)) + l.SetField(tbl, "reason", PushKickReason(l, val.Reason)) if val.Reason == mt.Shutdown || val.Reason == mt.Crash { l.SetField(tbl, "reconnect", lua.LBool(val.Reconnect)) } case *mt.ToCltLegacyKick: l.SetField(tbl, "reason", lua.LString(string(val.Reason))) case *mt.ToCltLocalPlayerAnim: - l.SetField(tbl, "dig", pushBox1(l, [2]lua.LNumber{lua.LNumber(val.Dig[0]), lua.LNumber(val.Dig[1])})) - l.SetField(tbl, "idle", pushBox1(l, [2]lua.LNumber{lua.LNumber(val.Idle[0]), lua.LNumber(val.Idle[1])})) + l.SetField(tbl, "dig", PushBox1(l, [2]lua.LNumber{lua.LNumber(val.Dig[0]), lua.LNumber(val.Dig[1])})) + l.SetField(tbl, "idle", PushBox1(l, [2]lua.LNumber{lua.LNumber(val.Idle[0]), lua.LNumber(val.Idle[1])})) l.SetField(tbl, "speed", lua.LNumber(val.Speed)) - l.SetField(tbl, "walk", pushBox1(l, [2]lua.LNumber{lua.LNumber(val.Walk[0]), lua.LNumber(val.Walk[1])})) - l.SetField(tbl, "walk_dig", pushBox1(l, [2]lua.LNumber{lua.LNumber(val.WalkDig[0]), lua.LNumber(val.WalkDig[1])})) + l.SetField(tbl, "walk", PushBox1(l, [2]lua.LNumber{lua.LNumber(val.Walk[0]), lua.LNumber(val.Walk[1])})) + l.SetField(tbl, "walk_dig", PushBox1(l, [2]lua.LNumber{lua.LNumber(val.WalkDig[0]), lua.LNumber(val.WalkDig[1])})) case *mt.ToCltMediaPush: l.SetField(tbl, "data", lua.LString(string(val.Data))) l.SetField(tbl, "filename", lua.LString(string(val.Filename))) @@ -559,7 +567,7 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "sender", lua.LString(string(val.Sender))) case *mt.ToCltModChanSig: l.SetField(tbl, "channel", lua.LString(string(val.Channel))) - l.SetField(tbl, "signal", pushModChanSig(l, val.Signal)) + l.SetField(tbl, "signal", PushModChanSig(l, val.Signal)) case *mt.ToCltMoonParams: l.SetField(tbl, "size", lua.LNumber(val.Size)) l.SetField(tbl, "texture", lua.LString(string(val.Texture))) @@ -567,7 +575,7 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "visible", lua.LBool(val.Visible)) case *mt.ToCltMovePlayer: l.SetField(tbl, "pitch", lua.LNumber(val.Pitch)) - l.SetField(tbl, "pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) + l.SetField(tbl, "pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) l.SetField(tbl, "yaw", lua.LNumber(val.Yaw)) case *mt.ToCltMovement: l.SetField(tbl, "air_accel", lua.LNumber(val.AirAccel)) @@ -582,6 +590,8 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "sink", lua.LNumber(val.Sink)) l.SetField(tbl, "smoothing", lua.LNumber(val.Smoothing)) l.SetField(tbl, "walk_speed", lua.LNumber(val.WalkSpeed)) + case *mt.ToCltNodeMetasChanged: + l.SetField(tbl, "changed", PushChangedNodeMetas(l, val.Changed)) case *mt.ToCltOverrideDayNightRatio: l.SetField(tbl, "override", lua.LBool(val.Override)) l.SetField(tbl, "ratio", lua.LNumber(val.Ratio)) @@ -593,56 +603,56 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "loop", lua.LBool(val.Loop)) l.SetField(tbl, "name", lua.LString(string(val.Name))) l.SetField(tbl, "pitch", lua.LNumber(val.Pitch)) - l.SetField(tbl, "pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) + l.SetField(tbl, "pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) l.SetField(tbl, "src_aoid", lua.LNumber(val.SrcAOID)) - l.SetField(tbl, "src_type", pushSoundSrcType(l, val.SrcType)) + l.SetField(tbl, "src_type", PushSoundSrcType(l, val.SrcType)) case *mt.ToCltPrivs: - l.SetField(tbl, "privs", pushStringSet(l, val.Privs)) + l.SetField(tbl, "privs", PushStringSet(l, val.Privs)) case *mt.ToCltRemoveNode: - l.SetField(tbl, "pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) + l.SetField(tbl, "pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) case *mt.ToCltRmHUD: l.SetField(tbl, "id", lua.LNumber(val.ID)) case *mt.ToCltSetHotbarParam: l.SetField(tbl, "img", lua.LString(string(val.Img))) - l.SetField(tbl, "param", pushHotbarParam(l, val.Param)) + l.SetField(tbl, "param", PushHotbarParam(l, val.Param)) l.SetField(tbl, "size", lua.LNumber(val.Size)) case *mt.ToCltShowFormspec: l.SetField(tbl, "formname", lua.LString(string(val.Formname))) l.SetField(tbl, "formspec", lua.LString(string(val.Formspec))) case *mt.ToCltSkyParams: - l.SetField(tbl, "bg_color", pushColor(l, val.BgColor)) + l.SetField(tbl, "bg_color", PushColor(l, val.BgColor)) l.SetField(tbl, "clouds", lua.LBool(val.Clouds)) if val.Type == "regular" { - l.SetField(tbl, "dawn_horizon", pushColor(l, val.DawnHorizon)) + l.SetField(tbl, "dawn_horizon", PushColor(l, val.DawnHorizon)) } if val.Type == "regular" { - l.SetField(tbl, "dawn_sky", pushColor(l, val.DawnSky)) + l.SetField(tbl, "dawn_sky", PushColor(l, val.DawnSky)) } if val.Type == "regular" { - l.SetField(tbl, "day_horizon", pushColor(l, val.DayHorizon)) + l.SetField(tbl, "day_horizon", PushColor(l, val.DayHorizon)) } if val.Type == "regular" { - l.SetField(tbl, "day_sky", pushColor(l, val.DaySky)) + l.SetField(tbl, "day_sky", PushColor(l, val.DaySky)) } l.SetField(tbl, "fog_tint_type", lua.LString(string(val.FogTintType))) if val.Type == "regular" { - l.SetField(tbl, "indoor", pushColor(l, val.Indoor)) + l.SetField(tbl, "indoor", PushColor(l, val.Indoor)) } - l.SetField(tbl, "moon_fog_tint", pushColor(l, val.MoonFogTint)) + l.SetField(tbl, "moon_fog_tint", PushColor(l, val.MoonFogTint)) if val.Type == "regular" { - l.SetField(tbl, "night_horizon", pushColor(l, val.NightHorizon)) + l.SetField(tbl, "night_horizon", PushColor(l, val.NightHorizon)) } if val.Type == "regular" { - l.SetField(tbl, "night_sky", pushColor(l, val.NightSky)) + l.SetField(tbl, "night_sky", PushColor(l, val.NightSky)) } - l.SetField(tbl, "sun_fog_tint", pushColor(l, val.SunFogTint)) + l.SetField(tbl, "sun_fog_tint", PushColor(l, val.SunFogTint)) if val.Type == "skybox" { - l.SetField(tbl, "textures", pushTextureList(l, val.Textures)) + l.SetField(tbl, "textures", PushStringList[mt.Texture](l, val.Textures)) } l.SetField(tbl, "type", lua.LString(string(val.Type))) case *mt.ToCltSpawnParticle: - l.SetField(tbl, "acc", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Acc[0]), lua.LNumber(val.Acc[1]), lua.LNumber(val.Acc[2])})) - l.SetField(tbl, "anim_params", pushTileAnim(l, val.AnimParams)) + l.SetField(tbl, "acc", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Acc[0]), lua.LNumber(val.Acc[1]), lua.LNumber(val.Acc[2])})) + l.SetField(tbl, "anim_params", PushTileAnim(l, val.AnimParams)) l.SetField(tbl, "ao_collision", lua.LBool(val.AOCollision)) l.SetField(tbl, "collide", lua.LBool(val.Collide)) l.SetField(tbl, "collision_rm", lua.LBool(val.CollisionRm)) @@ -651,16 +661,16 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "node_param0", lua.LNumber(val.NodeParam0)) l.SetField(tbl, "node_param2", lua.LNumber(val.NodeParam2)) l.SetField(tbl, "node_tile", lua.LNumber(val.NodeTile)) - l.SetField(tbl, "pos", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) + l.SetField(tbl, "pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1]), lua.LNumber(val.Pos[2])})) l.SetField(tbl, "size", lua.LNumber(val.Size)) l.SetField(tbl, "texture", lua.LString(string(val.Texture))) - l.SetField(tbl, "vel", pushVec3(l, [3]lua.LNumber{lua.LNumber(val.Vel[0]), lua.LNumber(val.Vel[1]), lua.LNumber(val.Vel[2])})) + l.SetField(tbl, "vel", PushVec3(l, [3]lua.LNumber{lua.LNumber(val.Vel[0]), lua.LNumber(val.Vel[1]), lua.LNumber(val.Vel[2])})) l.SetField(tbl, "vertical", lua.LBool(val.Vertical)) case *mt.ToCltSRPBytesSaltB: l.SetField(tbl, "b", lua.LString(string(val.B))) l.SetField(tbl, "salt", lua.LString(string(val.Salt))) case *mt.ToCltStarParams: - l.SetField(tbl, "color", pushColor(l, val.Color)) + l.SetField(tbl, "color", PushColor(l, val.Color)) l.SetField(tbl, "count", lua.LNumber(val.Count)) l.SetField(tbl, "size", lua.LNumber(val.Size)) l.SetField(tbl, "visible", lua.LBool(val.Visible)) @@ -677,8 +687,8 @@ func PushPkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { l.SetField(tbl, "speed", lua.LNumber(val.Speed)) l.SetField(tbl, "time", lua.LNumber(val.Time)) case *mt.ToCltUpdatePlayerList: - l.SetField(tbl, "players", pushStringList(l, val.Players)) - l.SetField(tbl, "type", pushPlayerListUpdateType(l, val.Type)) + l.SetField(tbl, "players", PushStringList[string](l, val.Players)) + l.SetField(tbl, "type", PushPlayerListUpdateType(l, val.Type)) } return tbl } diff --git a/convert/push_mkauto.lua b/convert/push_mkauto.lua index 3e02932..df13198 100755 --- a/convert/push_mkauto.lua +++ b/convert/push_mkauto.lua @@ -5,7 +5,7 @@ local funcs = "" for name, fields in spairs(parse_spec("client/enum")) do local camel = camel_case(name) - funcs = funcs .. "func push" .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\tswitch val {\n" + funcs = funcs .. "func Push" .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\tswitch val {\n" for _, var in ipairs(fields) do funcs = funcs .. "\tcase mt." .. apply_prefix(fields, var) .. ":\n\t\t" .. @@ -17,11 +17,10 @@ end for name, fields in spairs(parse_spec("client/flag")) do local camel = camel_case(name) - funcs = funcs .. "func push" .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\ttbl := l.NewTable()\n" + funcs = funcs .. "func Push" .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\ttbl := l.NewTable()\n" for _, var in ipairs(fields) do - funcs = funcs .. "\tif val&mt." .. apply_prefix(fields, var) - .. " != 0 {\n\t\tl.SetField(tbl, \"" .. var .. "\", lua.LTrue)\n\t}\n" + funcs = funcs .. "\tl.SetField(tbl, \"" .. var .. "\", lua.LBool(val&mt." .. apply_prefix(fields, var) .. " != 0))\n" end funcs = funcs .. "\treturn tbl\n}\n\n" @@ -32,22 +31,24 @@ local tolua = { fixed_string = "lua.LString(string(VAL[:]))", boolean = "lua.LBool(VAL)", number = "lua.LNumber(VAL)", - vec2 = "pushVec2(l, [2]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1])})", - vec3 = "pushVec3(l, [3]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1]), lua.LNumber(VAL[2])})", - box1 = "pushBox1(l, [2]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1])})", - box2 = "pushBox2(l, [2][2]lua.LNumber{{lua.LNumber(VAL[0][0]), lua.LNumber(VAL[0][1])}, {lua.LNumber(VAL[1][0]), lua.LNumber(VAL[1][1])}})", - box3 = "pushBox3(l, [2][3]lua.LNumber{{lua.LNumber(VAL[0][0]), lua.LNumber(VAL[0][1]), lua.LNumber(VAL[0][2])}, {lua.LNumber(VAL[1][0]), lua.LNumber(VAL[1][1]), lua.LNumber(VAL[1][2])}})", + vec2 = "PushVec2(l, [2]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1])})", + vec3 = "PushVec3(l, [3]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1]), lua.LNumber(VAL[2])})", + box1 = "PushBox1(l, [2]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1])})", + box2 = "PushBox2(l, [2][2]lua.LNumber{{lua.LNumber(VAL[0][0]), lua.LNumber(VAL[0][1])}, {lua.LNumber(VAL[1][0]), lua.LNumber(VAL[1][1])}})", + box3 = "PushBox3(l, [2][3]lua.LNumber{{lua.LNumber(VAL[0][0]), lua.LNumber(VAL[0][1]), lua.LNumber(VAL[0][2])}, {lua.LNumber(VAL[1][0]), lua.LNumber(VAL[1][1]), lua.LNumber(VAL[1][2])}})", } local function fields_tolua(fields, indent) local impl = "" for name, type in spairs(fields) do - if name:sub(1, 1) ~= "{" then + local c = name:sub(1, 1) + if c ~= "{" and c ~= "%" then local camel = "val." .. camel_case(name) local idt = indent local condition = fields["{" .. name .. "}"] + local typeparam = fields["%" .. name .. "%"] if condition then impl = impl .. indent .. "if " .. condition .. " {\n" @@ -58,7 +59,9 @@ local function fields_tolua(fields, indent) if tolua[type] then impl = impl .. tolua[type]:gsub("VAL", camel) else - impl = impl .. "push" .. camel_case(type) .. "(l, " .. camel .. ")" + impl = impl .. "Push" .. camel_case(type) + .. (typeparam and "[" .. typeparam .. "]" or "") + .. "(l, " .. camel .. ")" end impl = impl .. ")\n" @@ -74,7 +77,7 @@ end for name, fields in spairs(parse_spec("client/struct", true)) do local camel = camel_case(name) funcs = funcs - .. "func push" .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\ttbl := l.NewTable()\n" + .. "func Push" .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\ttbl := l.NewTable()\n" .. fields_tolua(fields, "\t") .. "\treturn tbl\n}\n\n" end diff --git a/convert/push_static.go b/convert/push_static.go index 4eb7cb0..75001a7 100644 --- a/convert/push_static.go +++ b/convert/push_static.go @@ -8,14 +8,14 @@ import ( //go:generate ./push_mkauto.lua -func vec2(l *lua.LState, val [2]lua.LNumber) { +func CreateVec2(l *lua.LState, val [2]lua.LNumber) { l.Push(l.GetGlobal("vec2")) l.Push(val[0]) l.Push(val[1]) l.Call(2, 1) } -func vec3(l *lua.LState, val [3]lua.LNumber) { +func CreateVec3(l *lua.LState, val [3]lua.LNumber) { l.Push(l.GetGlobal("vec3")) l.Push(val[0]) l.Push(val[1]) @@ -29,17 +29,17 @@ func popValue(l *lua.LState) lua.LValue { return ret } -func pushVec2(l *lua.LState, val [2]lua.LNumber) lua.LValue { - vec2(l, val) +func PushVec2(l *lua.LState, val [2]lua.LNumber) lua.LValue { + CreateVec2(l, val) return popValue(l) } -func pushVec3(l *lua.LState, val [3]lua.LNumber) lua.LValue { - vec3(l, val) +func PushVec3(l *lua.LState, val [3]lua.LNumber) lua.LValue { + CreateVec3(l, val) return popValue(l) } -func pushBox1(l *lua.LState, val [2]lua.LNumber) lua.LValue { +func PushBox1(l *lua.LState, val [2]lua.LNumber) lua.LValue { l.Push(l.GetGlobal("box")) l.Push(val[0]) l.Push(val[1]) @@ -47,23 +47,23 @@ func pushBox1(l *lua.LState, val [2]lua.LNumber) lua.LValue { return popValue(l) } -func pushBox2(l *lua.LState, val [2][2]lua.LNumber) lua.LValue { +func PushBox2(l *lua.LState, val [2][2]lua.LNumber) lua.LValue { l.Push(l.GetGlobal("box")) - vec2(l, val[0]) - vec2(l, val[1]) + CreateVec2(l, val[0]) + CreateVec2(l, val[1]) l.Call(2, 1) return popValue(l) } -func pushBox3(l *lua.LState, val [2][3]lua.LNumber) lua.LValue { +func PushBox3(l *lua.LState, val [2][3]lua.LNumber) lua.LValue { l.Push(l.GetGlobal("box")) - vec3(l, val[0]) - vec3(l, val[1]) + CreateVec3(l, val[0]) + CreateVec3(l, val[1]) l.Call(2, 1) return popValue(l) } -func pushColor(l *lua.LState, val color.NRGBA) lua.LValue { +func PushColor(l *lua.LState, val color.NRGBA) lua.LValue { tbl := l.NewTable() l.SetField(tbl, "r", lua.LNumber(val.R)) l.SetField(tbl, "g", lua.LNumber(val.G)) @@ -72,7 +72,7 @@ func pushColor(l *lua.LState, val color.NRGBA) lua.LValue { return tbl } -func pushStringSet(l *lua.LState, val []string) lua.LValue { +func PushStringSet(l *lua.LState, val []string) lua.LValue { tbl := l.NewTable() for _, str := range val { l.SetField(tbl, str, lua.LTrue) @@ -80,7 +80,7 @@ func pushStringSet(l *lua.LState, val []string) lua.LValue { return tbl } -func stringList[T ~string](l *lua.LState, val []T) lua.LValue { +func PushStringList[T ~string](l *lua.LState, val []T) lua.LValue { tbl := l.NewTable() for _, s := range val { tbl.Append(lua.LString(s)) @@ -88,10 +88,96 @@ func stringList[T ~string](l *lua.LState, val []T) lua.LValue { return tbl } -func pushStringList(l *lua.LState, val []string) lua.LValue { - return stringList[string](l, val) +func Push4096[T uint8 | mt.Content](l *lua.LState, val [4096]T) lua.LValue { + tbl := l.NewTable() + for i, v := range val { + l.RawSetInt(tbl, i, lua.LNumber(v)) + } + return tbl +} + +func PushFields(l *lua.LState, val []mt.Field) lua.LValue { + tbl := l.NewTable() + for _, pair := range val { + l.SetField(tbl, pair.Name, lua.LString(pair.Value)) + } + return tbl +} + +func PushNodeMetaFields(l *lua.LState, val []mt.NodeMetaField) lua.LValue { + tbl := l.NewTable() + for _, pair := range val { + l.SetField(tbl, pair.Name, lua.LString(pair.Value)) + } + return tbl +} + +func PushInv(l *lua.LState, val mt.Inv) lua.LValue { + linv := l.NewTable() + for _, list := range val { + llist := l.NewTable() + l.SetField(llist, "width", lua.LNumber(list.Width)) + for _, stack := range list.Stacks { + lmeta := l.NewTable() + l.SetField(lmeta, "fields", PushFields(l, stack.Fields())) + if toolcaps, ok := stack.ToolCaps(); ok { + l.SetField(lmeta, "tool_caps", PushToolCaps(l, toolcaps)) + } + + lstack := l.NewTable() + l.SetField(lstack, "name", lua.LString(stack.Name)) + l.SetField(lstack, "count", lua.LNumber(stack.Count)) + l.SetField(lstack, "wear", lua.LNumber(stack.Wear)) + l.SetField(lstack, "meta", lmeta) + + llist.Append(lstack) + } + l.SetField(linv, list.Name, llist) + } + return linv +} + +func PushNodeMetas(l *lua.LState, val map[uint16]*mt.NodeMeta) lua.LValue { + tbl := l.NewTable() + for i, meta := range val { + l.RawSetInt(tbl, int(i), PushNodeMeta(l, *meta)) + } + return tbl +} + +func PushChangedNodeMetas(l *lua.LState, val map[[3]int16]*mt.NodeMeta) lua.LValue { + lmetas := l.NewTable() + for pos, meta := range val { + lmeta := l.NewTable() + l.SetField(lmeta, "pos", PushVec3(l, [3]lua.LNumber{lua.LNumber(pos[0]), lua.LNumber(pos[1]), lua.LNumber(pos[2])})) + l.SetField(lmeta, "meta", PushNodeMeta(l, *meta)) + lmetas.Append(lmeta) + } + return lmetas } -func pushTextureList(l *lua.LState, val []mt.Texture) lua.LValue { - return stringList[mt.Texture](l, val) +func PushGroups(l *lua.LState, val []mt.Group) lua.LValue { + tbl := l.NewTable() + for _, group := range val { + l.SetField(tbl, group.Name, lua.LNumber(group.Rating)) + } + return tbl +} + +func PushGroupCaps(l *lua.LState, val []mt.ToolGroupCap) lua.LValue { + lcaps := l.NewTable() + for _, groupcap := range val { + ltimes := l.NewTable() + for _, digtime := range groupcap.Times { + l.RawSetInt(ltimes, int(digtime.Rating), lua.LNumber(digtime.Time)) + } + + lcap := l.NewTable() + l.SetField(lcap, "uses", lua.LNumber(groupcap.Uses)) + l.SetField(lcap, "max_lvl", lua.LNumber(groupcap.MaxLvl)) + l.SetField(lcap, "times", ltimes) + + l.SetField(lcaps, groupcap.Name, lcap) + } + return lcaps } diff --git a/convert/read_auto.go b/convert/read_auto.go index c5a39be..efb3d62 100644 --- a/convert/read_auto.go +++ b/convert/read_auto.go @@ -4,37 +4,38 @@ package convert import ( "github.com/anon55555/mt" "github.com/yuin/gopher-lua" + "math" ) -func readAOID(l *lua.LState, val lua.LValue, ptr *mt.AOID) { +func ReadAOID(l *lua.LState, val lua.LValue, ptr *mt.AOID) { if val.Type() != lua.LTNumber { panic("invalid value for AOID: must be a number") } - *ptr = mt.AOID(val.(lua.LNumber)) + *ptr = mt.AOID(math.Round(float64(val.(lua.LNumber)))) } -func readCompressionModes(l *lua.LState, val lua.LValue, ptr *mt.CompressionModes) { +func ReadCompressionModes(l *lua.LState, val lua.LValue, ptr *mt.CompressionModes) { if val.Type() != lua.LTNumber { panic("invalid value for CompressionModes: must be a number") } - *ptr = mt.CompressionModes(val.(lua.LNumber)) + *ptr = mt.CompressionModes(math.Round(float64(val.(lua.LNumber)))) } -func readInt16(l *lua.LState, val lua.LValue, ptr *int16) { +func ReadInt16(l *lua.LState, val lua.LValue, ptr *int16) { if val.Type() != lua.LTNumber { panic("invalid value for int16: must be a number") } - *ptr = int16(val.(lua.LNumber)) + *ptr = int16(math.Round(float64(val.(lua.LNumber)))) } -func readInt32(l *lua.LState, val lua.LValue, ptr *int32) { +func ReadInt32(l *lua.LState, val lua.LValue, ptr *int32) { if val.Type() != lua.LTNumber { panic("invalid value for int32: must be a number") } - *ptr = int32(val.(lua.LNumber)) + *ptr = int32(math.Round(float64(val.(lua.LNumber)))) } -func readInteraction(l *lua.LState, val lua.LValue, ptr *mt.Interaction) { +func ReadInteraction(l *lua.LState, val lua.LValue, ptr *mt.Interaction) { if val.Type() != lua.LTString { panic("invalid value for Interaction: must be a string") } @@ -57,7 +58,7 @@ func readInteraction(l *lua.LState, val lua.LValue, ptr *mt.Interaction) { } } -func readKeys(l *lua.LState, val lua.LValue, ptr *mt.Keys) { +func ReadKeys(l *lua.LState, val lua.LValue, ptr *mt.Keys) { if val.Type() != lua.LTTable { panic("invalid value for Keys: must be a table") } @@ -93,20 +94,20 @@ func readKeys(l *lua.LState, val lua.LValue, ptr *mt.Keys) { } } -func readPlayerPos(l *lua.LState, val lua.LValue, ptr *mt.PlayerPos) { +func ReadPlayerPos(l *lua.LState, val lua.LValue, ptr *mt.PlayerPos) { if val.Type() != lua.LTTable { panic("invalid value for PlayerPos: must be a table") } - readUint8(l, l.GetField(val, "fov80"), &ptr.FOV80) - readKeys(l, l.GetField(val, "keys"), &ptr.Keys) - readInt32(l, l.GetField(val, "pitch100"), &ptr.Pitch100) - readVec3Int32(l, l.GetField(val, "pos100"), &ptr.Pos100) - readVec3Int32(l, l.GetField(val, "vel100"), &ptr.Vel100) - readUint8(l, l.GetField(val, "wanted_range"), &ptr.WantedRange) - readInt32(l, l.GetField(val, "yaw100"), &ptr.Yaw100) + ReadUint8(l, l.GetField(val, "fov80"), &ptr.FOV80) + ReadKeys(l, l.GetField(val, "keys"), &ptr.Keys) + ReadInt32(l, l.GetField(val, "pitch100"), &ptr.Pitch100) + ReadVec3Int32(l, l.GetField(val, "pos100"), &ptr.Pos100) + ReadVec3Int32(l, l.GetField(val, "vel100"), &ptr.Vel100) + ReadUint8(l, l.GetField(val, "wanted_range"), &ptr.WantedRange) + ReadInt32(l, l.GetField(val, "yaw100"), &ptr.Yaw100) } -func readSliceSoundID(l *lua.LState, val lua.LValue, ptr *[]mt.SoundID) { +func ReadSliceSoundID(l *lua.LState, val lua.LValue, ptr *[]mt.SoundID) { if val.Type() != lua.LTTable { panic("invalid value for []SoundID: must be a table") } @@ -114,11 +115,11 @@ func readSliceSoundID(l *lua.LState, val lua.LValue, ptr *[]mt.SoundID) { n := tbl.MaxN() *ptr = make([]mt.SoundID, n) for i := range *ptr { - readSoundID(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) + ReadSoundID(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) } } -func readSliceString(l *lua.LState, val lua.LValue, ptr *[]string) { +func ReadSliceString(l *lua.LState, val lua.LValue, ptr *[]string) { if val.Type() != lua.LTTable { panic("invalid value for []string: must be a table") } @@ -126,11 +127,11 @@ func readSliceString(l *lua.LState, val lua.LValue, ptr *[]string) { n := tbl.MaxN() *ptr = make([]string, n) for i := range *ptr { - readString(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) + ReadString(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) } } -func readSliceVec3Int16(l *lua.LState, val lua.LValue, ptr *[][3]int16) { +func ReadSliceVec3Int16(l *lua.LState, val lua.LValue, ptr *[][3]int16) { if val.Type() != lua.LTTable { panic("invalid value for [][3]int16: must be a table") } @@ -138,47 +139,47 @@ func readSliceVec3Int16(l *lua.LState, val lua.LValue, ptr *[][3]int16) { n := tbl.MaxN() *ptr = make([][3]int16, n) for i := range *ptr { - readVec3Int16(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) + ReadVec3Int16(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) } } -func readSoundID(l *lua.LState, val lua.LValue, ptr *mt.SoundID) { +func ReadSoundID(l *lua.LState, val lua.LValue, ptr *mt.SoundID) { if val.Type() != lua.LTNumber { panic("invalid value for SoundID: must be a number") } - *ptr = mt.SoundID(val.(lua.LNumber)) + *ptr = mt.SoundID(math.Round(float64(val.(lua.LNumber)))) } -func readUint16(l *lua.LState, val lua.LValue, ptr *uint16) { +func ReadUint16(l *lua.LState, val lua.LValue, ptr *uint16) { if val.Type() != lua.LTNumber { panic("invalid value for uint16: must be a number") } - *ptr = uint16(val.(lua.LNumber)) + *ptr = uint16(math.Round(float64(val.(lua.LNumber)))) } -func readUint8(l *lua.LState, val lua.LValue, ptr *uint8) { +func ReadUint8(l *lua.LState, val lua.LValue, ptr *uint8) { if val.Type() != lua.LTNumber { panic("invalid value for uint8: must be a number") } - *ptr = uint8(val.(lua.LNumber)) + *ptr = uint8(math.Round(float64(val.(lua.LNumber)))) } -func readVec3Int16(l *lua.LState, val lua.LValue, ptr *[3]int16) { +func ReadVec3Int16(l *lua.LState, val lua.LValue, ptr *[3]int16) { if val.Type() != lua.LTTable { panic("invalid value for [3]int16: must be a table") } - readInt16(l, l.GetField(val, "x"), &(*ptr)[0]) - readInt16(l, l.GetField(val, "y"), &(*ptr)[1]) - readInt16(l, l.GetField(val, "z"), &(*ptr)[2]) + ReadInt16(l, l.GetField(val, "x"), &(*ptr)[0]) + ReadInt16(l, l.GetField(val, "y"), &(*ptr)[1]) + ReadInt16(l, l.GetField(val, "z"), &(*ptr)[2]) } -func readVec3Int32(l *lua.LState, val lua.LValue, ptr *[3]int32) { +func ReadVec3Int32(l *lua.LState, val lua.LValue, ptr *[3]int32) { if val.Type() != lua.LTTable { panic("invalid value for [3]int32: must be a table") } - readInt32(l, l.GetField(val, "x"), &(*ptr)[0]) - readInt32(l, l.GetField(val, "y"), &(*ptr)[1]) - readInt32(l, l.GetField(val, "z"), &(*ptr)[2]) + ReadInt32(l, l.GetField(val, "x"), &(*ptr)[0]) + ReadInt32(l, l.GetField(val, "y"), &(*ptr)[1]) + ReadInt32(l, l.GetField(val, "z"), &(*ptr)[2]) } func ReadCmd(l *lua.LState) mt.Cmd { @@ -187,88 +188,88 @@ func ReadCmd(l *lua.LState) mt.Cmd { case "chat_msg": ptr := &mt.ToSrvChatMsg{} val := l.CheckTable(3) - readString(l, l.GetField(val, "msg"), &ptr.Msg) + ReadString(l, l.GetField(val, "msg"), &ptr.Msg) return ptr case "clt_ready": ptr := &mt.ToSrvCltReady{} val := l.CheckTable(3) - readUint16(l, l.GetField(val, "formspec"), &ptr.Formspec) - readUint8(l, l.GetField(val, "major"), &ptr.Major) - readUint8(l, l.GetField(val, "minor"), &ptr.Minor) - readUint8(l, l.GetField(val, "patch"), &ptr.Patch) - readString(l, l.GetField(val, "version"), &ptr.Version) + ReadUint16(l, l.GetField(val, "formspec"), &ptr.Formspec) + ReadUint8(l, l.GetField(val, "major"), &ptr.Major) + ReadUint8(l, l.GetField(val, "minor"), &ptr.Minor) + ReadUint8(l, l.GetField(val, "patch"), &ptr.Patch) + ReadString(l, l.GetField(val, "version"), &ptr.Version) return ptr case "deleted_blks": ptr := &mt.ToSrvDeletedBlks{} val := l.CheckTable(3) - readSliceVec3Int16(l, l.GetField(val, "blks"), &ptr.Blks) + ReadSliceVec3Int16(l, l.GetField(val, "blks"), &ptr.Blks) return ptr case "fall_dmg": ptr := &mt.ToSrvFallDmg{} val := l.CheckTable(3) - readUint16(l, l.GetField(val, "amount"), &ptr.Amount) + ReadUint16(l, l.GetField(val, "amount"), &ptr.Amount) return ptr case "first_srp": ptr := &mt.ToSrvFirstSRP{} val := l.CheckTable(3) - readBool(l, l.GetField(val, "empty_passwd"), &ptr.EmptyPasswd) - readSliceByte(l, l.GetField(val, "salt"), &ptr.Salt) - readSliceByte(l, l.GetField(val, "verifier"), &ptr.Verifier) + ReadBool(l, l.GetField(val, "empty_passwd"), &ptr.EmptyPasswd) + ReadSliceByte(l, l.GetField(val, "salt"), &ptr.Salt) + ReadSliceByte(l, l.GetField(val, "verifier"), &ptr.Verifier) return ptr case "got_blks": ptr := &mt.ToSrvGotBlks{} val := l.CheckTable(3) - readSliceVec3Int16(l, l.GetField(val, "blks"), &ptr.Blks) + ReadSliceVec3Int16(l, l.GetField(val, "blks"), &ptr.Blks) return ptr case "init": ptr := &mt.ToSrvInit{} val := l.CheckTable(3) - readUint16(l, l.GetField(val, "max_proto_ver"), &ptr.MaxProtoVer) - readUint16(l, l.GetField(val, "min_proto_ver"), &ptr.MinProtoVer) - readString(l, l.GetField(val, "player_name"), &ptr.PlayerName) - readBool(l, l.GetField(val, "send_full_item_meta"), &ptr.SendFullItemMeta) - readUint8(l, l.GetField(val, "serialize_ver"), &ptr.SerializeVer) - readCompressionModes(l, l.GetField(val, "supported_compression"), &ptr.SupportedCompression) + ReadUint16(l, l.GetField(val, "max_proto_ver"), &ptr.MaxProtoVer) + ReadUint16(l, l.GetField(val, "min_proto_ver"), &ptr.MinProtoVer) + ReadString(l, l.GetField(val, "player_name"), &ptr.PlayerName) + ReadBool(l, l.GetField(val, "send_full_item_meta"), &ptr.SendFullItemMeta) + ReadUint8(l, l.GetField(val, "serialize_ver"), &ptr.SerializeVer) + ReadCompressionModes(l, l.GetField(val, "supported_compression"), &ptr.SupportedCompression) return ptr case "init2": ptr := &mt.ToSrvInit2{} val := l.CheckTable(3) - readString(l, l.GetField(val, "lang"), &ptr.Lang) + ReadString(l, l.GetField(val, "lang"), &ptr.Lang) return ptr case "interact": ptr := &mt.ToSrvInteract{} val := l.CheckTable(3) - readInteraction(l, l.GetField(val, "action"), &ptr.Action) - readUint16(l, l.GetField(val, "item_slot"), &ptr.ItemSlot) - readPointedThing(l, l.GetField(val, "pointed"), &ptr.Pointed) - readPlayerPos(l, l.GetField(val, "pos"), &ptr.Pos) + ReadInteraction(l, l.GetField(val, "action"), &ptr.Action) + ReadUint16(l, l.GetField(val, "item_slot"), &ptr.ItemSlot) + ReadPointedThing(l, l.GetField(val, "pointed"), &ptr.Pointed) + ReadPlayerPos(l, l.GetField(val, "pos"), &ptr.Pos) return ptr case "inv_action": ptr := &mt.ToSrvInvAction{} val := l.CheckTable(3) - readString(l, l.GetField(val, "action"), &ptr.Action) + ReadString(l, l.GetField(val, "action"), &ptr.Action) return ptr case "inv_fields": ptr := &mt.ToSrvInvFields{} val := l.CheckTable(3) - readSliceField(l, l.GetField(val, "fields"), &ptr.Fields) - readString(l, l.GetField(val, "formname"), &ptr.Formname) + ReadSliceField(l, l.GetField(val, "fields"), &ptr.Fields) + ReadString(l, l.GetField(val, "formname"), &ptr.Formname) return ptr case "join_mod_chan": ptr := &mt.ToSrvJoinModChan{} val := l.CheckTable(3) - readString(l, l.GetField(val, "channel"), &ptr.Channel) + ReadString(l, l.GetField(val, "channel"), &ptr.Channel) return ptr case "leave_mod_chan": ptr := &mt.ToSrvLeaveModChan{} val := l.CheckTable(3) - readString(l, l.GetField(val, "channel"), &ptr.Channel) + ReadString(l, l.GetField(val, "channel"), &ptr.Channel) return ptr case "msg_mod_chan": ptr := &mt.ToSrvMsgModChan{} val := l.CheckTable(3) - readString(l, l.GetField(val, "channel"), &ptr.Channel) - readString(l, l.GetField(val, "msg"), &ptr.Msg) + ReadString(l, l.GetField(val, "channel"), &ptr.Channel) + ReadString(l, l.GetField(val, "msg"), &ptr.Msg) return ptr case "nil": ptr := &mt.ToSrvNil{} @@ -276,24 +277,24 @@ func ReadCmd(l *lua.LState) mt.Cmd { case "node_meta_fields": ptr := &mt.ToSrvNodeMetaFields{} val := l.CheckTable(3) - readSliceField(l, l.GetField(val, "fields"), &ptr.Fields) - readString(l, l.GetField(val, "formname"), &ptr.Formname) - readVec3Int16(l, l.GetField(val, "pos"), &ptr.Pos) + ReadSliceField(l, l.GetField(val, "fields"), &ptr.Fields) + ReadString(l, l.GetField(val, "formname"), &ptr.Formname) + ReadVec3Int16(l, l.GetField(val, "pos"), &ptr.Pos) return ptr case "player_pos": ptr := &mt.ToSrvPlayerPos{} val := l.CheckTable(3) - readPlayerPos(l, l.GetField(val, "pos"), &ptr.Pos) + ReadPlayerPos(l, l.GetField(val, "pos"), &ptr.Pos) return ptr case "removed_sounds": ptr := &mt.ToSrvRemovedSounds{} val := l.CheckTable(3) - readSliceSoundID(l, l.GetField(val, "ids"), &ptr.IDs) + ReadSliceSoundID(l, l.GetField(val, "ids"), &ptr.IDs) return ptr case "req_media": ptr := &mt.ToSrvReqMedia{} val := l.CheckTable(3) - readSliceString(l, l.GetField(val, "filenames"), &ptr.Filenames) + ReadSliceString(l, l.GetField(val, "filenames"), &ptr.Filenames) return ptr case "respawn": ptr := &mt.ToSrvRespawn{} @@ -301,18 +302,18 @@ func ReadCmd(l *lua.LState) mt.Cmd { case "select_item": ptr := &mt.ToSrvSelectItem{} val := l.CheckTable(3) - readUint16(l, l.GetField(val, "slot"), &ptr.Slot) + ReadUint16(l, l.GetField(val, "slot"), &ptr.Slot) return ptr case "srp_bytes_a": ptr := &mt.ToSrvSRPBytesA{} val := l.CheckTable(3) - readSliceByte(l, l.GetField(val, "a"), &ptr.A) - readBool(l, l.GetField(val, "no_sha1"), &ptr.NoSHA1) + ReadSliceByte(l, l.GetField(val, "a"), &ptr.A) + ReadBool(l, l.GetField(val, "no_sha1"), &ptr.NoSHA1) return ptr case "srp_bytes_m": ptr := &mt.ToSrvSRPBytesM{} val := l.CheckTable(3) - readSliceByte(l, l.GetField(val, "m"), &ptr.M) + ReadSliceByte(l, l.GetField(val, "m"), &ptr.M) return ptr } diff --git a/convert/read_mkauto.lua b/convert/read_mkauto.lua index f749f99..7ef82dd 100755 --- a/convert/read_mkauto.lua +++ b/convert/read_mkauto.lua @@ -11,7 +11,7 @@ local readers = { PointedThing = true, } -local static_uses = { +local external = { "[3]int16", "AOID" } @@ -40,7 +40,7 @@ local function generate(name) end if not readers[fnname] then - local fun = "func read" .. fnname .. "(l *lua.LState, val lua.LValue, ptr *" .. type .. ") {\n" + 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 " @@ -53,7 +53,7 @@ local function generate(name) n := tbl.MaxN() *ptr = make(]] .. type .. [[, n) for i := range *ptr { - read]] .. childfn .. [[(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) + Read]] .. childfn .. [[(l, l.RawGetInt(tbl, i+1), &(*ptr)[i]) } ]] else @@ -64,14 +64,20 @@ local function generate(name) end fun = fun - .. "\tread" .. childfn + .. "\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 .. "(val.(lua.LNumber))\n" + .. "\t*ptr = " .. type .. "(" + .. (is_float and "" or "math.Round(float64(") + .. "val.(lua.LNumber)" + .. (is_float and "" or "))") + .. ")\n" end fun = fun .. "}\n\n" @@ -82,13 +88,13 @@ local function generate(name) return fnname, type end -for _, use in ipairs(static_uses) do +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" + 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 @@ -135,7 +141,7 @@ 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." + impl = impl .. indent .. "Read" .. generate(type) .. "(l, l.GetField(val, \"" .. name .. "\"), &ptr." .. camel_case(name) .. ")\n" end @@ -183,6 +189,7 @@ package convert import ( "github.com/anon55555/mt" "github.com/yuin/gopher-lua" + "math" ) ]] .. funcs .. [[ diff --git a/convert/read_static.go b/convert/read_static.go index 3e7dc30..3be41e1 100644 --- a/convert/read_static.go +++ b/convert/read_static.go @@ -7,28 +7,28 @@ import ( //go:generate ./read_mkauto.lua -func readBool(l *lua.LState, val lua.LValue, ptr *bool) { +func ReadBool(l *lua.LState, val lua.LValue, ptr *bool) { if val.Type() != lua.LTBool { panic("invalid value for bool: must be a boolean") } *ptr = bool(val.(lua.LBool)) } -func readString(l *lua.LState, val lua.LValue, ptr *string) { +func ReadString(l *lua.LState, val lua.LValue, ptr *string) { if val.Type() != lua.LTString { panic("invalid value for string: must be a string") } *ptr = string(val.(lua.LString)) } -func readSliceByte(l *lua.LState, val lua.LValue, ptr *[]byte) { +func ReadSliceByte(l *lua.LState, val lua.LValue, ptr *[]byte) { if val.Type() != lua.LTString { panic("invalid value for []byte: must be a string") } *ptr = []byte(val.(lua.LString)) } -func readSliceField(l *lua.LState, val lua.LValue, ptr *[]mt.Field) { +func ReadSliceField(l *lua.LState, val lua.LValue, ptr *[]mt.Field) { if val.Type() != lua.LTTable { panic("invalid value for []Field: must be a table") } @@ -40,7 +40,7 @@ func readSliceField(l *lua.LState, val lua.LValue, ptr *[]mt.Field) { }) } -func readPointedThing(l *lua.LState, val lua.LValue, ptr *mt.PointedThing) { +func ReadPointedThing(l *lua.LState, val lua.LValue, ptr *mt.PointedThing) { if val.Type() != lua.LTTable { panic("invalid value for PointedThing: must be a table") } @@ -48,12 +48,12 @@ func readPointedThing(l *lua.LState, val lua.LValue, ptr *mt.PointedThing) { if id != lua.LNil { pt := &mt.PointedAO{} - readAOID(l, id, &(*pt).ID) + ReadAOID(l, id, &(*pt).ID) *ptr = pt } else { pt := &mt.PointedNode{} - readVec3Int16(l, l.GetField(val, "under"), &(*pt).Under) - readVec3Int16(l, l.GetField(val, "above"), &(*pt).Above) + ReadVec3Int16(l, l.GetField(val, "under"), &(*pt).Under) + ReadVec3Int16(l, l.GetField(val, "above"), &(*pt).Above) *ptr = pt } } diff --git a/convert/spec.lua b/convert/spec.lua index 588f4d7..d7ba432 100644 --- a/convert/spec.lua +++ b/convert/spec.lua @@ -40,8 +40,9 @@ local function parse_pair(pair, value_first) if idx then local first, second = pair:sub(1, idx - 1), pair:sub(idx + 1) + local c = first:sub(1, 1) - if value_first and first:sub(1, 1) ~= "{" then + if value_first and c ~= "{" and c ~= "%" then return second, first else return first, second @@ -52,7 +53,7 @@ local function parse_pair(pair, value_first) end function parse_spec(name, value_first) - local f = io.open("../spec/" .. name, "r") + local f = io.open("spec/" .. name, "r") local spec = {} local top diff --git a/convert/spec/casemap b/convert/spec/casemap new file mode 100644 index 0000000..ab4c10a --- /dev/null +++ b/convert/spec/casemap @@ -0,0 +1,28 @@ +id ID +ao AO +hud HUD +hp HP +fov FOV +srp SRP +sha1 SHA1 +ao_rm_add AORmAdd +ao_msgs AOMsgs +src_aoid SrcAOID +ao_collision AOCollision +add_hud AddHUD +rm_hud RmHUD +change_hud ChangeHUD +hud_flags HUDFlags +hud_type HUDType +hud_field HUDField +first_srp FirstSRP +csm_restriction_flags CSMRestrictionFlags +srp_bytes_salt_b SRPBytesSaltB +srp_bytes_a SRPBytesA +srp_bytes_m SRPBytesM +no_csms NoCSMs +join_ok JoinOK +leave_ok LeaveOK +no_sha1 NoSHA1 +fov80 FOV80 +ids IDs diff --git a/convert/spec/client/enum b/convert/spec/client/enum new file mode 100644 index 0000000..cd5f166 --- /dev/null +++ b/convert/spec/client/enum @@ -0,0 +1,70 @@ +kick_reason + wrong_passwd + unexpected_data + srv_is_singleplayer + unsupported_ver + bad_name_chars + bad_name + too_many_clts + empty_passwd + already_connected + srv_err + custom + shutdown + crash +chat_msg_type + postfix Msg + raw + normal + announce + sys +sound_src_type + postfix Src + no + pos + ao +anim_type + postfix Anim + no + vertical_frame + sprite_sheet +hud_type + postfix HUD + img + text + statbar + inv + waypoint + img_waypoint +hud_field + prefix HUD + pos + name + scale + text + number + item + dir + align + offset + world_pos + size + z_index + text_2 +hotbar_param + prefix Hotbar + size + img + sel_img +mod_chan_sig + join_ok + join_fail + leave_ok + leave_fail + not_registered + set_state +player_list_update_type + postfix Players + init + add + remove diff --git a/convert/spec/client/flag b/convert/spec/client/flag new file mode 100644 index 0000000..17a8c7a --- /dev/null +++ b/convert/spec/client/flag @@ -0,0 +1,25 @@ +auth_methods + legacy_passwd + srp + first_srp +csm_restriction_flags + no_csms + no_chat_msgs + no_node_defs + limit_map_range + no_player_list +hud_flags + prefix Show + hotbar + health_bar + crosshair + wielded_item + breath_bar + minimap + radar_minimap +map_blk_flags + prefix Blk + is_underground + day_night_diff + light_expired + not_generated diff --git a/convert/spec/client/pkt b/convert/spec/client/pkt new file mode 100644 index 0000000..0a15002 --- /dev/null +++ b/convert/spec/client/pkt @@ -0,0 +1,276 @@ +hello + number serialize_ver + number compression + number proto_ver + auth_methods auth_methods + string username +accept_auth + vec3 player_pos + number map_seed + number send_interval + auth_methods sudo_auth_methods +accept_sudo_mode +deny_sudo_mode +kick + kick_reason reason + {custom} val.Reason == mt.Custom || val.Reason == mt.Shutdown || val.Reason == mt.Crash + string custom + {reconnect} val.Reason == mt.Shutdown || val.Reason == mt.Crash + boolean reconnect +blk_data + vec3 blkpos + map_blk blk +add_node + vec3 pos + node node + boolean keep_meta +remove_node + vec3 pos +inv + string inv +time_of_day + number time + number speed +csm_restriction_flags + csm_restriction_flags flags + number map_range +add_player_vel + vec3 vel +media_push + fixed_string sha1 + string filename + boolean should_cache + string data +chat_msg + chat_msg_type type + string sender + string text + number timestamp +ao_rm_add + # TODO +ao_msgs + # TODO +hp + number hp +move_player + vec3 pos + number pitch + number yaw +legacy_kick + string reason +fov + number fov + boolean multiplier + number transition_time +death_screen + boolean point_cam + vec3 point_at +media + # TODO +node_defs + # TODO +announce_media + # TODO +item_defs + # TODO +play_sound + number id + string name + number gain + sound_src_type src_type + vec3 pos + number src_aoid + boolean loop + number fade + number pitch + boolean ephemeral +stop_sound + number id +privs + string_set privs +inv_formspec + string formspec +detached_inv + string name + boolean keep + number len + string inv +show_formspec + string formspec + string formname +movement + number default_accel + number air_accel + number fast_accel + number walk_speed + number crouch_speed + number fast_speed + number climb_speed + number jump_speed + number fluidity + number smoothing + number sink + number gravity +spawn_particle + vec3 pos + vec3 vel + vec3 acc + number expiration_time + number size + boolean collide + string texture + boolean vertical + boolean collision_rm + tile_anim anim_params + number glow + boolean ao_collision + number node_param0 + number node_param2 + number node_tile +add_particle_spawner + number amount + number duration + box3 pos + box3 vel + box3 acc + box1 expiration_time + box1 size + boolean collide + string texture + number id + boolean vertical + boolean collision_rm + tile_anim anim_params + number glow + boolean ao_collision + number node_param0 + number node_param2 + number node_tile +add_hud + number id + hud hud +rm_hud + number id +change_hud + number id + hud_field field + {pos} val.Field == mt.HUDPos + {name} val.Field == mt.HUDName + {text} val.Field == mt.HUDText + {number} val.Field == mt.HUDNumber + {item} val.Field == mt.HUDItem + {dir} val.Field == mt.HUDDir + {align} val.Field == mt.HUDAlign + {offset} val.Field == mt.HUDOffset + {world_pos} val.Field == mt.HUDWorldPos + {size} val.Field == mt.HUDSize + {z_index} val.Field == mt.HUDZIndex + {text_2} val.Field == mt.HUDText2 + vec2 pos + string name + string text + number number + number item + number dir + vec2 align + vec2 offset + vec3 world_pos + vec2 size + number z_index + string text_2 +hud_flags + hud_flags flags + hud_flags mask +set_hotbar_param + hotbar_param param + number size + string img +breath + number breath +sky_params + color bg_color + string type + boolean clouds + color sun_fog_tint + color moon_fog_tint + string fog_tint_type + {textures} val.Type == "skybox" + %textures% mt.Texture + string_list textures + {day_sky} val.Type == "regular" + {day_horizon} val.Type == "regular" + {dawn_sky} val.Type == "regular" + {dawn_horizon} val.Type == "regular" + {night_sky} val.Type == "regular" + {night_horizon} val.Type == "regular" + {indoor} val.Type == "regular" + color day_sky + color day_horizon + color dawn_sky + color dawn_horizon + color night_sky + color night_horizon + color indoor +override_day_night_ratio + boolean override + number ratio +local_player_anim + box1 idle + box1 walk + box1 dig + box1 walk_dig + number speed +eye_offset + vec3 first + vec3 third +del_particle_spawner + number id +cloud_params + number density + color diffuse_color + color ambient_color + number height + number thickness + vec2 speed +fade_sound + number id + number step + number gain +update_player_list + player_list_update_type type + %players% string + string_list players +mod_chan_msg + string channel + string sender + string msg +mod_chan_sig + mod_chan_sig signal + string channel +node_metas_changed + changed_node_metas changed +sun_params + boolean visible + string texture + string tone_map + string rise + boolean rising + number size +moon_params + boolean visible + string texture + string tone_map + number size +star_params + boolean visible + number count + color color + number size +srp_bytes_salt_b + string salt + string b +formspec_prepend + string prepend +minimap_modes + # TODO +disco diff --git a/convert/spec/client/struct b/convert/spec/client/struct new file mode 100644 index 0000000..f3bbd10 --- /dev/null +++ b/convert/spec/client/struct @@ -0,0 +1,43 @@ +node + number param0 + number param1 + number param2 +tile_anim + anim_type type + vec2 aspect_ratio + vec2 n_frames + number duration +hud + hud_type type + vec2 pos + string name + vec2 scale + string text + number number + number item + number dir + vec2 align + vec2 offset + vec3 world_pos + vec2 size + number z_index + string text_2 +map_blk + map_blk_flags flags + number lit_from + %param0% mt.Content + 4096 param0 + %param1% uint8 + 4096 param1 + %param2% uint8 + 4096 param2 + node_metas node_metas +node_meta + node_meta_fields fields + inv inv +tool_caps + number attack_cooldown + number max_drop_lvl + group_caps group_caps + groups dmg_groups + number punch_uses diff --git a/convert/spec/server/enum b/convert/spec/server/enum new file mode 100644 index 0000000..6f49e6d --- /dev/null +++ b/convert/spec/server/enum @@ -0,0 +1,7 @@ +interaction + dig + stop_digging + dug + place + use + activate diff --git a/convert/spec/server/flag b/convert/spec/server/flag new file mode 100644 index 0000000..4f8c164 --- /dev/null +++ b/convert/spec/server/flag @@ -0,0 +1,12 @@ +keys + postfix Key + forward + backward + left + right + jump + special + sneak + dig + place + zoom diff --git a/convert/spec/server/pkt b/convert/spec/server/pkt new file mode 100644 index 0000000..5578d55 --- /dev/null +++ b/convert/spec/server/pkt @@ -0,0 +1,63 @@ +nil +init + uint8 serialize_ver + CompressionModes supported_compression + uint16 min_proto_ver + uint16 max_proto_ver + string player_name + bool send_full_item_meta +init2 + string lang +join_mod_chan + string channel +leave_mod_chan + string channel +msg_mod_chan + string channel + string msg +player_pos + PlayerPos pos +got_blks + [][3]int16 blks +deleted_blks + [][3]int16 blks +inv_action + string action +chat_msg + string msg +fall_dmg + uint16 amount +select_item + uint16 slot +respawn +interact + Interaction action + uint16 item_slot + PointedThing pointed + PlayerPos pos +removed_sounds + []SoundID ids +node_meta_fields + [3]int16 pos + string formname + []Field fields +inv_fields + string formname + []Field fields +req_media + []string filenames +clt_ready + uint8 major + uint8 minor + uint8 patch + string version + uint16 formspec +first_srp + []byte salt + []byte verifier + bool empty_passwd +srp_bytes_a + []byte a + bool no_sha1 +srp_bytes_m + []byte m diff --git a/convert/spec/server/struct b/convert/spec/server/struct new file mode 100644 index 0000000..e971dbc --- /dev/null +++ b/convert/spec/server/struct @@ -0,0 +1,8 @@ +player_pos + [3]int32 pos100 + [3]int32 vel100 + int32 pitch100 + int32 yaw100 + Keys keys + uint8 fov80 + uint8 wanted_range diff --git a/doc/api.md b/doc/api.md index 8dda81e..2105a81 100644 --- a/doc/api.md +++ b/doc/api.md @@ -15,6 +15,7 @@ Hydra uses gopher-lua, Lua 5.1 - `escapes`: contains utility functions to deal with minetest escape sequences, see [escapes.md](escapes.md) - `client`: a function to create a client from command line arguments in the form ` `. This is trivial but so commonly used that this function was added to avoid repetition in scripts. +- `base64`: contains the `base64.encode(data)` function to base64 encode a string as well as `base64.decode(data)` to decode ## Standard library additions diff --git a/doc/client.md b/doc/client.md index 9844591..9c1922e 100644 --- a/doc/client.md +++ b/doc/client.md @@ -22,3 +22,4 @@ After being disconnect, a client cannot be reconnected. Enabled components can be accessed by using `self.`. - `self.auth`: Handles authentication. Recommended for the vast majority of scripts. See [auth.md](auth.md). +- `self.map`: Stores MapBlocks received from server. See [map.md](map.md). diff --git a/doc/client_pkts.md b/doc/client_pkts.md index 7f967a0..2594b9d 100644 --- a/doc/client_pkts.md +++ b/doc/client_pkts.md @@ -1,4 +1,4 @@ # Client Packets TODO: automatically generate documentation from spec. -For now, have a look at [spec/client](../spec/client) +For now, have a look at [spec/client](../convert/spec/client) diff --git a/doc/map.md b/doc/map.md new file mode 100644 index 0000000..26fd51a --- /dev/null +++ b/doc/map.md @@ -0,0 +1,13 @@ +# Map Component +Source code: [map.go](../map.go) + +Map handles the `blk_data` and `node_metas_changed` packets. +Map may send `got_blks`, `deleted_blks` packets. + +## Functions + +`self:clear()`: Forget all blocks. + +`self:block(blkpos)`: Return the `map_blk` at `blkpos` as found in the `blk_data` packet (See [client_pkts.md](client_pkts.md)). `nil` if block is not present. + +`self:node(pos)`: Return a node in the form `{ param0 = 126, param1 = 0, param2 = 0, meta = { ... } }`. The meta field is a `node_meta` as found in the `blk_data` packet. `nil` if node is not present. diff --git a/doc/server_pkts.md b/doc/server_pkts.md index 0b34367..ac8741e 100644 --- a/doc/server_pkts.md +++ b/doc/server_pkts.md @@ -1,4 +1,4 @@ # Server Packets TODO: automatically generate documentation from spec. -For now, have a look at [spec/server](../spec/server) +For now, have a look at [spec/server](../convert/spec/server) diff --git a/example/dump-traffic.lua b/example/dump-traffic.lua index b3d89da..5dc83b6 100755 --- a/example/dump-traffic.lua +++ b/example/dump-traffic.lua @@ -1,19 +1,53 @@ #!/usr/bin/env hydra-dragonfire +local escapes = require("escapes") +local base64 = require("base64") local client = require("client")() client:wildcard(true) client:connect() +local function dump(val, indent) + local t = type(val) + local mt = getmetatable(val) + + if t ~= "table" or mt and mt.__tostring then + if t == "string" then + val = val:gsub("\n", "\\n") + end + print(val) + else + print(val._type or "") + + local idt = (indent or "") .. " " + for k, v in pairs(val) do + if k ~= "_type" then + io.write(idt .. k .. " ") + dump(v, idt) + end + end + end +end + while not hydra.canceled() do local pkt, interrupt = client:poll() if pkt then - print(pkt._type) - for k, v in pairs(pkt) do - if k ~= "_type" then - print("", k, v) - end + if pkt._type == "srp_bytes_salt_b" then + pkt.b = base64.encode(pkt.b) + pkt.salt = base64.encode(pkt.salt) + end + + if pkt._type == "chat_msg" then + pkt.text = escapes.strip_all(pkt.text) + end + + if pkt._type == "blk_data" then + pkt.blk.param0 = {} + pkt.blk.param1 = {} + pkt.blk.param2 = {} end + + dump(pkt) elseif not interrupt then print("disconnected") break diff --git a/example/print-node.lua b/example/print-node.lua new file mode 100755 index 0000000..3cf514e --- /dev/null +++ b/example/print-node.lua @@ -0,0 +1,23 @@ +#!/usr/bin/env hydra-dragonfire +local client = require("client")() +client:enable("map") + +client:subscribe("move_player") +client:connect() + +local pos + +while not hydra.canceled() do + local pkt, interrupted = client:poll(1) + + if pkt then + pos = (pkt.pos / hydra.BS + vec3(0, -1, 0)):round() + elseif not interrupted then + break + elseif pos then + local node = client.map:node(pos) + print(pos, node and node.param0) + end +end + +client:close() diff --git a/hydra.go b/hydra.go index c8f1e67..f34ca2b 100644 --- a/hydra.go +++ b/hydra.go @@ -28,11 +28,15 @@ var builtinEscapes string //go:embed builtin/client.lua var builtinClient string +//go:embed builtin/base64.lua +var builtinBase64 string + var builtinFiles = []string{ builtinLuaX, builtinVector, builtinEscapes, builtinClient, + builtinBase64, } var hydraFuncs = map[string]lua.LGFunction{ @@ -107,6 +111,7 @@ func main() { l.SetField(l.NewTypeMetatable("hydra.auth"), "__index", l.SetFuncs(l.NewTable(), authFuncs)) l.SetField(l.NewTypeMetatable("hydra.client"), "__index", l.NewFunction(l_client_index)) + l.SetField(l.NewTypeMetatable("hydra.map"), "__index", l.SetFuncs(l.NewTable(), mapFuncs)) for _, str := range builtinFiles { if err := l.DoString(str); err != nil { diff --git a/map.go b/map.go new file mode 100644 index 0000000..08b97ec --- /dev/null +++ b/map.go @@ -0,0 +1,116 @@ +package main + +import ( + "github.com/anon55555/mt" + "github.com/dragonfireclient/hydra-dragonfire/convert" + "github.com/yuin/gopher-lua" + "sync" +) + +type Map struct { + client *Client + mu sync.Mutex + blocks map[[3]int16]*mt.MapBlk + userdata *lua.LUserData +} + +var mapFuncs = map[string]lua.LGFunction{ + "clear": l_map_clear, + "block": l_map_block, + "node": l_map_node, +} + +func getMap(l *lua.LState) *Map { + return l.CheckUserData(1).Value.(*Map) +} + +func (mtmap *Map) create(client *Client, l *lua.LState) { + mtmap.client = client + mtmap.blocks = map[[3]int16]*mt.MapBlk{} + mtmap.userdata = l.NewUserData() + mtmap.userdata.Value = mtmap + l.SetMetatable(mtmap.userdata, l.GetTypeMetatable("hydra.map")) +} + +func (mtmap *Map) push() lua.LValue { + return mtmap.userdata +} + +func (mtmap *Map) connect() { +} + +func (mtmap *Map) process(pkt *mt.Pkt) { + switch cmd := pkt.Cmd.(type) { + case *mt.ToCltBlkData: + mtmap.mu.Lock() + mtmap.blocks[cmd.Blkpos] = &cmd.Blk + mtmap.client.conn.SendCmd(&mt.ToSrvGotBlks{Blks: [][3]int16{cmd.Blkpos}}) + mtmap.mu.Unlock() + } +} + +func l_map_clear(l *lua.LState) int { + mtmap := getMap(l) + + mtmap.mu.Lock() + defer mtmap.mu.Unlock() + + var cmd mt.ToSrvDeletedBlks + for pos := range mtmap.blocks { + cmd.Blks = append(cmd.Blks, pos) + } + + mtmap.blocks = map[[3]int16]*mt.MapBlk{} + + mtmap.client.conn.SendCmd(&cmd) + + return 0 +} + +func l_map_block(l *lua.LState) int { + mtmap := getMap(l) + var blkpos [3]int16 + convert.ReadVec3Int16(l, l.Get(2), &blkpos) + + mtmap.mu.Lock() + defer mtmap.mu.Unlock() + + block, ok := mtmap.blocks[blkpos] + if ok { + l.Push(convert.PushMapBlk(l, *block)) + } else { + l.Push(lua.LNil) + } + + return 1 +} + +func l_map_node(l *lua.LState) int { + mtmap := getMap(l) + + var pos [3]int16 + convert.ReadVec3Int16(l, l.Get(2), &pos) + blkpos, i := mt.Pos2Blkpos(pos) + + mtmap.mu.Lock() + defer mtmap.mu.Unlock() + + block, block_exists := mtmap.blocks[blkpos] + if block_exists { + meta, meta_exists := block.NodeMetas[i] + if !meta_exists { + meta = &mt.NodeMeta{} + } + + lnode := l.NewTable() + l.SetField(lnode, "param0", lua.LNumber(block.Param0[i])) + l.SetField(lnode, "param1", lua.LNumber(block.Param1[i])) + l.SetField(lnode, "param2", lua.LNumber(block.Param2[i])) + l.SetField(lnode, "meta", convert.PushNodeMeta(l, *meta)) + l.Push(lnode) + } else { + l.Push(lua.LNil) + } + + return 1 +} diff --git a/spec/casemap b/spec/casemap deleted file mode 100644 index ab4c10a..0000000 --- a/spec/casemap +++ /dev/null @@ -1,28 +0,0 @@ -id ID -ao AO -hud HUD -hp HP -fov FOV -srp SRP -sha1 SHA1 -ao_rm_add AORmAdd -ao_msgs AOMsgs -src_aoid SrcAOID -ao_collision AOCollision -add_hud AddHUD -rm_hud RmHUD -change_hud ChangeHUD -hud_flags HUDFlags -hud_type HUDType -hud_field HUDField -first_srp FirstSRP -csm_restriction_flags CSMRestrictionFlags -srp_bytes_salt_b SRPBytesSaltB -srp_bytes_a SRPBytesA -srp_bytes_m SRPBytesM -no_csms NoCSMs -join_ok JoinOK -leave_ok LeaveOK -no_sha1 NoSHA1 -fov80 FOV80 -ids IDs diff --git a/spec/client/enum b/spec/client/enum deleted file mode 100644 index cd5f166..0000000 --- a/spec/client/enum +++ /dev/null @@ -1,70 +0,0 @@ -kick_reason - wrong_passwd - unexpected_data - srv_is_singleplayer - unsupported_ver - bad_name_chars - bad_name - too_many_clts - empty_passwd - already_connected - srv_err - custom - shutdown - crash -chat_msg_type - postfix Msg - raw - normal - announce - sys -sound_src_type - postfix Src - no - pos - ao -anim_type - postfix Anim - no - vertical_frame - sprite_sheet -hud_type - postfix HUD - img - text - statbar - inv - waypoint - img_waypoint -hud_field - prefix HUD - pos - name - scale - text - number - item - dir - align - offset - world_pos - size - z_index - text_2 -hotbar_param - prefix Hotbar - size - img - sel_img -mod_chan_sig - join_ok - join_fail - leave_ok - leave_fail - not_registered - set_state -player_list_update_type - postfix Players - init - add - remove diff --git a/spec/client/flag b/spec/client/flag deleted file mode 100644 index e13f4da..0000000 --- a/spec/client/flag +++ /dev/null @@ -1,19 +0,0 @@ -auth_methods - legacy_passwd - srp - first_srp -csm_restriction_flags - no_csms - no_chat_msgs - no_node_defs - limit_map_range - no_player_list -hud_flags - prefix Show - hotbar - health_bar - crosshair - wielded_item - breath_bar - minimap - radar_minimap diff --git a/spec/client/pkt b/spec/client/pkt deleted file mode 100644 index 2a150e3..0000000 --- a/spec/client/pkt +++ /dev/null @@ -1,274 +0,0 @@ -hello - number serialize_ver - number compression - number proto_ver - auth_methods auth_methods - string username -accept_auth - vec3 player_pos - number map_seed - number send_interval - auth_methods sudo_auth_methods -accept_sudo_mode -deny_sudo_mode -kick - kick_reason reason - {custom} val.Reason == mt.Custom || val.Reason == mt.Shutdown || val.Reason == mt.Crash - string custom - {reconnect} val.Reason == mt.Shutdown || val.Reason == mt.Crash - boolean reconnect -blk_data - vec3 blkpos - # TODO -add_node - vec3 pos - node node - boolean keep_meta -remove_node - vec3 pos -inv - string inv -time_of_day - number time - number speed -csm_restriction_flags - csm_restriction_flags flags - number map_range -add_player_vel - vec3 vel -media_push - fixed_string sha1 - string filename - boolean should_cache - string data -chat_msg - chat_msg_type type - string sender - string text - number timestamp -ao_rm_add - # TODO -ao_msgs - # TODO -hp - number hp -move_player - vec3 pos - number pitch - number yaw -legacy_kick - string reason -fov - number fov - boolean multiplier - number transition_time -death_screen - boolean point_cam - vec3 point_at -media - # TODO -node_defs - # TODO -announce_media - # TODO -item_defs - # TODO -play_sound - number id - string name - number gain - sound_src_type src_type - vec3 pos - number src_aoid - boolean loop - number fade - number pitch - boolean ephemeral -stop_sound - number id -privs - string_set privs -inv_formspec - string formspec -detached_inv - string name - boolean keep - number len - string inv -show_formspec - string formspec - string formname -movement - number default_accel - number air_accel - number fast_accel - number walk_speed - number crouch_speed - number fast_speed - number climb_speed - number jump_speed - number fluidity - number smoothing - number sink - number gravity -spawn_particle - vec3 pos - vec3 vel - vec3 acc - number expiration_time - number size - boolean collide - string texture - boolean vertical - boolean collision_rm - tile_anim anim_params - number glow - boolean ao_collision - number node_param0 - number node_param2 - number node_tile -add_particle_spawner - number amount - number duration - box3 pos - box3 vel - box3 acc - box1 expiration_time - box1 size - boolean collide - string texture - number id - boolean vertical - boolean collision_rm - tile_anim anim_params - number glow - boolean ao_collision - number node_param0 - number node_param2 - number node_tile -add_hud - number id - hud hud -rm_hud - number id -change_hud - number id - hud_field field - {pos} val.Field == mt.HUDPos - {name} val.Field == mt.HUDName - {text} val.Field == mt.HUDText - {number} val.Field == mt.HUDNumber - {item} val.Field == mt.HUDItem - {dir} val.Field == mt.HUDDir - {align} val.Field == mt.HUDAlign - {offset} val.Field == mt.HUDOffset - {world_pos} val.Field == mt.HUDWorldPos - {size} val.Field == mt.HUDSize - {z_index} val.Field == mt.HUDZIndex - {text_2} val.Field == mt.HUDText2 - vec2 pos - string name - string text - number number - number item - number dir - vec2 align - vec2 offset - vec3 world_pos - vec2 size - number z_index - string text_2 -hud_flags - hud_flags flags - hud_flags mask -set_hotbar_param - hotbar_param param - number size - string img -breath - number breath -sky_params - color bg_color - string type - boolean clouds - color sun_fog_tint - color moon_fog_tint - string fog_tint_type - {textures} val.Type == "skybox" - texture_list textures - {day_sky} val.Type == "regular" - {day_horizon} val.Type == "regular" - {dawn_sky} val.Type == "regular" - {dawn_horizon} val.Type == "regular" - {night_sky} val.Type == "regular" - {night_horizon} val.Type == "regular" - {indoor} val.Type == "regular" - color day_sky - color day_horizon - color dawn_sky - color dawn_horizon - color night_sky - color night_horizon - color indoor -override_day_night_ratio - boolean override - number ratio -local_player_anim - box1 idle - box1 walk - box1 dig - box1 walk_dig - number speed -eye_offset - vec3 first - vec3 third -del_particle_spawner - number id -cloud_params - number density - color diffuse_color - color ambient_color - number height - number thickness - vec2 speed -fade_sound - number id - number step - number gain -update_player_list - player_list_update_type type - string_list players -mod_chan_msg - string channel - string sender - string msg -mod_chan_sig - mod_chan_sig signal - string channel -node_metas_changed - # TODO -sun_params - boolean visible - string texture - string tone_map - string rise - boolean rising - number size -moon_params - boolean visible - string texture - string tone_map - number size -star_params - boolean visible - number count - color color - number size -srp_bytes_salt_b - string salt - string b -formspec_prepend - string prepend -minimap_modes - # TODO -disco diff --git a/spec/client/struct b/spec/client/struct deleted file mode 100644 index d18189c..0000000 --- a/spec/client/struct +++ /dev/null @@ -1,24 +0,0 @@ -node - number param0 - number param1 - number param2 -tile_anim - anim_type type - vec2 aspect_ratio - vec2 n_frames - number duration -hud - hud_type type - vec2 pos - string name - vec2 scale - string text - number number - number item - number dir - vec2 align - vec2 offset - vec3 world_pos - vec2 size - number z_index - string text_2 diff --git a/spec/server/enum b/spec/server/enum deleted file mode 100644 index 6f49e6d..0000000 --- a/spec/server/enum +++ /dev/null @@ -1,7 +0,0 @@ -interaction - dig - stop_digging - dug - place - use - activate diff --git a/spec/server/flag b/spec/server/flag deleted file mode 100644 index 4f8c164..0000000 --- a/spec/server/flag +++ /dev/null @@ -1,12 +0,0 @@ -keys - postfix Key - forward - backward - left - right - jump - special - sneak - dig - place - zoom diff --git a/spec/server/pkt b/spec/server/pkt deleted file mode 100644 index 5578d55..0000000 --- a/spec/server/pkt +++ /dev/null @@ -1,63 +0,0 @@ -nil -init - uint8 serialize_ver - CompressionModes supported_compression - uint16 min_proto_ver - uint16 max_proto_ver - string player_name - bool send_full_item_meta -init2 - string lang -join_mod_chan - string channel -leave_mod_chan - string channel -msg_mod_chan - string channel - string msg -player_pos - PlayerPos pos -got_blks - [][3]int16 blks -deleted_blks - [][3]int16 blks -inv_action - string action -chat_msg - string msg -fall_dmg - uint16 amount -select_item - uint16 slot -respawn -interact - Interaction action - uint16 item_slot - PointedThing pointed - PlayerPos pos -removed_sounds - []SoundID ids -node_meta_fields - [3]int16 pos - string formname - []Field fields -inv_fields - string formname - []Field fields -req_media - []string filenames -clt_ready - uint8 major - uint8 minor - uint8 patch - string version - uint16 formspec -first_srp - []byte salt - []byte verifier - bool empty_passwd -srp_bytes_a - []byte a - bool no_sha1 -srp_bytes_m - []byte m diff --git a/spec/server/struct b/spec/server/struct deleted file mode 100644 index e971dbc..0000000 --- a/spec/server/struct +++ /dev/null @@ -1,8 +0,0 @@ -player_pos - [3]int32 pos100 - [3]int32 vel100 - int32 pitch100 - int32 yaw100 - Keys keys - uint8 fov80 - uint8 wanted_range -- cgit v1.2.3