aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2022-05-31 14:24:19 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2022-05-31 14:24:19 +0200
commitfae336d1a2d613fd00640ed6ccbb9eb386086c82 (patch)
tree48f0fe2cf3a3d86d2d0e192f1b38da55bc18d2f7
parent76071affa0f33bef03e323aa0552c750c56a2cab (diff)
downloadhydra-dragonfire-fae336d1a2d613fd00640ed6ccbb9eb386086c82.tar.xz
Add map component
-rw-r--r--README.md2
-rw-r--r--builtin/base64.lua43
-rw-r--r--builtin/escapes.lua2
-rw-r--r--builtin/vector.lua10
-rw-r--r--client.go2
-rw-r--r--convert/push_auto.go270
-rwxr-xr-xconvert/push_mkauto.lua27
-rw-r--r--convert/push_static.go126
-rw-r--r--convert/read_auto.go157
-rwxr-xr-xconvert/read_mkauto.lua23
-rw-r--r--convert/read_static.go16
-rw-r--r--convert/spec.lua5
-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/struct43
-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.md1
-rw-r--r--doc/client.md1
-rw-r--r--doc/client_pkts.md2
-rw-r--r--doc/map.md13
-rw-r--r--doc/server_pkts.md2
-rwxr-xr-xexample/dump-traffic.lua44
-rwxr-xr-xexample/print-node.lua23
-rw-r--r--hydra.go5
-rw-r--r--map.go116
-rw-r--r--spec/client/struct24
31 files changed, 675 insertions, 296 deletions
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 <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)
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/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
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 `<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()
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/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