diff options
author | Elias Fleckenstein <eliasfleckenstein@web.de> | 2022-05-31 14:24:19 +0200 |
---|---|---|
committer | Elias Fleckenstein <eliasfleckenstein@web.de> | 2022-05-31 14:24:19 +0200 |
commit | fae336d1a2d613fd00640ed6ccbb9eb386086c82 (patch) | |
tree | 48f0fe2cf3a3d86d2d0e192f1b38da55bc18d2f7 | |
parent | 76071affa0f33bef03e323aa0552c750c56a2cab (diff) | |
download | hydra-dragonfire-fae336d1a2d613fd00640ed6ccbb9eb386086c82.tar.xz |
Add map component
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | builtin/base64.lua | 43 | ||||
-rw-r--r-- | builtin/escapes.lua | 2 | ||||
-rw-r--r-- | builtin/vector.lua | 10 | ||||
-rw-r--r-- | client.go | 2 | ||||
-rw-r--r-- | convert/push_auto.go | 270 | ||||
-rwxr-xr-x | convert/push_mkauto.lua | 27 | ||||
-rw-r--r-- | convert/push_static.go | 126 | ||||
-rw-r--r-- | convert/read_auto.go | 157 | ||||
-rwxr-xr-x | convert/read_mkauto.lua | 23 | ||||
-rw-r--r-- | convert/read_static.go | 16 | ||||
-rw-r--r-- | convert/spec.lua | 5 | ||||
-rw-r--r-- | convert/spec/casemap (renamed from spec/casemap) | 0 | ||||
-rw-r--r-- | convert/spec/client/enum (renamed from spec/client/enum) | 0 | ||||
-rw-r--r-- | convert/spec/client/flag (renamed from spec/client/flag) | 6 | ||||
-rw-r--r-- | convert/spec/client/pkt (renamed from spec/client/pkt) | 8 | ||||
-rw-r--r-- | convert/spec/client/struct | 43 | ||||
-rw-r--r-- | convert/spec/server/enum (renamed from spec/server/enum) | 0 | ||||
-rw-r--r-- | convert/spec/server/flag (renamed from spec/server/flag) | 0 | ||||
-rw-r--r-- | convert/spec/server/pkt (renamed from spec/server/pkt) | 0 | ||||
-rw-r--r-- | convert/spec/server/struct (renamed from spec/server/struct) | 0 | ||||
-rw-r--r-- | doc/api.md | 1 | ||||
-rw-r--r-- | doc/client.md | 1 | ||||
-rw-r--r-- | doc/client_pkts.md | 2 | ||||
-rw-r--r-- | doc/map.md | 13 | ||||
-rw-r--r-- | doc/server_pkts.md | 2 | ||||
-rwxr-xr-x | example/dump-traffic.lua | 44 | ||||
-rwxr-xr-x | example/print-node.lua | 23 | ||||
-rw-r--r-- | hydra.go | 5 | ||||
-rw-r--r-- | map.go | 116 | ||||
-rw-r--r-- | spec/client/struct | 24 |
31 files changed, 675 insertions, 296 deletions
@@ -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 <alexthkloss@web.de> +-- 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) @@ -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/spec/casemap b/convert/spec/casemap index ab4c10a..ab4c10a 100644 --- a/spec/casemap +++ b/convert/spec/casemap diff --git a/spec/client/enum b/convert/spec/client/enum index cd5f166..cd5f166 100644 --- a/spec/client/enum +++ b/convert/spec/client/enum diff --git a/spec/client/flag b/convert/spec/client/flag index e13f4da..17a8c7a 100644 --- a/spec/client/flag +++ b/convert/spec/client/flag @@ -17,3 +17,9 @@ hud_flags breath_bar minimap radar_minimap +map_blk_flags + prefix Blk + is_underground + day_night_diff + light_expired + not_generated diff --git a/spec/client/pkt b/convert/spec/client/pkt index 2a150e3..0a15002 100644 --- a/spec/client/pkt +++ b/convert/spec/client/pkt @@ -19,7 +19,7 @@ kick boolean reconnect blk_data vec3 blkpos - # TODO + map_blk blk add_node vec3 pos node node @@ -195,7 +195,8 @@ sky_params color moon_fog_tint string fog_tint_type {textures} val.Type == "skybox" - texture_list textures + %textures% mt.Texture + string_list textures {day_sky} val.Type == "regular" {day_horizon} val.Type == "regular" {dawn_sky} val.Type == "regular" @@ -237,6 +238,7 @@ fade_sound number gain update_player_list player_list_update_type type + %players% string string_list players mod_chan_msg string channel @@ -246,7 +248,7 @@ mod_chan_sig mod_chan_sig signal string channel node_metas_changed - # TODO + changed_node_metas changed sun_params boolean visible string texture 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/spec/server/enum b/convert/spec/server/enum index 6f49e6d..6f49e6d 100644 --- a/spec/server/enum +++ b/convert/spec/server/enum diff --git a/spec/server/flag b/convert/spec/server/flag index 4f8c164..4f8c164 100644 --- a/spec/server/flag +++ b/convert/spec/server/flag diff --git a/spec/server/pkt b/convert/spec/server/pkt index 5578d55..5578d55 100644 --- a/spec/server/pkt +++ b/convert/spec/server/pkt diff --git a/spec/server/struct b/convert/spec/server/struct index e971dbc..e971dbc 100644 --- a/spec/server/struct +++ b/convert/spec/server/struct @@ -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 `<server> <username> <password>`. 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.<component name>`. - `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() @@ -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 { @@ -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/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 |