From: Elias Fleckenstein Date: Sat, 28 May 2022 21:16:55 +0000 (+0200) Subject: Migrate to gopher-lua X-Git-Tag: v0.1.0~13 X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=f0318bd020abe57c0cf365b0479b5d14b95ff07a;p=hydra-dragonfire.git Migrate to gopher-lua --- diff --git a/auth.go b/auth.go index bc8d24e..879ffce 100644 --- a/auth.go +++ b/auth.go @@ -2,8 +2,9 @@ package main import ( "github.com/HimbeerserverDE/srp" - "github.com/Shopify/go-lua" "github.com/anon55555/mt" + "github.com/dragonfireclient/hydra/tolua" + "github.com/yuin/gopher-lua" "strings" "time" ) @@ -23,47 +24,50 @@ type Auth struct { username string password string language string + version string state authState err string srpBytesA, bytesA []byte + userdata *lua.LUserData } -func getAuth(l *lua.State) *Auth { - return lua.CheckUserData(l, 1, "hydra.auth").(*Auth) +var authFuncs = map[string]lua.LGFunction{ + "username": l_auth_username, + "password": l_auth_password, + "language": l_auth_language, + "version": l_auth_version, + "state": l_auth_state, } -func (auth *Auth) create(client *Client) { +func getAuth(l *lua.LState) *Auth { + return l.CheckUserData(1).Value.(*Auth) +} + +func (auth *Auth) create(client *Client, l *lua.LState) { + if client.state != csNew { + panic("can't add auth component after connect") + } + auth.client = client auth.language = "en_US" + auth.version = "hydra-dragonfire" auth.state = asInit + auth.userdata = l.NewUserData() + auth.userdata.Value = auth + l.SetMetatable(auth.userdata, l.GetTypeMetatable("hydra.auth")) } -func (auth *Auth) push(l *lua.State) { - l.PushUserData(auth) - - if lua.NewMetaTable(l, "hydra.auth") { - lua.NewLibrary(l, []lua.RegistryFunction{ - {Name: "username", Function: l_auth_username}, - {Name: "password", Function: l_auth_password}, - {Name: "language", Function: l_auth_language}, - {Name: "state", Function: l_auth_state}, - }) - l.SetField(-2, "__index") - } - l.SetMetaTable(-2) +func (auth *Auth) tolua() lua.LValue { + return auth.userdata } -func (auth *Auth) canConnect() (bool, string) { +func (auth *Auth) connect() { if auth.username == "" { - return false, "missing username" + panic("missing username") } - return true, "" -} - -func (auth *Auth) connect() { go func() { - for auth.state == asInit && auth.client.state == csConnected { + for auth.client.state == csConnected && auth.state == asInit { auth.client.conn.SendCmd(&mt.ToSrvInit{ SerializeVer: 28, MinProtoVer: 39, @@ -75,10 +79,10 @@ func (auth *Auth) connect() { }() } -func (auth *Auth) setError(err string) { - auth.state = asError +func (auth *Auth) fail(err string) { auth.err = err - auth.client.conn.Close() + auth.state = asError + auth.client.disconnect() } func (auth *Auth) checkState(state authState, pkt *mt.Pkt) bool { @@ -86,12 +90,12 @@ func (auth *Auth) checkState(state authState, pkt *mt.Pkt) bool { return true } - auth.setError("received " + pktToString(pkt) + " in invalid state") + auth.fail("received " + string(tolua.PktType(pkt)) + " in invalid state") return false } -func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { - if pkt == nil { +func (auth *Auth) process(pkt *mt.Pkt) { + if auth.state == asError { return } @@ -102,14 +106,14 @@ func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { } if cmd.SerializeVer != 28 { - auth.setError("unsupported serialize_ver") + auth.fail("unsupported serialize version") return } if cmd.AuthMethods == mt.FirstSRP { salt, verifier, err := srp.NewClient([]byte(strings.ToLower(auth.username)), []byte(auth.password)) if err != nil { - auth.setError(err.Error()) + auth.fail(err.Error()) return } @@ -123,7 +127,7 @@ func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { var err error auth.srpBytesA, auth.bytesA, err = srp.InitiateHandshake() if err != nil { - auth.setError(err.Error()) + auth.fail(err.Error()) return } @@ -133,8 +137,8 @@ func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { }) auth.state = asRequested } else { - auth.setError("invalid auth methods") - return + auth.fail("invalid auth methods") + return } case *mt.ToCltSRPBytesSaltB: @@ -144,7 +148,7 @@ func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { srpBytesK, err := srp.CompleteHandshake(auth.srpBytesA, auth.bytesA, []byte(strings.ToLower(auth.username)), []byte(auth.password), cmd.Salt, cmd.B) if err != nil { - auth.setError(err.Error()) + auth.fail(err.Error()) return } @@ -153,7 +157,7 @@ func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { auth.bytesA = []byte{} if M == nil { - auth.setError("srp safety check fail") + auth.fail("srp safety check fail") return } @@ -180,72 +184,60 @@ func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) { Patch: 0, Reserved: 0, Formspec: 4, - Version: "hydra-dragonfire", + Version: auth.version, }) auth.state = asActive } } -func l_auth_username(l *lua.State) int { - auth := getAuth(l) - - if l.IsString(2) { - if auth.client.state > csNew { - panic("can't change username after connecting") +func (auth *Auth) accessProperty(l *lua.LState, key string, ptr *string) int { + if str, ok := l.Get(2).(lua.LString); ok { + if auth.client.state != csNew { + panic("can't change " + key + " after connecting") } - auth.username = lua.CheckString(l, 2) + *ptr = string(str) return 0 } else { - l.PushString(auth.username) + l.Push(lua.LString(*ptr)) return 1 } } -func l_auth_password(l *lua.State) int { +func l_auth_username(l *lua.LState) int { auth := getAuth(l) + return auth.accessProperty(l, "username", &auth.username) +} - if l.IsString(2) { - if auth.client.state > csNew { - panic("can't change password after connecting") - } - auth.password = lua.CheckString(l, 2) - return 0 - } else { - l.PushString(auth.password) - return 1 - } +func l_auth_password(l *lua.LState) int { + auth := getAuth(l) + return auth.accessProperty(l, "password", &auth.password) } -func l_auth_language(l *lua.State) int { +func l_auth_language(l *lua.LState) int { auth := getAuth(l) + return auth.accessProperty(l, "language", &auth.language) +} - if l.IsString(2) { - if auth.client.state > csNew { - panic("can't change language after connecting") - } - auth.language = lua.CheckString(l, 2) - return 0 - } else { - l.PushString(auth.language) - return 1 - } +func l_auth_version(l *lua.LState) int { + auth := getAuth(l) + return auth.accessProperty(l, "version", &auth.version) } -func l_auth_state(l *lua.State) int { +func l_auth_state(l *lua.LState) int { auth := getAuth(l) switch auth.state { case asInit: - l.PushString("init") + l.Push(lua.LString("init")) case asRequested: - l.PushString("requested") + l.Push(lua.LString("requested")) case asVerified: - l.PushString("verified") + l.Push(lua.LString("verified")) case asActive: - l.PushString("active") + l.Push(lua.LString("active")) case asError: - l.PushString("error") - l.PushString(auth.err) + l.Push(lua.LString("error")) + l.Push(lua.LString(auth.err)) return 2 } diff --git a/builtin/vector.lua b/builtin/vector.lua index 2fd926a..95e1ebd 100644 --- a/builtin/vector.lua +++ b/builtin/vector.lua @@ -1,7 +1,7 @@ --[[ builtin/vector.lua ]]-- local function wrap(op, body_wrapper, ...) - return load("return function(a, b) " .. body_wrapper(op, ...) .. "end")() + return loadstring("return function(a, b) " .. body_wrapper(op, ...) .. "end")() end local function arith_mt(...) diff --git a/callbacks.go b/callbacks.go deleted file mode 100644 index e16aec7..0000000 --- a/callbacks.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "github.com/Shopify/go-lua" - "github.com/anon55555/mt" -) - -type Callbacks struct { - wildcard bool - subscribed map[string]struct{} -} - -func getCallbacks(l *lua.State) *Callbacks { - return lua.CheckUserData(l, 1, "hydra.callbacks").(*Callbacks) -} - -func (handler *Callbacks) create(client *Client) { - handler.subscribed = map[string]struct{}{} -} - -func (handler *Callbacks) push(l *lua.State) { - l.PushUserData(handler) - - if lua.NewMetaTable(l, "hydra.callbacks") { - lua.NewLibrary(l, []lua.RegistryFunction{ - {Name: "wildcard", Function: l_callbacks_wildcard}, - {Name: "subscribe", Function: l_callbacks_subscribe}, - {Name: "unsubscribe", Function: l_callbacks_unsubscribe}, - }) - l.SetField(-2, "__index") - } - l.SetMetaTable(-2) -} - -func (handler *Callbacks) canConnect() (bool, string) { - return true, "" -} - -func (handler *Callbacks) connect() { -} - -func (handler *Callbacks) handle(pkt *mt.Pkt, l *lua.State, idx int) { - if !handler.wildcard && pkt != nil { - if _, exists := handler.subscribed[pktToString(pkt)]; !exists { - return - } - } - - if !l.IsFunction(2) { - return - } - - l.PushValue(2) // callback - l.RawGetInt(1, idx) // arg 1: client - pktToLua(l, pkt) // arg 2: pkt - l.Call(2, 0) -} - -func l_callbacks_wildcard(l *lua.State) int { - handler := getCallbacks(l) - handler.wildcard = l.ToBoolean(2) - return 0 -} - -func l_callbacks_subscribe(l *lua.State) int { - handler := getCallbacks(l) - - n := l.Top() - for i := 2; i <= n; i++ { - handler.subscribed[lua.CheckString(l, i)] = struct{}{} - } - - return 0 -} - -func l_callbacks_unsubscribe(l *lua.State) int { - handler := getCallbacks(l) - - n := l.Top() - for i := 2; i <= n; i++ { - delete(handler.subscribed, lua.CheckString(l, i)) - } - - return 0 -} diff --git a/client.go b/client.go index a57e032..a518c95 100644 --- a/client.go +++ b/client.go @@ -2,9 +2,11 @@ package main import ( "errors" - "github.com/Shopify/go-lua" "github.com/anon55555/mt" + "github.com/dragonfireclient/hydra/tolua" + "github.com/yuin/gopher-lua" "net" + "sync" ) type clientState uint8 @@ -15,141 +17,160 @@ const ( csDisconnected ) -type Handler interface { - create(client *Client) - push(l *lua.State) - canConnect() (bool, string) +type Component interface { + create(client *Client, l *lua.LState) + tolua() lua.LValue connect() - handle(pkt *mt.Pkt, l *lua.State, idx int) + process(pkt *mt.Pkt) } type Client struct { - address string - state clientState - handlers map[string]Handler - conn mt.Peer - queue chan *mt.Pkt + mu sync.Mutex + address string + state clientState + conn mt.Peer + queue chan *mt.Pkt + wildcard bool + subscribed map[string]struct{} + components map[string]Component + userdata *lua.LUserData } -func getClient(l *lua.State) *Client { - return lua.CheckUserData(l, 1, "hydra.client").(*Client) +var clientFuncs = map[string]lua.LGFunction{ + "address": l_client_address, + "state": l_client_state, + "connect": l_client_connect, + "poll": l_client_poll, + "disconnect": l_client_disconnect, + "enable": l_client_enable, + "subscribe": l_client_subscribe, + "unsubscribe": l_client_unsubscribe, + "wildcard": l_client_wildcard, } -func l_client(l *lua.State) int { - client := &Client{ - address: lua.CheckString(l, 1), - state: csNew, - handlers: map[string]Handler{}, - } +func getClient(l *lua.LState) *Client { + return l.CheckUserData(1).Value.(*Client) +} + +func getClients(l *lua.LState) []*Client { + tbl := l.CheckTable(1) + n := tbl.MaxN() - l.PushUserData(client) - - if lua.NewMetaTable(l, "hydra.client") { - lua.NewLibrary(l, []lua.RegistryFunction{ - {Name: "address", Function: l_client_address}, - {Name: "state", Function: l_client_state}, - {Name: "handler", Function: l_client_handler}, - {Name: "connect", Function: l_client_connect}, - {Name: "disconnect", Function: l_client_disconnect}, - }) - l.SetField(-2, "__index") + clients := make([]*Client, 0, n) + for i := 1; i <= n; i++ { + clients = append(clients, l.RawGetInt(tbl, i).(*lua.LUserData).Value.(*Client)) } - l.SetMetaTable(-2) - return 1 + return clients } -func l_client_address(l *lua.State) int { - client := getClient(l) - l.PushString(client.address) - return 1 -} +func getStrings(l *lua.LState) []string { + n := l.GetTop() -func l_client_state(l *lua.State) int { - client := getClient(l) - switch client.state { - case csNew: - l.PushString("new") - case csConnected: - l.PushString("connected") - case csDisconnected: - l.PushString("disconnected") + strs := make([]string, 0, n-1) + for i := 2; i <= n; i++ { + strs = append(strs, l.CheckString(i)) } - return 1 + + return strs } -func l_client_handler(l *lua.State) int { - client := getClient(l) - name := lua.CheckString(l, 2) +func (client *Client) disconnect() { + client.mu.Lock() + defer client.mu.Unlock() - handler, exists := client.handlers[name] - if !exists { - switch name { - case "callbacks": - handler = &Callbacks{} + if client.state == csConnected { + client.conn.Close() + } +} - case "auth": - handler = &Auth{} +func l_client(l *lua.LState) int { + client := &Client{} - default: - return 0 - } + client.address = l.CheckString(1) + client.state = csNew + client.wildcard = false + client.subscribed = map[string]struct{}{} + client.components = map[string]Component{} + client.userdata = l.NewUserData() + client.userdata.Value = client + l.SetMetatable(client.userdata, l.GetTypeMetatable("hydra.client")) - client.handlers[name] = handler - handler.create(client) + l.Push(client.userdata) + return 1 +} + +func l_client_index(l *lua.LState) int { + client := getClient(l) + key := l.CheckString(2) + + if fun, exists := clientFuncs[key]; exists { + l.Push(l.NewFunction(fun)) + } else if component, exists := client.components[key]; exists { + l.Push(component.tolua()) + } else { + l.Push(lua.LNil) } - handler.push(l) return 1 } -func l_client_connect(l *lua.State) int { +func l_client_address(l *lua.LState) int { client := getClient(l) + l.Push(lua.LString(client.address)) + return 1 +} - if client.state != csNew { - l.PushBoolean(false) - l.PushString("invalid state") - return 2 +func l_client_state(l *lua.LState) int { + client := getClient(l) + switch client.state { + case csNew: + l.Push(lua.LString("new")) + case csConnected: + l.Push(lua.LString("connected")) + case csDisconnected: + l.Push(lua.LString("disconnected")) } + return 1 +} - for _, handler := range client.handlers { - ok, err := handler.canConnect() +func l_client_connect(l *lua.LState) int { + client := getClient(l) - if !ok { - l.PushBoolean(false) - l.PushString(err) - return 2 - } + if client.state != csNew { + panic("can't reconnect") } addr, err := net.ResolveUDPAddr("udp", client.address) if err != nil { - l.PushBoolean(false) - l.PushString(err.Error()) - return 2 + panic(err) } conn, err := net.DialUDP("udp", nil, addr) if err != nil { - l.PushBoolean(false) - l.PushString(err.Error()) - return 2 + panic(err) } client.state = csConnected client.conn = mt.Connect(conn) client.queue = make(chan *mt.Pkt, 1024) - for _, handler := range client.handlers { - handler.connect() - } - go func() { for { pkt, err := client.conn.Recv() if err == nil { - client.queue <- &pkt + client.mu.Lock() + + for _, component := range client.components { + component.process(&pkt) + } + + if _, exists := client.subscribed[string(tolua.PktType(&pkt))]; exists || client.wildcard { + client.queue <- &pkt + } + + client.mu.Unlock() } else if errors.Is(err, net.ErrClosed) { close(client.queue) return @@ -157,16 +178,96 @@ func l_client_connect(l *lua.State) int { } }() - l.PushBoolean(true) - return 1 + client.mu.Lock() + for _, component := range client.components { + component.connect() + } + client.mu.Unlock() + + return 0 +} + +func l_client_poll(l *lua.LState) int { + client := getClient(l) + _, pkt, timeout := doPoll(l, []*Client{client}) + + l.Push(tolua.Pkt(l, pkt)) + l.Push(lua.LBool(timeout)) + return 2 +} + +func l_client_disconnect(l *lua.LState) int { + client := getClient(l) + client.disconnect() + return 0 +} + +func l_client_enable(l *lua.LState) int { + client := getClient(l) + client.mu.Lock() + defer client.mu.Unlock() + + for _, compname := range getStrings(l) { + if component, exists := client.components[compname]; !exists { + switch compname { + case "auth": + component = &Auth{} + default: + panic("invalid component: " + compname) + } + + client.components[compname] = component + component.create(client, l) + } + } + + return 0 +} + +func l_client_subscribe(l *lua.LState) int { + client := getClient(l) + client.mu.Lock() + defer client.mu.Unlock() + + for _, pkt := range getStrings(l) { + client.subscribed[pkt] = struct{}{} + } + + return 0 } -func l_client_disconnect(l *lua.State) int { +func l_client_unsubscribe(l *lua.LState) int { client := getClient(l) + client.mu.Lock() + defer client.mu.Unlock() + + for _, pkt := range getStrings(l) { + delete(client.subscribed, pkt) + } + + return 0 +} + +func l_client_wildcard(l *lua.LState) int { + client := getClient(l) + client.wildcard = l.ToBool(2) + return 0 +} + +/* + +func l_client_send(l *lua.LState) int { + client := getClient(l) + pkt := fromlua.Pkt(l.CheckTable(2)) + + client.mu.Lock() + defer client.mu.Unlock() if client.state == csConnected { - client.conn.Close() + client.conn.Send(pkt) } return 0 } + +*/ diff --git a/convert.go b/convert.go deleted file mode 100644 index b53b6b9..0000000 --- a/convert.go +++ /dev/null @@ -1,882 +0,0 @@ -// generated by mkconvert.lua, DO NOT EDIT -package main - -import ( - "github.com/Shopify/go-lua" - "github.com/anon55555/mt" -) - -func luaPushAnimType(l *lua.State, val mt.AnimType) { - switch val { - case mt.NoAnim: - l.PushNil() - case mt.VerticalFrameAnim: - l.PushString("vertical_frame") - case mt.SpriteSheetAnim: - l.PushString("sprite_sheet") - } -} - -func luaPushChatMsgType(l *lua.State, val mt.ChatMsgType) { - switch val { - case mt.RawMsg: - l.PushString("raw") - case mt.NormalMsg: - l.PushString("normal") - case mt.AnnounceMsg: - l.PushString("announce") - case mt.SysMsg: - l.PushString("sys") - } -} - -func luaPushHotbarParam(l *lua.State, val mt.HotbarParam) { - switch val { - case mt.HotbarSize: - l.PushString("size") - case mt.HotbarImg: - l.PushString("img") - case mt.HotbarSelImg: - l.PushString("sel_img") - } -} - -func luaPushHUDField(l *lua.State, val mt.HUDField) { - switch val { - case mt.HUDPos: - l.PushString("pos") - case mt.HUDName: - l.PushString("name") - case mt.HUDScale: - l.PushString("scale") - case mt.HUDText: - l.PushString("text") - case mt.HUDNumber: - l.PushString("number") - case mt.HUDItem: - l.PushString("item") - case mt.HUDDir: - l.PushString("dir") - case mt.HUDAlign: - l.PushString("align") - case mt.HUDOffset: - l.PushString("offset") - case mt.HUDWorldPos: - l.PushString("world_pos") - case mt.HUDSize: - l.PushString("size") - case mt.HUDZIndex: - l.PushString("z_index") - case mt.HUDText2: - l.PushString("text_2") - } -} - -func luaPushHUDType(l *lua.State, val mt.HUDType) { - switch val { - case mt.ImgHUD: - l.PushString("img") - case mt.TextHUD: - l.PushString("text") - case mt.StatbarHUD: - l.PushString("statbar") - case mt.InvHUD: - l.PushString("inv") - case mt.WaypointHUD: - l.PushString("waypoint") - case mt.ImgWaypointHUD: - l.PushString("img_waypoint") - } -} - -func luaPushKickReason(l *lua.State, val mt.KickReason) { - switch val { - case mt.WrongPasswd: - l.PushString("wrong_passwd") - case mt.UnexpectedData: - l.PushString("unexpected_data") - case mt.SrvIsSingleplayer: - l.PushString("srv_is_singleplayer") - case mt.UnsupportedVer: - l.PushString("unsupported_ver") - case mt.BadNameChars: - l.PushString("bad_name_chars") - case mt.BadName: - l.PushString("bad_name") - case mt.TooManyClts: - l.PushString("too_many_clts") - case mt.EmptyPasswd: - l.PushString("empty_passwd") - case mt.AlreadyConnected: - l.PushString("already_connected") - case mt.SrvErr: - l.PushString("srv_err") - case mt.Custom: - l.PushString("custom") - case mt.Shutdown: - l.PushString("shutdown") - case mt.Crash: - l.PushString("crash") - } -} - -func luaPushModChanSig(l *lua.State, val mt.ModChanSig) { - switch val { - case mt.JoinOK: - l.PushString("join_ok") - case mt.JoinFail: - l.PushString("join_fail") - case mt.LeaveOK: - l.PushString("leave_ok") - case mt.LeaveFail: - l.PushString("leave_fail") - case mt.NotRegistered: - l.PushString("not_registered") - case mt.SetState: - l.PushString("set_state") - } -} - -func luaPushPlayerListUpdateType(l *lua.State, val mt.PlayerListUpdateType) { - switch val { - case mt.InitPlayers: - l.PushString("init") - case mt.AddPlayers: - l.PushString("add") - case mt.RemovePlayers: - l.PushString("remove") - } -} - -func luaPushSoundSrcType(l *lua.State, val mt.SoundSrcType) { - switch val { - case mt.NoSrc: - l.PushNil() - case mt.PosSrc: - l.PushString("pos") - case mt.AOSrc: - l.PushString("ao") - } -} - -func luaPushAuthMethods(l *lua.State, val mt.AuthMethods) { - l.NewTable() - if val&mt.LegacyPasswd != 0 { - l.PushBoolean(true) - l.SetField(-2, "legacy_passwd") - } - if val&mt.SRP != 0 { - l.PushBoolean(true) - l.SetField(-2, "srp") - } - if val&mt.FirstSRP != 0 { - l.PushBoolean(true) - l.SetField(-2, "first_srp") - } -} - -func luaPushCSMRestrictionFlags(l *lua.State, val mt.CSMRestrictionFlags) { - l.NewTable() - if val&mt.NoCSMs != 0 { - l.PushBoolean(true) - l.SetField(-2, "no_csms") - } - if val&mt.NoChatMsgs != 0 { - l.PushBoolean(true) - l.SetField(-2, "no_chat_msgs") - } - if val&mt.NoNodeDefs != 0 { - l.PushBoolean(true) - l.SetField(-2, "no_node_defs") - } - if val&mt.LimitMapRange != 0 { - l.PushBoolean(true) - l.SetField(-2, "limit_map_range") - } - if val&mt.NoPlayerList != 0 { - l.PushBoolean(true) - l.SetField(-2, "no_player_list") - } -} - -func luaPushHUDFlags(l *lua.State, val mt.HUDFlags) { - l.NewTable() - if val&mt.ShowHotbar != 0 { - l.PushBoolean(true) - l.SetField(-2, "hotbar") - } - if val&mt.ShowHealthBar != 0 { - l.PushBoolean(true) - l.SetField(-2, "health_bar") - } - if val&mt.ShowCrosshair != 0 { - l.PushBoolean(true) - l.SetField(-2, "crosshair") - } - if val&mt.ShowWieldedItem != 0 { - l.PushBoolean(true) - l.SetField(-2, "wielded_item") - } - if val&mt.ShowBreathBar != 0 { - l.PushBoolean(true) - l.SetField(-2, "breath_bar") - } - if val&mt.ShowMinimap != 0 { - l.PushBoolean(true) - l.SetField(-2, "minimap") - } - if val&mt.ShowRadarMinimap != 0 { - l.PushBoolean(true) - l.SetField(-2, "radar_minimap") - } -} - -func luaPushHUD(l *lua.State, val mt.HUD) { - l.NewTable() - luaPushVec2(l, [2]float64{float64(val.Align[0]), float64(val.Align[1])}) - l.SetField(-2, "align") - l.PushInteger(int(val.Dir)) - l.SetField(-2, "dir") - l.PushInteger(int(val.Item)) - l.SetField(-2, "item") - l.PushString(string(val.Name)) - l.SetField(-2, "name") - l.PushInteger(int(val.Number)) - l.SetField(-2, "number") - luaPushVec2(l, [2]float64{float64(val.Offset[0]), float64(val.Offset[1])}) - l.SetField(-2, "offset") - luaPushVec2(l, [2]float64{float64(val.Pos[0]), float64(val.Pos[1])}) - l.SetField(-2, "pos") - luaPushVec2(l, [2]float64{float64(val.Scale[0]), float64(val.Scale[1])}) - l.SetField(-2, "scale") - luaPushVec2(l, [2]float64{float64(val.Size[0]), float64(val.Size[1])}) - l.SetField(-2, "size") - l.PushString(string(val.Text)) - l.SetField(-2, "text") - l.PushString(string(val.Text2)) - l.SetField(-2, "text_2") - luaPushHUDType(l, val.Type) - l.SetField(-2, "type") - luaPushVec3(l, [3]float64{float64(val.WorldPos[0]), float64(val.WorldPos[1]), float64(val.WorldPos[2])}) - l.SetField(-2, "world_pos") - l.PushInteger(int(val.ZIndex)) - l.SetField(-2, "z_index") -} - -func luaPushNode(l *lua.State, val mt.Node) { - l.NewTable() - l.PushInteger(int(val.Param0)) - l.SetField(-2, "param0") - l.PushInteger(int(val.Param1)) - l.SetField(-2, "param1") - l.PushInteger(int(val.Param2)) - l.SetField(-2, "param2") -} - -func luaPushTileAnim(l *lua.State, val mt.TileAnim) { - l.NewTable() - luaPushVec2(l, [2]float64{float64(val.AspectRatio[0]), float64(val.AspectRatio[1])}) - l.SetField(-2, "aspect_ratio") - l.PushNumber(float64(val.Duration)) - l.SetField(-2, "duration") - luaPushVec2(l, [2]float64{float64(val.NFrames[0]), float64(val.NFrames[1])}) - l.SetField(-2, "n_frames") - luaPushAnimType(l, val.Type) - l.SetField(-2, "type") -} - -func pktToString(pkt *mt.Pkt) string { - switch pkt.Cmd.(type) { - case *mt.ToCltAcceptAuth: - return "accept_auth" - case *mt.ToCltAcceptSudoMode: - return "accept_sudo_mode" - case *mt.ToCltAddHUD: - return "add_hud" - case *mt.ToCltAddNode: - return "add_node" - case *mt.ToCltAddParticleSpawner: - return "add_particle_spawner" - case *mt.ToCltAddPlayerVel: - return "add_player_vel" - case *mt.ToCltAnnounceMedia: - return "announce_media" - case *mt.ToCltAOMsgs: - return "ao_msgs" - case *mt.ToCltAORmAdd: - return "ao_rm_add" - case *mt.ToCltBlkData: - return "blk_data" - case *mt.ToCltBreath: - return "breath" - case *mt.ToCltChangeHUD: - return "change_hud" - case *mt.ToCltChatMsg: - return "chat_msg" - case *mt.ToCltCloudParams: - return "cloud_params" - case *mt.ToCltCSMRestrictionFlags: - return "csm_restriction_flags" - case *mt.ToCltDeathScreen: - return "death_screen" - case *mt.ToCltDelParticleSpawner: - return "del_particle_spawner" - case *mt.ToCltDenySudoMode: - return "deny_sudo_mode" - case *mt.ToCltDetachedInv: - return "detached_inv" - case *mt.ToCltDisco: - return "disco" - case *mt.ToCltEyeOffset: - return "eye_offset" - case *mt.ToCltFadeSound: - return "fade_sound" - case *mt.ToCltFormspecPrepend: - return "formspec_prepend" - case *mt.ToCltFOV: - return "fov" - case *mt.ToCltHello: - return "hello" - case *mt.ToCltHP: - return "hp" - case *mt.ToCltHUDFlags: - return "hud_flags" - case *mt.ToCltInv: - return "inv" - case *mt.ToCltInvFormspec: - return "inv_formspec" - case *mt.ToCltItemDefs: - return "item_defs" - case *mt.ToCltKick: - return "kick" - case *mt.ToCltLegacyKick: - return "legacy_kick" - case *mt.ToCltLocalPlayerAnim: - return "local_player_anim" - case *mt.ToCltMedia: - return "media" - case *mt.ToCltMediaPush: - return "media_push" - case *mt.ToCltMinimapModes: - return "minimap_modes" - case *mt.ToCltModChanMsg: - return "mod_chan_msg" - case *mt.ToCltModChanSig: - return "mod_chan_sig" - case *mt.ToCltMoonParams: - return "moon_params" - case *mt.ToCltMovePlayer: - return "move_player" - case *mt.ToCltMovement: - return "movement" - case *mt.ToCltNodeDefs: - return "node_defs" - case *mt.ToCltNodeMetasChanged: - return "node_metas_changed" - case *mt.ToCltOverrideDayNightRatio: - return "override_day_night_ratio" - case *mt.ToCltPlaySound: - return "play_sound" - case *mt.ToCltPrivs: - return "privs" - case *mt.ToCltRemoveNode: - return "remove_node" - case *mt.ToCltRmHUD: - return "rm_hud" - case *mt.ToCltSetHotbarParam: - return "set_hotbar_param" - case *mt.ToCltShowFormspec: - return "show_formspec" - case *mt.ToCltSkyParams: - return "sky_params" - case *mt.ToCltSpawnParticle: - return "spawn_particle" - case *mt.ToCltSRPBytesSaltB: - return "srp_bytes_salt_b" - case *mt.ToCltStarParams: - return "star_params" - case *mt.ToCltStopSound: - return "stop_sound" - case *mt.ToCltSunParams: - return "sun_params" - case *mt.ToCltTimeOfDay: - return "time_of_day" - case *mt.ToCltUpdatePlayerList: - return "update_player_list" - } - panic("impossible") - return "" -} - -func pktToLua(l *lua.State, pkt *mt.Pkt) { - if pkt == nil { - l.PushNil() - return - } - l.NewTable() - l.PushString(pktToString(pkt)) - l.SetField(-2, "_type") - switch val := pkt.Cmd.(type) { - case *mt.ToCltAcceptAuth: - l.PushNumber(float64(val.MapSeed)) - l.SetField(-2, "map_seed") - luaPushVec3(l, [3]float64{float64(val.PlayerPos[0]), float64(val.PlayerPos[1]), float64(val.PlayerPos[2])}) - l.SetField(-2, "player_pos") - l.PushNumber(float64(val.SendInterval)) - l.SetField(-2, "send_interval") - luaPushAuthMethods(l, val.SudoAuthMethods) - l.SetField(-2, "sudo_auth_methods") - case *mt.ToCltAddHUD: - luaPushHUD(l, val.HUD) - l.SetField(-2, "hud") - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - case *mt.ToCltAddNode: - l.PushBoolean(bool(val.KeepMeta)) - l.SetField(-2, "keep_meta") - luaPushNode(l, val.Node) - l.SetField(-2, "node") - luaPushVec3(l, [3]float64{float64(val.Pos[0]), float64(val.Pos[1]), float64(val.Pos[2])}) - l.SetField(-2, "pos") - case *mt.ToCltAddParticleSpawner: - luaPushBox3(l, [2][3]float64{{float64(val.Acc[0][0]), float64(val.Acc[0][1]), float64(val.Acc[0][2])}, {float64(val.Acc[1][0]), float64(val.Acc[1][1]), float64(val.Acc[1][2])}}) - l.SetField(-2, "acc") - l.PushInteger(int(val.Amount)) - l.SetField(-2, "amount") - luaPushTileAnim(l, val.AnimParams) - l.SetField(-2, "anim_params") - l.PushBoolean(bool(val.AOCollision)) - l.SetField(-2, "ao_collision") - l.PushBoolean(bool(val.Collide)) - l.SetField(-2, "collide") - l.PushBoolean(bool(val.CollisionRm)) - l.SetField(-2, "collision_rm") - l.PushNumber(float64(val.Duration)) - l.SetField(-2, "duration") - luaPushBox1(l, [2]float64{float64(val.ExpirationTime[0]), float64(val.ExpirationTime[1])}) - l.SetField(-2, "expiration_time") - l.PushInteger(int(val.Glow)) - l.SetField(-2, "glow") - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - l.PushInteger(int(val.NodeParam0)) - l.SetField(-2, "node_param0") - l.PushInteger(int(val.NodeParam2)) - l.SetField(-2, "node_param2") - l.PushInteger(int(val.NodeTile)) - l.SetField(-2, "node_tile") - luaPushBox3(l, [2][3]float64{{float64(val.Pos[0][0]), float64(val.Pos[0][1]), float64(val.Pos[0][2])}, {float64(val.Pos[1][0]), float64(val.Pos[1][1]), float64(val.Pos[1][2])}}) - l.SetField(-2, "pos") - luaPushBox1(l, [2]float64{float64(val.Size[0]), float64(val.Size[1])}) - l.SetField(-2, "size") - l.PushString(string(val.Texture)) - l.SetField(-2, "texture") - luaPushBox3(l, [2][3]float64{{float64(val.Vel[0][0]), float64(val.Vel[0][1]), float64(val.Vel[0][2])}, {float64(val.Vel[1][0]), float64(val.Vel[1][1]), float64(val.Vel[1][2])}}) - l.SetField(-2, "vel") - l.PushBoolean(bool(val.Vertical)) - l.SetField(-2, "vertical") - case *mt.ToCltAddPlayerVel: - luaPushVec3(l, [3]float64{float64(val.Vel[0]), float64(val.Vel[1]), float64(val.Vel[2])}) - l.SetField(-2, "vel") - case *mt.ToCltBlkData: - luaPushVec3(l, [3]float64{float64(val.Blkpos[0]), float64(val.Blkpos[1]), float64(val.Blkpos[2])}) - l.SetField(-2, "blkpos") - case *mt.ToCltBreath: - l.PushInteger(int(val.Breath)) - l.SetField(-2, "breath") - case *mt.ToCltChangeHUD: - if val.Field == mt.HUDAlign { - luaPushVec2(l, [2]float64{float64(val.Align[0]), float64(val.Align[1])}) - l.SetField(-2, "align") - } - if val.Field == mt.HUDDir { - l.PushInteger(int(val.Dir)) - l.SetField(-2, "dir") - } - luaPushHUDField(l, val.Field) - l.SetField(-2, "field") - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - if val.Field == mt.HUDItem { - l.PushInteger(int(val.Item)) - l.SetField(-2, "item") - } - if val.Field == mt.HUDName { - l.PushString(string(val.Name)) - l.SetField(-2, "name") - } - if val.Field == mt.HUDNumber { - l.PushInteger(int(val.Number)) - l.SetField(-2, "number") - } - if val.Field == mt.HUDOffset { - luaPushVec2(l, [2]float64{float64(val.Offset[0]), float64(val.Offset[1])}) - l.SetField(-2, "offset") - } - if val.Field == mt.HUDPos { - luaPushVec2(l, [2]float64{float64(val.Pos[0]), float64(val.Pos[1])}) - l.SetField(-2, "pos") - } - if val.Field == mt.HUDSize { - luaPushVec2(l, [2]float64{float64(val.Size[0]), float64(val.Size[1])}) - l.SetField(-2, "size") - } - if val.Field == mt.HUDText { - l.PushString(string(val.Text)) - l.SetField(-2, "text") - } - if val.Field == mt.HUDText2 { - l.PushString(string(val.Text2)) - l.SetField(-2, "text_2") - } - if val.Field == mt.HUDWorldPos { - luaPushVec3(l, [3]float64{float64(val.WorldPos[0]), float64(val.WorldPos[1]), float64(val.WorldPos[2])}) - l.SetField(-2, "world_pos") - } - if val.Field == mt.HUDZIndex { - l.PushInteger(int(val.ZIndex)) - l.SetField(-2, "z_index") - } - case *mt.ToCltChatMsg: - l.PushString(string(val.Sender)) - l.SetField(-2, "sender") - l.PushString(string(val.Text)) - l.SetField(-2, "text") - l.PushNumber(float64(val.Timestamp)) - l.SetField(-2, "timestamp") - luaPushChatMsgType(l, val.Type) - l.SetField(-2, "type") - case *mt.ToCltCloudParams: - luaPushColor(l, val.AmbientColor) - l.SetField(-2, "ambient_color") - l.PushNumber(float64(val.Density)) - l.SetField(-2, "density") - luaPushColor(l, val.DiffuseColor) - l.SetField(-2, "diffuse_color") - l.PushNumber(float64(val.Height)) - l.SetField(-2, "height") - luaPushVec2(l, [2]float64{float64(val.Speed[0]), float64(val.Speed[1])}) - l.SetField(-2, "speed") - l.PushNumber(float64(val.Thickness)) - l.SetField(-2, "thickness") - case *mt.ToCltCSMRestrictionFlags: - luaPushCSMRestrictionFlags(l, val.Flags) - l.SetField(-2, "flags") - l.PushInteger(int(val.MapRange)) - l.SetField(-2, "map_range") - case *mt.ToCltDeathScreen: - luaPushVec3(l, [3]float64{float64(val.PointAt[0]), float64(val.PointAt[1]), float64(val.PointAt[2])}) - l.SetField(-2, "point_at") - l.PushBoolean(bool(val.PointCam)) - l.SetField(-2, "point_cam") - case *mt.ToCltDelParticleSpawner: - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - case *mt.ToCltDetachedInv: - l.PushString(string(val.Inv)) - l.SetField(-2, "inv") - l.PushBoolean(bool(val.Keep)) - l.SetField(-2, "keep") - l.PushInteger(int(val.Len)) - l.SetField(-2, "len") - l.PushString(string(val.Name)) - l.SetField(-2, "name") - case *mt.ToCltEyeOffset: - luaPushVec3(l, [3]float64{float64(val.First[0]), float64(val.First[1]), float64(val.First[2])}) - l.SetField(-2, "first") - luaPushVec3(l, [3]float64{float64(val.Third[0]), float64(val.Third[1]), float64(val.Third[2])}) - l.SetField(-2, "third") - case *mt.ToCltFadeSound: - l.PushNumber(float64(val.Gain)) - l.SetField(-2, "gain") - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - l.PushNumber(float64(val.Step)) - l.SetField(-2, "step") - case *mt.ToCltFormspecPrepend: - l.PushString(string(val.Prepend)) - l.SetField(-2, "prepend") - case *mt.ToCltFOV: - l.PushNumber(float64(val.FOV)) - l.SetField(-2, "fov") - l.PushBoolean(bool(val.Multiplier)) - l.SetField(-2, "multiplier") - l.PushNumber(float64(val.TransitionTime)) - l.SetField(-2, "transition_time") - case *mt.ToCltHello: - luaPushAuthMethods(l, val.AuthMethods) - l.SetField(-2, "auth_methods") - l.PushInteger(int(val.Compression)) - l.SetField(-2, "compression") - l.PushInteger(int(val.ProtoVer)) - l.SetField(-2, "proto_ver") - l.PushInteger(int(val.SerializeVer)) - l.SetField(-2, "serialize_ver") - l.PushString(string(val.Username)) - l.SetField(-2, "username") - case *mt.ToCltHP: - l.PushInteger(int(val.HP)) - l.SetField(-2, "hp") - case *mt.ToCltHUDFlags: - luaPushHUDFlags(l, val.Flags) - l.SetField(-2, "flags") - luaPushHUDFlags(l, val.Mask) - l.SetField(-2, "mask") - case *mt.ToCltInv: - l.PushString(string(val.Inv)) - l.SetField(-2, "inv") - case *mt.ToCltInvFormspec: - l.PushString(string(val.Formspec)) - l.SetField(-2, "formspec") - case *mt.ToCltKick: - if dr := val.Reason; dr == mt.Custom || dr == mt.Shutdown || dr == mt.Crash { - l.PushString(string(val.Custom)) - l.SetField(-2, "custom") - } - luaPushKickReason(l, val.Reason) - l.SetField(-2, "reason") - if dr := val.Reason; dr == mt.Shutdown || dr == mt.Crash { - l.PushBoolean(bool(val.Reconnect)) - l.SetField(-2, "reconnect") - } - case *mt.ToCltLegacyKick: - l.PushString(string(val.Reason)) - l.SetField(-2, "reason") - case *mt.ToCltLocalPlayerAnim: - luaPushBox1(l, [2]float64{float64(val.Dig[0]), float64(val.Dig[1])}) - l.SetField(-2, "dig") - luaPushBox1(l, [2]float64{float64(val.Idle[0]), float64(val.Idle[1])}) - l.SetField(-2, "idle") - l.PushNumber(float64(val.Speed)) - l.SetField(-2, "speed") - luaPushBox1(l, [2]float64{float64(val.Walk[0]), float64(val.Walk[1])}) - l.SetField(-2, "walk") - luaPushBox1(l, [2]float64{float64(val.WalkDig[0]), float64(val.WalkDig[1])}) - l.SetField(-2, "walk_dig") - case *mt.ToCltMediaPush: - l.PushString(string(val.Data)) - l.SetField(-2, "data") - l.PushString(string(val.Filename)) - l.SetField(-2, "filename") - l.PushString(string(val.SHA1[:])) - l.SetField(-2, "sha1") - l.PushBoolean(bool(val.ShouldCache)) - l.SetField(-2, "should_cache") - case *mt.ToCltModChanMsg: - l.PushString(string(val.Channel)) - l.SetField(-2, "channel") - l.PushString(string(val.Msg)) - l.SetField(-2, "msg") - l.PushString(string(val.Sender)) - l.SetField(-2, "sender") - case *mt.ToCltModChanSig: - l.PushString(string(val.Channel)) - l.SetField(-2, "channel") - luaPushModChanSig(l, val.Signal) - l.SetField(-2, "signal") - case *mt.ToCltMoonParams: - l.PushNumber(float64(val.Size)) - l.SetField(-2, "size") - l.PushString(string(val.Texture)) - l.SetField(-2, "texture") - l.PushString(string(val.ToneMap)) - l.SetField(-2, "tone_map") - l.PushBoolean(bool(val.Visible)) - l.SetField(-2, "visible") - case *mt.ToCltMovePlayer: - l.PushNumber(float64(val.Pitch)) - l.SetField(-2, "pitch") - luaPushVec3(l, [3]float64{float64(val.Pos[0]), float64(val.Pos[1]), float64(val.Pos[2])}) - l.SetField(-2, "pos") - l.PushNumber(float64(val.Yaw)) - l.SetField(-2, "yaw") - case *mt.ToCltMovement: - l.PushNumber(float64(val.AirAccel)) - l.SetField(-2, "air_accel") - l.PushNumber(float64(val.ClimbSpeed)) - l.SetField(-2, "climb_speed") - l.PushNumber(float64(val.CrouchSpeed)) - l.SetField(-2, "crouch_speed") - l.PushNumber(float64(val.DefaultAccel)) - l.SetField(-2, "default_accel") - l.PushNumber(float64(val.FastAccel)) - l.SetField(-2, "fast_accel") - l.PushNumber(float64(val.FastSpeed)) - l.SetField(-2, "fast_speed") - l.PushNumber(float64(val.Fluidity)) - l.SetField(-2, "fluidity") - l.PushNumber(float64(val.Gravity)) - l.SetField(-2, "gravity") - l.PushNumber(float64(val.JumpSpeed)) - l.SetField(-2, "jump_speed") - l.PushNumber(float64(val.Sink)) - l.SetField(-2, "sink") - l.PushNumber(float64(val.Smoothing)) - l.SetField(-2, "smoothing") - l.PushNumber(float64(val.WalkSpeed)) - l.SetField(-2, "walk_speed") - case *mt.ToCltOverrideDayNightRatio: - l.PushBoolean(bool(val.Override)) - l.SetField(-2, "override") - l.PushInteger(int(val.Ratio)) - l.SetField(-2, "ratio") - case *mt.ToCltPlaySound: - l.PushBoolean(bool(val.Ephemeral)) - l.SetField(-2, "ephemeral") - l.PushNumber(float64(val.Fade)) - l.SetField(-2, "fade") - l.PushNumber(float64(val.Gain)) - l.SetField(-2, "gain") - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - l.PushBoolean(bool(val.Loop)) - l.SetField(-2, "loop") - l.PushString(string(val.Name)) - l.SetField(-2, "name") - l.PushNumber(float64(val.Pitch)) - l.SetField(-2, "pitch") - luaPushVec3(l, [3]float64{float64(val.Pos[0]), float64(val.Pos[1]), float64(val.Pos[2])}) - l.SetField(-2, "pos") - l.PushInteger(int(val.SrcAOID)) - l.SetField(-2, "src_aoid") - luaPushSoundSrcType(l, val.SrcType) - l.SetField(-2, "src_type") - case *mt.ToCltPrivs: - luaPushStringSet(l, val.Privs) - l.SetField(-2, "privs") - case *mt.ToCltRemoveNode: - luaPushVec3(l, [3]float64{float64(val.Pos[0]), float64(val.Pos[1]), float64(val.Pos[2])}) - l.SetField(-2, "pos") - case *mt.ToCltRmHUD: - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - case *mt.ToCltSetHotbarParam: - l.PushString(string(val.Img)) - l.SetField(-2, "img") - luaPushHotbarParam(l, val.Param) - l.SetField(-2, "param") - l.PushInteger(int(val.Size)) - l.SetField(-2, "size") - case *mt.ToCltShowFormspec: - l.PushString(string(val.Formname)) - l.SetField(-2, "formname") - l.PushString(string(val.Formspec)) - l.SetField(-2, "formspec") - case *mt.ToCltSkyParams: - luaPushColor(l, val.BgColor) - l.SetField(-2, "bg_color") - l.PushBoolean(bool(val.Clouds)) - l.SetField(-2, "clouds") - if val.Type == "regular" { - luaPushColor(l, val.DawnHorizon) - l.SetField(-2, "dawn_horizon") - } - if val.Type == "regular" { - luaPushColor(l, val.DawnSky) - l.SetField(-2, "dawn_sky") - } - if val.Type == "regular" { - luaPushColor(l, val.DayHorizon) - l.SetField(-2, "day_horizon") - } - if val.Type == "regular" { - luaPushColor(l, val.DaySky) - l.SetField(-2, "day_sky") - } - l.PushString(string(val.FogTintType)) - l.SetField(-2, "fog_tint_type") - if val.Type == "regular" { - luaPushColor(l, val.Indoor) - l.SetField(-2, "indoor") - } - luaPushColor(l, val.MoonFogTint) - l.SetField(-2, "moon_fog_tint") - if val.Type == "regular" { - luaPushColor(l, val.NightHorizon) - l.SetField(-2, "night_horizon") - } - if val.Type == "regular" { - luaPushColor(l, val.NightSky) - l.SetField(-2, "night_sky") - } - luaPushColor(l, val.SunFogTint) - l.SetField(-2, "sun_fog_tint") - if val.Type == "skybox" { - luaPushTextureList(l, val.Textures) - l.SetField(-2, "textures") - } - l.PushString(string(val.Type)) - l.SetField(-2, "type") - case *mt.ToCltSpawnParticle: - luaPushVec3(l, [3]float64{float64(val.Acc[0]), float64(val.Acc[1]), float64(val.Acc[2])}) - l.SetField(-2, "acc") - luaPushTileAnim(l, val.AnimParams) - l.SetField(-2, "anim_params") - l.PushBoolean(bool(val.AOCollision)) - l.SetField(-2, "ao_collision") - l.PushBoolean(bool(val.Collide)) - l.SetField(-2, "collide") - l.PushBoolean(bool(val.CollisionRm)) - l.SetField(-2, "collision_rm") - l.PushNumber(float64(val.ExpirationTime)) - l.SetField(-2, "expiration_time") - l.PushInteger(int(val.Glow)) - l.SetField(-2, "glow") - l.PushInteger(int(val.NodeParam0)) - l.SetField(-2, "node_param0") - l.PushInteger(int(val.NodeParam2)) - l.SetField(-2, "node_param2") - l.PushInteger(int(val.NodeTile)) - l.SetField(-2, "node_tile") - luaPushVec3(l, [3]float64{float64(val.Pos[0]), float64(val.Pos[1]), float64(val.Pos[2])}) - l.SetField(-2, "pos") - l.PushNumber(float64(val.Size)) - l.SetField(-2, "size") - l.PushString(string(val.Texture)) - l.SetField(-2, "texture") - luaPushVec3(l, [3]float64{float64(val.Vel[0]), float64(val.Vel[1]), float64(val.Vel[2])}) - l.SetField(-2, "vel") - l.PushBoolean(bool(val.Vertical)) - l.SetField(-2, "vertical") - case *mt.ToCltSRPBytesSaltB: - l.PushString(string(val.B)) - l.SetField(-2, "b") - l.PushString(string(val.Salt)) - l.SetField(-2, "salt") - case *mt.ToCltStarParams: - luaPushColor(l, val.Color) - l.SetField(-2, "color") - l.PushInteger(int(val.Count)) - l.SetField(-2, "count") - l.PushNumber(float64(val.Size)) - l.SetField(-2, "size") - l.PushBoolean(bool(val.Visible)) - l.SetField(-2, "visible") - case *mt.ToCltStopSound: - l.PushInteger(int(val.ID)) - l.SetField(-2, "id") - case *mt.ToCltSunParams: - l.PushString(string(val.Rise)) - l.SetField(-2, "rise") - l.PushBoolean(bool(val.Rising)) - l.SetField(-2, "rising") - l.PushNumber(float64(val.Size)) - l.SetField(-2, "size") - l.PushString(string(val.Texture)) - l.SetField(-2, "texture") - l.PushString(string(val.ToneMap)) - l.SetField(-2, "tone_map") - l.PushBoolean(bool(val.Visible)) - l.SetField(-2, "visible") - case *mt.ToCltTimeOfDay: - l.PushNumber(float64(val.Speed)) - l.SetField(-2, "speed") - l.PushInteger(int(val.Time)) - l.SetField(-2, "time") - case *mt.ToCltUpdatePlayerList: - luaPushStringList(l, val.Players) - l.SetField(-2, "players") - luaPushPlayerListUpdateType(l, val.Type) - l.SetField(-2, "type") - } -} diff --git a/example/dump-traffic.lua b/example/dump-traffic.lua new file mode 100755 index 0000000..b9f30a3 --- /dev/null +++ b/example/dump-traffic.lua @@ -0,0 +1,28 @@ +#!/usr/bin/env hydra +local address, name, password = unpack(arg) +local client = hydra.client(address) + +client:enable("auth") +client.auth:username(name) +client.auth:password(password or "") + +client:wildcard(true) +client:connect() + +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 + end + elseif not interrupt then + print("disconnected") + break + end +end + +client:disconnect() diff --git a/go.mod b/go.mod index 9a3d9b0..cd45843 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,9 @@ module github.com/dragonfireclient/hydra -go 1.17 +go 1.18 require ( - github.com/HimbeerserverDE/srp v0.0.0 // indirect - github.com/Shopify/go-lua v0.0.0-20220120202609-9ab779377807 // indirect - github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f // indirect - github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect + github.com/HimbeerserverDE/srp v0.0.0 + github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f + github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 ) diff --git a/go.sum b/go.sum index 42ec0ba..0717da6 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/HimbeerserverDE/srp v0.0.0 h1:Iy2GIF7DJphXXO9NjncLEBO6VsZd8Yhrlxl/qTr09eE= github.com/HimbeerserverDE/srp v0.0.0/go.mod h1:pxNH8S2nh4n2DWE0ToX5GnnDr/uEAuaAhJsCpkDLIWw= -github.com/Shopify/go-lua v0.0.0-20220120202609-9ab779377807 h1:b10jUZ94GuJk5GBl0iElM5aGIPPHi7FTRvqOKA7Ku+s= -github.com/Shopify/go-lua v0.0.0-20220120202609-9ab779377807/go.mod h1:1cxA/QL5xgRGP7Crq6tXSOY4eo//me8GHGMyypHynM8= github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f h1:tZU8VPYLyRrG3Lj9zBZvTVF5tUGciC/2aUIgTcU4WaM= github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f/go.mod h1:jH4ER+ahjl7H6TczzK+q4V9sXY++U2Geh6/vt3r4Xvs= github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ= diff --git a/hydra.go b/hydra.go index 77d7e05..e3d2427 100644 --- a/hydra.go +++ b/hydra.go @@ -2,7 +2,8 @@ package main import ( _ "embed" - "github.com/Shopify/go-lua" + "github.com/dragonfireclient/hydra/tolua" + "github.com/yuin/gopher-lua" "os" "os/signal" "syscall" @@ -15,15 +16,12 @@ var canceled = false //go:embed builtin/vector.lua var vectorLibrary string -func l_dtime(l *lua.State) int { - l.PushNumber(time.Since(lastTime).Seconds()) - lastTime = time.Now() - return 1 -} - -func l_canceled(l *lua.State) int { - l.PushBoolean(canceled) - return 1 +var hydraFuncs = map[string]lua.LGFunction{ + "client": l_client, + "dtime": l_dtime, + "canceled": l_canceled, + "poll": l_poll, + "disconnect": l_disconnect, } func signalChannel() chan os.Signal { @@ -32,6 +30,36 @@ func signalChannel() chan os.Signal { return sig } +func l_dtime(l *lua.LState) int { + l.Push(lua.LNumber(time.Since(lastTime).Seconds())) + return 1 +} + +func l_canceled(l *lua.LState) int { + l.Push(lua.LBool(canceled)) + return 1 +} + +func l_poll(l *lua.LState) int { + client, pkt, timeout := doPoll(l, getClients(l)) + if client == nil { + l.Push(lua.LNil) + } else { + l.Push(client.userdata) + } + l.Push(tolua.Pkt(l, pkt)) + l.Push(lua.LBool(timeout)) + return 3 +} + +func l_disconnect(l *lua.LState) int { + for _, client := range getClients(l) { + client.disconnect() + } + + return 0 +} + func main() { if len(os.Args) < 2 { panic("missing filename") @@ -42,33 +70,27 @@ func main() { canceled = true }() - l := lua.NewState() - lua.OpenLibraries(l) - - lua.NewLibrary(l, []lua.RegistryFunction{ - {Name: "client", Function: l_client}, - {Name: "dtime", Function: l_dtime}, - {Name: "canceled", Function: l_canceled}, - {Name: "poll", Function: l_poll}, - }) + l := lua.NewState(lua.Options{IncludeGoStackTrace: true}) + defer l.Close() - l.PushNumber(10.0) - l.SetField(-2, "BS") + arg := l.NewTable() + for i, a := range os.Args { + l.RawSetInt(arg, i-1, lua.LString(a)) + } + l.SetGlobal("arg", arg) - l.SetGlobal("hydra") + hydra := l.SetFuncs(l.NewTable(), hydraFuncs) + l.SetField(hydra, "BS", lua.LNumber(10.0)) + l.SetGlobal("hydra", hydra) - l.NewTable() - for i, arg := range os.Args { - l.PushString(arg) - l.RawSetInt(-2, i - 1) - } - l.SetGlobal("arg") + l.SetField(l.NewTypeMetatable("hydra.auth"), "__index", l.SetFuncs(l.NewTable(), authFuncs)) + l.SetField(l.NewTypeMetatable("hydra.client"), "__index", l.NewFunction(l_client_index)) - if err := lua.DoString(l, vectorLibrary); err != nil { + if err := l.DoString(vectorLibrary); err != nil { panic(err) } - if err := lua.DoFile(l, os.Args[1]); err != nil { + if err := l.DoFile(os.Args[1]); err != nil { panic(err) } } diff --git a/mkconvert.lua b/mkconvert.lua deleted file mode 100755 index 1141991..0000000 --- a/mkconvert.lua +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env lua -local function snext(t, state) - local key - - if state == nil then - t.__sorted = {} - for k in pairs(t) do - if k ~= "__sorted" then - table.insert(t.__sorted, k) - end - end - table.sort(t.__sorted) - - key = t.__sorted[1] - else - for i, v in ipairs(t.__sorted) do - if v == state then - key = t.__sorted[i + 1] - break - end - end - end - - if key then - return key, t[key] - end - - t.__sorted = nil -end - -local function spairs(t) - return snext, t, nil -end - -local function parse_pair(pair, value_first) - if pair:sub(1, 1) == "#" then - return - end - - local idx = pair:find(" ") - - if idx then - local first, second = pair:sub(1, idx - 1), pair:sub(idx + 1) - - if value_first and first:sub(1, 1) ~= "[" then - return second, first - else - return first, second - end - else - return pair - end -end - -local function parse_spec(name, value_first) - local f = io.open("spec/" .. name, "r") - local spec = {} - local top - - for l in f:lines() do - if l:sub(1, 1) == "\t" then - local key, val = parse_pair(l:sub(2), value_first) - - if val then - top[key] = val - elseif key then - table.insert(top, key) - end - else - local key, val = parse_pair(l, value_first) - - if val then - spec[key] = val - elseif key then - top = {} - spec[key] = top - end - end - end - - f:close() - return spec -end - -local casemap = parse_spec("casemap") - -local function camel_case(snake) - if casemap[snake] then - return casemap[snake] - end - - local camel = "" - - while #snake > 0 do - local idx = snake:find("_") or #snake + 1 - - camel = camel - .. snake:sub(1, 1):upper() - .. snake:sub(2, idx - 1) - - snake = snake:sub(idx + 1) - end - - return camel -end - -local funcs = "" - -for name, fields in spairs(parse_spec("client/enum")) do - local camel = camel_case(name) - funcs = funcs .. "func luaPush" .. camel .. "(l *lua.State, val mt." .. camel .. ") {\n\tswitch val {\n" - - for _, var in ipairs(fields) do - funcs = funcs .. "\tcase mt." - .. (fields.prefix or "") .. camel_case(var) .. (fields.postfix or "") - .. ":\n\t\t" .. (var == "no" and "l.PushNil()" or "l.PushString(\"" .. var .. "\")") .. "\n" - end - - funcs = funcs .. "\t}\n}\n\n" -end - -for name, fields in spairs(parse_spec("client/flag")) do - local camel = camel_case(name) - funcs = funcs .. "func luaPush" .. camel .. "(l *lua.State, val mt." .. camel .. ") {\n\tl.NewTable()\n" - - for _, var in ipairs(fields) do - funcs = funcs .. "\tif val&mt." - .. (fields.prefix or "") .. camel_case(var) .. (fields.postfix or "") - .. " != 0 {\n\t\tl.PushBoolean(true)\n\t\tl.SetField(-2, \"" .. var .. "\")\n\t}\n" - end - - funcs = funcs .. "}\n\n" -end - -local push_type = { - string = "l.PushString(string(VAL))", - fixed_string = "l.PushString(string(VAL[:]))", - boolean = "l.PushBoolean(bool(VAL))", - integer = "l.PushInteger(int(VAL))", - number = "l.PushNumber(float64(VAL))", - vec2 = "luaPushVec2(l, [2]float64{float64(VAL[0]), float64(VAL[1])})", - vec3 = "luaPushVec3(l, [3]float64{float64(VAL[0]), float64(VAL[1]), float64(VAL[2])})", - box1 = "luaPushBox1(l, [2]float64{float64(VAL[0]), float64(VAL[1])})", - box2 = "luaPushBox2(l, [2][2]float64{{float64(VAL[0][0]), float64(VAL[0][1])}, {float64(VAL[1][0]), float64(VAL[1][1])}})", - box3 = "luaPushBox3(l, [2][3]float64{{float64(VAL[0][0]), float64(VAL[0][1]), float64(VAL[0][2])}, {float64(VAL[1][0]), float64(VAL[1][1]), float64(VAL[1][2])}})", -} - -local function push_fields(fields, indent) - local impl = "" - - for name, type in spairs(fields) do - if name:sub(1, 1) ~= "[" then - local camel = "val." .. camel_case(name) - - local idt = indent - local condition = fields["[" .. name .. "]"] - - if condition then - impl = impl .. indent .. "if " .. condition .. " {\n" - idt = idt .. "\t" - end - - if push_type[type] then - impl = impl .. idt .. push_type[type]:gsub("VAL", camel) .. "\n" - else - impl = impl .. idt .. "luaPush" .. camel_case(type) .. "(l, " .. camel .. ")\n" - end - - impl = impl .. idt .. "l.SetField(-2, \"" .. name .. "\")\n" - - if condition then - impl = impl .. indent .. "}\n" - end - end - end - - return impl -end - -for name, fields in spairs(parse_spec("client/struct", true)) do - local camel = camel_case(name) - funcs = funcs - .. "func luaPush" .. camel .. "(l *lua.State, val mt." .. camel .. ") {\n\tl.NewTable()\n" - .. push_fields(fields, "\t") - .. "}\n\n" -end - -local to_string_impl = "" -local to_lua_impl = "" - -for name, fields in spairs(parse_spec("client/pkt", true)) do - local case = "\tcase *mt.ToClt" .. camel_case(name) .. ":\n" - - to_string_impl = to_string_impl - .. case .. "\t\treturn \"" .. name .. "\"\n" - - if next(fields) then - to_lua_impl = to_lua_impl .. case .. push_fields(fields, "\t\t") - end -end - -local f = io.open("convert.go", "w") -f:write([[ -// generated by mkconvert.lua, DO NOT EDIT -package main - -import ( - "github.com/Shopify/go-lua" - "github.com/anon55555/mt" -) - -]] .. funcs .. [[ -func pktToString(pkt *mt.Pkt) string { - switch pkt.Cmd.(type) { -]] .. to_string_impl .. [[ - } - panic("impossible") - return "" -} - -func pktToLua(l *lua.State, pkt *mt.Pkt) { - if pkt == nil { - l.PushNil() - return - } - l.NewTable() - l.PushString(pktToString(pkt)) - l.SetField(-2, "_type") - switch val := pkt.Cmd.(type) { -]] .. to_lua_impl .. [[ - } -} -]]) -f:close() diff --git a/parse_spec.lua b/parse_spec.lua new file mode 100644 index 0000000..449360c --- /dev/null +++ b/parse_spec.lua @@ -0,0 +1,105 @@ +local function snext(t, state) + local key + + if state == nil then + t.__sorted = {} + for k in pairs(t) do + if k ~= "__sorted" then + table.insert(t.__sorted, k) + end + end + table.sort(t.__sorted) + + key = t.__sorted[1] + else + for i, v in ipairs(t.__sorted) do + if v == state then + key = t.__sorted[i + 1] + break + end + end + end + + if key then + return key, t[key] + end + + t.__sorted = nil +end + +function spairs(t) + return snext, t, nil +end + +local function parse_pair(pair, value_first) + if pair:sub(1, 1) == "#" then + return + end + + local idx = pair:find(" ") + + if idx then + local first, second = pair:sub(1, idx - 1), pair:sub(idx + 1) + + if value_first and first:sub(1, 1) ~= "[" then + return second, first + else + return first, second + end + else + return pair + end +end + +function parse_spec(name, value_first) + local f = io.open("../spec/" .. name, "r") + local spec = {} + local top + + for l in f:lines() do + if l:sub(1, 1) == "\t" then + local key, val = parse_pair(l:sub(2), value_first) + + if val then + top[key] = val + elseif key then + table.insert(top, key) + end + else + local key, val = parse_pair(l, value_first) + + if val then + spec[key] = val + elseif key then + top = {} + spec[key] = top + end + end + end + + f:close() + return spec +end + +local casemap = parse_spec("casemap") + +function camel_case(snake) + if casemap[snake] then + return casemap[snake] + end + + local camel = "" + + while #snake > 0 do + local idx = snake:find("_") or #snake + 1 + + camel = camel + .. snake:sub(1, 1):upper() + .. snake:sub(2, idx - 1) + + snake = snake:sub(idx + 1) + end + + return camel +end + diff --git a/poll.go b/poll.go index bfbe298..db00ef9 100644 --- a/poll.go +++ b/poll.go @@ -1,89 +1,64 @@ package main import ( - "github.com/Shopify/go-lua" "github.com/anon55555/mt" + "github.com/yuin/gopher-lua" "reflect" "time" ) -func l_poll(l *lua.State) int { - clients := make([]*Client, 0) - - lua.CheckType(l, 1, lua.TypeTable) - i := 1 - for { - l.RawGetInt(1, i) - if l.IsNil(-1) { - l.Pop(1) - break - } - - clients = append(clients, l.ToUserData(-1).(*Client)) - i++ - } - +func doPoll(l *lua.LState, clients []*Client) (*Client, *mt.Pkt, bool) { var timeout time.Duration hasTimeout := false - if l.IsNumber(3) { - timeout = time.Duration(lua.CheckNumber(l, 3) * float64(time.Second)) + if l.GetTop() > 1 { + timeout = time.Duration(float64(l.ToNumber(2)) * float64(time.Second)) hasTimeout = true } - for { - cases := make([]reflect.SelectCase, 0, len(clients)+2) + cases := make([]reflect.SelectCase, 0, len(clients)+2) + for _, client := range clients { + if client.state != csConnected { + continue + } - for _, client := range clients { - if client.state != csConnected { - continue - } + cases = append(cases, reflect.SelectCase{ + Dir: reflect.SelectRecv, + Chan: reflect.ValueOf(client.queue), + }) + } - cases = append(cases, reflect.SelectCase{ - Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(client.queue), - }) - } + offset := len(cases) - offset := len(cases) + if offset < 1 { + return nil, nil, false + } - if offset < 1 { - l.PushBoolean(false) - return 1 - } + cases = append(cases, reflect.SelectCase{ + Dir: reflect.SelectRecv, + Chan: reflect.ValueOf(signalChannel()), + }) + if hasTimeout { cases = append(cases, reflect.SelectCase{ Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(signalChannel()), + Chan: reflect.ValueOf(time.After(timeout)), }) + } - if hasTimeout { - cases = append(cases, reflect.SelectCase{ - Dir: reflect.SelectRecv, - Chan: reflect.ValueOf(time.After(timeout)), - }) - } - - idx, value, ok := reflect.Select(cases) - - if idx >= offset { - l.PushBoolean(true) - return 1 - } + idx, value, ok := reflect.Select(cases) - client := clients[idx] + if idx >= offset { + return nil, nil, true + } - var pkt *mt.Pkt = nil - if ok { - pkt = value.Interface().(*mt.Pkt) - } else { - client.state = csDisconnected - } + client := clients[idx] - for _, handler := range client.handlers { - handler.handle(pkt, l, idx+1) - } + var pkt *mt.Pkt = nil + if ok { + pkt = value.Interface().(*mt.Pkt) + } else { + client.state = csDisconnected } - panic("impossible") - return 0 + return client, pkt, false } diff --git a/spec/client/pkt b/spec/client/pkt index bc04127..e7c609b 100644 --- a/spec/client/pkt +++ b/spec/client/pkt @@ -1,7 +1,7 @@ hello - integer serialize_ver - integer compression - integer proto_ver + number serialize_ver + number compression + number proto_ver auth_methods auth_methods string username accept_auth @@ -14,9 +14,9 @@ accept_sudo_mode deny_sudo_mode kick kick_reason reason - [custom] dr := val.Reason; dr == mt.Custom || dr == mt.Shutdown || dr == mt.Crash + [custom] val.Reason == mt.Custom || val.Reason == mt.Shutdown || val.Reason == mt.Crash string custom - [reconnect] dr := val.Reason; dr == mt.Shutdown || dr == mt.Crash + [reconnect] val.Reason == mt.Shutdown || val.Reason == mt.Crash boolean reconnect blk_data vec3 blkpos @@ -30,11 +30,11 @@ remove_node inv string inv time_of_day - integer time + number time number speed csm_restriction_flags csm_restriction_flags flags - integer map_range + number map_range add_player_vel vec3 vel media_push @@ -53,7 +53,7 @@ ao_rm_add ao_msgs # TODO hp - integer hp + number hp move_player vec3 pos number pitch @@ -76,18 +76,18 @@ announce_media item_defs # TODO play_sound - integer id + number id string name number gain sound_src_type src_type vec3 pos - integer src_aoid + number src_aoid boolean loop number fade number pitch boolean ephemeral stop_sound - integer id + number id privs string_set privs inv_formspec @@ -95,7 +95,7 @@ inv_formspec detached_inv string name boolean keep - integer len + number len string inv show_formspec string formspec @@ -124,13 +124,13 @@ spawn_particle boolean vertical boolean collision_rm tile_anim anim_params - integer glow + number glow boolean ao_collision - integer node_param0 - integer node_param2 - integer node_tile + number node_param0 + number node_param2 + number node_tile add_particle_spawner - integer amount + number amount number duration box3 pos box3 vel @@ -139,22 +139,22 @@ add_particle_spawner box1 size boolean collide string texture - integer id + number id boolean vertical boolean collision_rm tile_anim anim_params - integer glow + number glow boolean ao_collision - integer node_param0 - integer node_param2 - integer node_tile + number node_param0 + number node_param2 + number node_tile add_hud - integer id + number id hud hud rm_hud - integer id + number id change_hud - integer id + number id hud_field field [pos] val.Field == mt.HUDPos [name] val.Field == mt.HUDName @@ -171,24 +171,24 @@ change_hud vec2 pos string name string text - integer number - integer item - integer dir + number number + number item + number dir vec2 align vec2 offset vec3 world_pos vec2 size - integer z_index + number z_index string text_2 hud_flags hud_flags flags hud_flags mask set_hotbar_param hotbar_param param - integer size + number size string img breath - integer breath + number breath sky_params color bg_color string type @@ -214,7 +214,7 @@ sky_params color indoor override_day_night_ratio boolean override - integer ratio + number ratio local_player_anim box1 idle box1 walk @@ -225,7 +225,7 @@ eye_offset vec3 first vec3 third del_particle_spawner - integer id + number id cloud_params number density color diffuse_color @@ -234,7 +234,7 @@ cloud_params number thickness vec2 speed fade_sound - integer id + number id number step number gain update_player_list @@ -263,7 +263,7 @@ moon_params number size star_params boolean visible - integer count + number count color color number size srp_bytes_salt_b diff --git a/spec/client/struct b/spec/client/struct index 1fa149c..d18189c 100644 --- a/spec/client/struct +++ b/spec/client/struct @@ -1,7 +1,7 @@ node - integer param0 - integer param1 - integer param2 + number param0 + number param1 + number param2 tile_anim anim_type type vec2 aspect_ratio @@ -13,12 +13,12 @@ hud string name vec2 scale string text - integer number - integer item - integer dir + number number + number item + number dir vec2 align vec2 offset vec3 world_pos vec2 size - integer z_index + number z_index string text_2 diff --git a/tolua/generate.lua b/tolua/generate.lua new file mode 100755 index 0000000..7c2d5a7 --- /dev/null +++ b/tolua/generate.lua @@ -0,0 +1,129 @@ +#!/usr/bin/env lua +dofile("../parse_spec.lua") + +local funcs = "" + +for name, fields in spairs(parse_spec("client/enum")) do + local camel = camel_case(name) + funcs = funcs .. "func " .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\tswitch val {\n" + + for _, var in ipairs(fields) do + funcs = funcs .. "\tcase mt." + .. (fields.prefix or "") .. camel_case(var) .. (fields.postfix or "") + .. ":\n\t\t" .. (var == "no" and "return lua.LNil" or "return lua.LString(\"" .. var .. "\")") .. "\n" + end + + funcs = funcs .. "\t}\n\tpanic(\"impossible\")\n\treturn lua.LNil\n}\n\n" +end + +for name, fields in spairs(parse_spec("client/flag")) do + local camel = camel_case(name) + funcs = funcs .. "func " .. 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." + .. (fields.prefix or "") .. camel_case(var) .. (fields.postfix or "") + .. " != 0 {\n\t\tl.SetField(tbl, \"" .. var .. "\", lua.LTrue)\n\t}\n" + end + + funcs = funcs .. "\treturn tbl\n}\n\n" +end + +local to_lua = { + string = "lua.LString(string(VAL))", + fixed_string = "lua.LString(string(VAL[:]))", + boolean = "lua.LBool(VAL)", + number = "lua.LNumber(VAL)", + vec2 = "Vec2(l, [2]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1])})", + vec3 = "Vec3(l, [3]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1]), lua.LNumber(VAL[2])})", + box1 = "Box1(l, [2]lua.LNumber{lua.LNumber(VAL[0]), lua.LNumber(VAL[1])})", + box2 = "Box2(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 = "Box3(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_to_lua(fields, indent) + local impl = "" + + for name, type in spairs(fields) do + if name:sub(1, 1) ~= "[" then + local camel = "val." .. camel_case(name) + + local idt = indent + local condition = fields["[" .. name .. "]"] + + if condition then + impl = impl .. indent .. "if " .. condition .. " {\n" + idt = idt .. "\t" + end + + impl = impl .. idt .. "l.SetField(tbl, \"" .. name .. "\", " + if to_lua[type] then + impl = impl .. to_lua[type]:gsub("VAL", camel) + else + impl = impl .. camel_case(type) .. "(l, " .. camel .. ")" + end + impl = impl .. ")\n" + + if condition then + impl = impl .. indent .. "}\n" + end + end + end + + return impl +end + +for name, fields in spairs(parse_spec("client/struct", true)) do + local camel = camel_case(name) + funcs = funcs + .. "func " .. camel .. "(l *lua.LState, val mt." .. camel .. ") lua.LValue {\n\ttbl := l.NewTable()\n" + .. fields_to_lua(fields, "\t") + .. "\treturn tbl\n}\n\n" +end + +local to_string_impl = "" +local to_lua_impl = "" + +for name, fields in spairs(parse_spec("client/pkt", true)) do + local case = "\tcase *mt.ToClt" .. camel_case(name) .. ":\n" + + to_string_impl = to_string_impl + .. case .. "\t\treturn lua.LString(\"" .. name .. "\")\n" + + if next(fields) then + to_lua_impl = to_lua_impl .. case .. fields_to_lua(fields, "\t\t") + end +end + +local f = io.open("generated.go", "w") +f:write([[ +// generated by generate.lua, DO NOT EDIT +package tolua + +import ( + "github.com/anon55555/mt" + "github.com/yuin/gopher-lua" +) + +]] .. funcs .. [[ +func PktType(pkt *mt.Pkt) lua.LString { + switch pkt.Cmd.(type) { +]] .. to_string_impl .. [[ + } + panic("impossible") + return "" +} + +func Pkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { + if pkt == nil { + return lua.LNil + } + tbl := l.NewTable() + l.SetField(tbl, "_type", PktType(pkt)) + switch val := pkt.Cmd.(type) { +]] .. to_lua_impl .. [[ + } + return tbl +} +]]) +f:close() diff --git a/tolua/generated.go b/tolua/generated.go new file mode 100644 index 0000000..ec53231 --- /dev/null +++ b/tolua/generated.go @@ -0,0 +1,684 @@ +// generated by generate.lua, DO NOT EDIT +package tolua + +import ( + "github.com/anon55555/mt" + "github.com/yuin/gopher-lua" +) + +func AnimType(l *lua.LState, val mt.AnimType) lua.LValue { + switch val { + case mt.NoAnim: + return lua.LNil + case mt.VerticalFrameAnim: + return lua.LString("vertical_frame") + case mt.SpriteSheetAnim: + return lua.LString("sprite_sheet") + } + panic("impossible") + return lua.LNil +} + +func ChatMsgType(l *lua.LState, val mt.ChatMsgType) lua.LValue { + switch val { + case mt.RawMsg: + return lua.LString("raw") + case mt.NormalMsg: + return lua.LString("normal") + case mt.AnnounceMsg: + return lua.LString("announce") + case mt.SysMsg: + return lua.LString("sys") + } + panic("impossible") + return lua.LNil +} + +func HotbarParam(l *lua.LState, val mt.HotbarParam) lua.LValue { + switch val { + case mt.HotbarSize: + return lua.LString("size") + case mt.HotbarImg: + return lua.LString("img") + case mt.HotbarSelImg: + return lua.LString("sel_img") + } + panic("impossible") + return lua.LNil +} + +func HUDField(l *lua.LState, val mt.HUDField) lua.LValue { + switch val { + case mt.HUDPos: + return lua.LString("pos") + case mt.HUDName: + return lua.LString("name") + case mt.HUDScale: + return lua.LString("scale") + case mt.HUDText: + return lua.LString("text") + case mt.HUDNumber: + return lua.LString("number") + case mt.HUDItem: + return lua.LString("item") + case mt.HUDDir: + return lua.LString("dir") + case mt.HUDAlign: + return lua.LString("align") + case mt.HUDOffset: + return lua.LString("offset") + case mt.HUDWorldPos: + return lua.LString("world_pos") + case mt.HUDSize: + return lua.LString("size") + case mt.HUDZIndex: + return lua.LString("z_index") + case mt.HUDText2: + return lua.LString("text_2") + } + panic("impossible") + return lua.LNil +} + +func HUDType(l *lua.LState, val mt.HUDType) lua.LValue { + switch val { + case mt.ImgHUD: + return lua.LString("img") + case mt.TextHUD: + return lua.LString("text") + case mt.StatbarHUD: + return lua.LString("statbar") + case mt.InvHUD: + return lua.LString("inv") + case mt.WaypointHUD: + return lua.LString("waypoint") + case mt.ImgWaypointHUD: + return lua.LString("img_waypoint") + } + panic("impossible") + return lua.LNil +} + +func KickReason(l *lua.LState, val mt.KickReason) lua.LValue { + switch val { + case mt.WrongPasswd: + return lua.LString("wrong_passwd") + case mt.UnexpectedData: + return lua.LString("unexpected_data") + case mt.SrvIsSingleplayer: + return lua.LString("srv_is_singleplayer") + case mt.UnsupportedVer: + return lua.LString("unsupported_ver") + case mt.BadNameChars: + return lua.LString("bad_name_chars") + case mt.BadName: + return lua.LString("bad_name") + case mt.TooManyClts: + return lua.LString("too_many_clts") + case mt.EmptyPasswd: + return lua.LString("empty_passwd") + case mt.AlreadyConnected: + return lua.LString("already_connected") + case mt.SrvErr: + return lua.LString("srv_err") + case mt.Custom: + return lua.LString("custom") + case mt.Shutdown: + return lua.LString("shutdown") + case mt.Crash: + return lua.LString("crash") + } + panic("impossible") + return lua.LNil +} + +func ModChanSig(l *lua.LState, val mt.ModChanSig) lua.LValue { + switch val { + case mt.JoinOK: + return lua.LString("join_ok") + case mt.JoinFail: + return lua.LString("join_fail") + case mt.LeaveOK: + return lua.LString("leave_ok") + case mt.LeaveFail: + return lua.LString("leave_fail") + case mt.NotRegistered: + return lua.LString("not_registered") + case mt.SetState: + return lua.LString("set_state") + } + panic("impossible") + return lua.LNil +} + +func PlayerListUpdateType(l *lua.LState, val mt.PlayerListUpdateType) lua.LValue { + switch val { + case mt.InitPlayers: + return lua.LString("init") + case mt.AddPlayers: + return lua.LString("add") + case mt.RemovePlayers: + return lua.LString("remove") + } + panic("impossible") + return lua.LNil +} + +func SoundSrcType(l *lua.LState, val mt.SoundSrcType) lua.LValue { + switch val { + case mt.NoSrc: + return lua.LNil + case mt.PosSrc: + return lua.LString("pos") + case mt.AOSrc: + return lua.LString("ao") + } + panic("impossible") + return lua.LNil +} + +func AuthMethods(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) + } + return tbl +} + +func CSMRestrictionFlags(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) + } + return tbl +} + +func HUDFlags(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) + } + return tbl +} + +func HUD(l *lua.LState, val mt.HUD) lua.LValue { + tbl := l.NewTable() + l.SetField(tbl, "align", Vec2(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", Vec2(l, [2]lua.LNumber{lua.LNumber(val.Offset[0]), lua.LNumber(val.Offset[1])})) + l.SetField(tbl, "pos", Vec2(l, [2]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1])})) + l.SetField(tbl, "scale", Vec2(l, [2]lua.LNumber{lua.LNumber(val.Scale[0]), lua.LNumber(val.Scale[1])})) + l.SetField(tbl, "size", Vec2(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", HUDType(l, val.Type)) + l.SetField(tbl, "world_pos", Vec3(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 Node(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)) + l.SetField(tbl, "param2", lua.LNumber(val.Param2)) + return tbl +} + +func TileAnim(l *lua.LState, val mt.TileAnim) lua.LValue { + tbl := l.NewTable() + l.SetField(tbl, "aspect_ratio", Vec2(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", Vec2(l, [2]lua.LNumber{lua.LNumber(val.NFrames[0]), lua.LNumber(val.NFrames[1])})) + l.SetField(tbl, "type", AnimType(l, val.Type)) + return tbl +} + +func PktType(pkt *mt.Pkt) lua.LString { + switch pkt.Cmd.(type) { + case *mt.ToCltAcceptAuth: + return lua.LString("accept_auth") + case *mt.ToCltAcceptSudoMode: + return lua.LString("accept_sudo_mode") + case *mt.ToCltAddHUD: + return lua.LString("add_hud") + case *mt.ToCltAddNode: + return lua.LString("add_node") + case *mt.ToCltAddParticleSpawner: + return lua.LString("add_particle_spawner") + case *mt.ToCltAddPlayerVel: + return lua.LString("add_player_vel") + case *mt.ToCltAnnounceMedia: + return lua.LString("announce_media") + case *mt.ToCltAOMsgs: + return lua.LString("ao_msgs") + case *mt.ToCltAORmAdd: + return lua.LString("ao_rm_add") + case *mt.ToCltBlkData: + return lua.LString("blk_data") + case *mt.ToCltBreath: + return lua.LString("breath") + case *mt.ToCltChangeHUD: + return lua.LString("change_hud") + case *mt.ToCltChatMsg: + return lua.LString("chat_msg") + case *mt.ToCltCloudParams: + return lua.LString("cloud_params") + case *mt.ToCltCSMRestrictionFlags: + return lua.LString("csm_restriction_flags") + case *mt.ToCltDeathScreen: + return lua.LString("death_screen") + case *mt.ToCltDelParticleSpawner: + return lua.LString("del_particle_spawner") + case *mt.ToCltDenySudoMode: + return lua.LString("deny_sudo_mode") + case *mt.ToCltDetachedInv: + return lua.LString("detached_inv") + case *mt.ToCltDisco: + return lua.LString("disco") + case *mt.ToCltEyeOffset: + return lua.LString("eye_offset") + case *mt.ToCltFadeSound: + return lua.LString("fade_sound") + case *mt.ToCltFormspecPrepend: + return lua.LString("formspec_prepend") + case *mt.ToCltFOV: + return lua.LString("fov") + case *mt.ToCltHello: + return lua.LString("hello") + case *mt.ToCltHP: + return lua.LString("hp") + case *mt.ToCltHUDFlags: + return lua.LString("hud_flags") + case *mt.ToCltInv: + return lua.LString("inv") + case *mt.ToCltInvFormspec: + return lua.LString("inv_formspec") + case *mt.ToCltItemDefs: + return lua.LString("item_defs") + case *mt.ToCltKick: + return lua.LString("kick") + case *mt.ToCltLegacyKick: + return lua.LString("legacy_kick") + case *mt.ToCltLocalPlayerAnim: + return lua.LString("local_player_anim") + case *mt.ToCltMedia: + return lua.LString("media") + case *mt.ToCltMediaPush: + return lua.LString("media_push") + case *mt.ToCltMinimapModes: + return lua.LString("minimap_modes") + case *mt.ToCltModChanMsg: + return lua.LString("mod_chan_msg") + case *mt.ToCltModChanSig: + return lua.LString("mod_chan_sig") + case *mt.ToCltMoonParams: + return lua.LString("moon_params") + case *mt.ToCltMovePlayer: + return lua.LString("move_player") + case *mt.ToCltMovement: + return lua.LString("movement") + case *mt.ToCltNodeDefs: + return lua.LString("node_defs") + case *mt.ToCltNodeMetasChanged: + return lua.LString("node_metas_changed") + case *mt.ToCltOverrideDayNightRatio: + return lua.LString("override_day_night_ratio") + case *mt.ToCltPlaySound: + return lua.LString("play_sound") + case *mt.ToCltPrivs: + return lua.LString("privs") + case *mt.ToCltRemoveNode: + return lua.LString("remove_node") + case *mt.ToCltRmHUD: + return lua.LString("rm_hud") + case *mt.ToCltSetHotbarParam: + return lua.LString("set_hotbar_param") + case *mt.ToCltShowFormspec: + return lua.LString("show_formspec") + case *mt.ToCltSkyParams: + return lua.LString("sky_params") + case *mt.ToCltSpawnParticle: + return lua.LString("spawn_particle") + case *mt.ToCltSRPBytesSaltB: + return lua.LString("srp_bytes_salt_b") + case *mt.ToCltStarParams: + return lua.LString("star_params") + case *mt.ToCltStopSound: + return lua.LString("stop_sound") + case *mt.ToCltSunParams: + return lua.LString("sun_params") + case *mt.ToCltTimeOfDay: + return lua.LString("time_of_day") + case *mt.ToCltUpdatePlayerList: + return lua.LString("update_player_list") + } + panic("impossible") + return "" +} + +func Pkt(l *lua.LState, pkt *mt.Pkt) lua.LValue { + if pkt == nil { + return lua.LNil + } + tbl := l.NewTable() + l.SetField(tbl, "_type", PktType(pkt)) + switch val := pkt.Cmd.(type) { + case *mt.ToCltAcceptAuth: + l.SetField(tbl, "map_seed", lua.LNumber(val.MapSeed)) + l.SetField(tbl, "player_pos", Vec3(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", AuthMethods(l, val.SudoAuthMethods)) + case *mt.ToCltAddHUD: + l.SetField(tbl, "hud", HUD(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", Node(l, val.Node)) + l.SetField(tbl, "pos", Vec3(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", Box3(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", TileAnim(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", Box1(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", Box3(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", Box1(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", Box3(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", Vec3(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", Vec3(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", Vec2(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", HUDField(l, val.Field)) + l.SetField(tbl, "id", lua.LNumber(val.ID)) + if val.Field == mt.HUDItem { + l.SetField(tbl, "item", lua.LNumber(val.Item)) + } + if val.Field == mt.HUDName { + l.SetField(tbl, "name", lua.LString(string(val.Name))) + } + if val.Field == mt.HUDNumber { + l.SetField(tbl, "number", lua.LNumber(val.Number)) + } + if val.Field == mt.HUDOffset { + l.SetField(tbl, "offset", Vec2(l, [2]lua.LNumber{lua.LNumber(val.Offset[0]), lua.LNumber(val.Offset[1])})) + } + if val.Field == mt.HUDPos { + l.SetField(tbl, "pos", Vec2(l, [2]lua.LNumber{lua.LNumber(val.Pos[0]), lua.LNumber(val.Pos[1])})) + } + if val.Field == mt.HUDSize { + l.SetField(tbl, "size", Vec2(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))) + } + if val.Field == mt.HUDText2 { + l.SetField(tbl, "text_2", lua.LString(string(val.Text2))) + } + if val.Field == mt.HUDWorldPos { + l.SetField(tbl, "world_pos", Vec3(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)) + } + case *mt.ToCltChatMsg: + 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", ChatMsgType(l, val.Type)) + case *mt.ToCltCloudParams: + l.SetField(tbl, "ambient_color", Color(l, val.AmbientColor)) + l.SetField(tbl, "density", lua.LNumber(val.Density)) + l.SetField(tbl, "diffuse_color", Color(l, val.DiffuseColor)) + l.SetField(tbl, "height", lua.LNumber(val.Height)) + l.SetField(tbl, "speed", Vec2(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", CSMRestrictionFlags(l, val.Flags)) + l.SetField(tbl, "map_range", lua.LNumber(val.MapRange)) + case *mt.ToCltDeathScreen: + l.SetField(tbl, "point_at", Vec3(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)) + case *mt.ToCltDetachedInv: + l.SetField(tbl, "inv", lua.LString(string(val.Inv))) + l.SetField(tbl, "keep", lua.LBool(val.Keep)) + l.SetField(tbl, "len", lua.LNumber(val.Len)) + l.SetField(tbl, "name", lua.LString(string(val.Name))) + case *mt.ToCltEyeOffset: + l.SetField(tbl, "first", Vec3(l, [3]lua.LNumber{lua.LNumber(val.First[0]), lua.LNumber(val.First[1]), lua.LNumber(val.First[2])})) + l.SetField(tbl, "third", Vec3(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)) + l.SetField(tbl, "step", lua.LNumber(val.Step)) + case *mt.ToCltFormspecPrepend: + l.SetField(tbl, "prepend", lua.LString(string(val.Prepend))) + case *mt.ToCltFOV: + l.SetField(tbl, "fov", lua.LNumber(val.FOV)) + 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", AuthMethods(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)) + l.SetField(tbl, "username", lua.LString(string(val.Username))) + case *mt.ToCltHP: + l.SetField(tbl, "hp", lua.LNumber(val.HP)) + case *mt.ToCltHUDFlags: + l.SetField(tbl, "flags", HUDFlags(l, val.Flags)) + l.SetField(tbl, "mask", HUDFlags(l, val.Mask)) + case *mt.ToCltInv: + l.SetField(tbl, "inv", lua.LString(string(val.Inv))) + case *mt.ToCltInvFormspec: + l.SetField(tbl, "formspec", lua.LString(string(val.Formspec))) + case *mt.ToCltKick: + 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", KickReason(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", Box1(l, [2]lua.LNumber{lua.LNumber(val.Dig[0]), lua.LNumber(val.Dig[1])})) + l.SetField(tbl, "idle", Box1(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", Box1(l, [2]lua.LNumber{lua.LNumber(val.Walk[0]), lua.LNumber(val.Walk[1])})) + l.SetField(tbl, "walk_dig", Box1(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))) + l.SetField(tbl, "sha1", lua.LString(string(val.SHA1[:]))) + l.SetField(tbl, "should_cache", lua.LBool(val.ShouldCache)) + case *mt.ToCltModChanMsg: + l.SetField(tbl, "channel", lua.LString(string(val.Channel))) + l.SetField(tbl, "msg", lua.LString(string(val.Msg))) + 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", ModChanSig(l, val.Signal)) + case *mt.ToCltMoonParams: + l.SetField(tbl, "size", lua.LNumber(val.Size)) + l.SetField(tbl, "texture", lua.LString(string(val.Texture))) + l.SetField(tbl, "tone_map", lua.LString(string(val.ToneMap))) + l.SetField(tbl, "visible", lua.LBool(val.Visible)) + case *mt.ToCltMovePlayer: + l.SetField(tbl, "pitch", lua.LNumber(val.Pitch)) + l.SetField(tbl, "pos", Vec3(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)) + l.SetField(tbl, "climb_speed", lua.LNumber(val.ClimbSpeed)) + l.SetField(tbl, "crouch_speed", lua.LNumber(val.CrouchSpeed)) + l.SetField(tbl, "default_accel", lua.LNumber(val.DefaultAccel)) + l.SetField(tbl, "fast_accel", lua.LNumber(val.FastAccel)) + l.SetField(tbl, "fast_speed", lua.LNumber(val.FastSpeed)) + l.SetField(tbl, "fluidity", lua.LNumber(val.Fluidity)) + l.SetField(tbl, "gravity", lua.LNumber(val.Gravity)) + l.SetField(tbl, "jump_speed", lua.LNumber(val.JumpSpeed)) + 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.ToCltOverrideDayNightRatio: + l.SetField(tbl, "override", lua.LBool(val.Override)) + l.SetField(tbl, "ratio", lua.LNumber(val.Ratio)) + case *mt.ToCltPlaySound: + l.SetField(tbl, "ephemeral", lua.LBool(val.Ephemeral)) + l.SetField(tbl, "fade", lua.LNumber(val.Fade)) + l.SetField(tbl, "gain", lua.LNumber(val.Gain)) + l.SetField(tbl, "id", lua.LNumber(val.ID)) + 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", Vec3(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", SoundSrcType(l, val.SrcType)) + case *mt.ToCltPrivs: + l.SetField(tbl, "privs", StringSet(l, val.Privs)) + case *mt.ToCltRemoveNode: + l.SetField(tbl, "pos", Vec3(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", HotbarParam(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", Color(l, val.BgColor)) + l.SetField(tbl, "clouds", lua.LBool(val.Clouds)) + if val.Type == "regular" { + l.SetField(tbl, "dawn_horizon", Color(l, val.DawnHorizon)) + } + if val.Type == "regular" { + l.SetField(tbl, "dawn_sky", Color(l, val.DawnSky)) + } + if val.Type == "regular" { + l.SetField(tbl, "day_horizon", Color(l, val.DayHorizon)) + } + if val.Type == "regular" { + l.SetField(tbl, "day_sky", Color(l, val.DaySky)) + } + l.SetField(tbl, "fog_tint_type", lua.LString(string(val.FogTintType))) + if val.Type == "regular" { + l.SetField(tbl, "indoor", Color(l, val.Indoor)) + } + l.SetField(tbl, "moon_fog_tint", Color(l, val.MoonFogTint)) + if val.Type == "regular" { + l.SetField(tbl, "night_horizon", Color(l, val.NightHorizon)) + } + if val.Type == "regular" { + l.SetField(tbl, "night_sky", Color(l, val.NightSky)) + } + l.SetField(tbl, "sun_fog_tint", Color(l, val.SunFogTint)) + if val.Type == "skybox" { + l.SetField(tbl, "textures", TextureList(l, val.Textures)) + } + l.SetField(tbl, "type", lua.LString(string(val.Type))) + case *mt.ToCltSpawnParticle: + l.SetField(tbl, "acc", Vec3(l, [3]lua.LNumber{lua.LNumber(val.Acc[0]), lua.LNumber(val.Acc[1]), lua.LNumber(val.Acc[2])})) + l.SetField(tbl, "anim_params", TileAnim(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, "expiration_time", lua.LNumber(val.ExpirationTime)) + l.SetField(tbl, "glow", lua.LNumber(val.Glow)) + 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", Vec3(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", Vec3(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", Color(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)) + case *mt.ToCltStopSound: + l.SetField(tbl, "id", lua.LNumber(val.ID)) + case *mt.ToCltSunParams: + l.SetField(tbl, "rise", lua.LString(string(val.Rise))) + l.SetField(tbl, "rising", lua.LBool(val.Rising)) + l.SetField(tbl, "size", lua.LNumber(val.Size)) + l.SetField(tbl, "texture", lua.LString(string(val.Texture))) + l.SetField(tbl, "tone_map", lua.LString(string(val.ToneMap))) + l.SetField(tbl, "visible", lua.LBool(val.Visible)) + case *mt.ToCltTimeOfDay: + l.SetField(tbl, "speed", lua.LNumber(val.Speed)) + l.SetField(tbl, "time", lua.LNumber(val.Time)) + case *mt.ToCltUpdatePlayerList: + l.SetField(tbl, "players", StringList(l, val.Players)) + l.SetField(tbl, "type", PlayerListUpdateType(l, val.Type)) + } + return tbl +} diff --git a/tolua/static.go b/tolua/static.go new file mode 100644 index 0000000..30d56ef --- /dev/null +++ b/tolua/static.go @@ -0,0 +1,97 @@ +package tolua + +import ( + "github.com/anon55555/mt" + "github.com/yuin/gopher-lua" + "image/color" +) + +//go:generate ./generate.lua + +func pushVec2(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 pushVec3(l *lua.LState, val [3]lua.LNumber) { + l.Push(l.GetGlobal("vec3")) + l.Push(val[0]) + l.Push(val[1]) + l.Push(val[2]) + l.Call(3, 1) +} + +func popValue(l *lua.LState) lua.LValue { + ret := l.Get(-1) + l.Pop(1) + return ret +} + +func Vec2(l *lua.LState, val [2]lua.LNumber) lua.LValue { + pushVec2(l, val) + return popValue(l) +} + +func Vec3(l *lua.LState, val [3]lua.LNumber) lua.LValue { + pushVec3(l, val) + return popValue(l) +} + +func Box1(l *lua.LState, val [2]lua.LNumber) lua.LValue { + l.Push(l.GetGlobal("box")) + l.Push(val[0]) + l.Push(val[1]) + l.Call(2, 1) + return popValue(l) +} + +func Box2(l *lua.LState, val [2][2]lua.LNumber) lua.LValue { + l.Push(l.GetGlobal("box")) + pushVec2(l, val[0]) + pushVec2(l, val[1]) + l.Call(2, 1) + return popValue(l) +} + +func Box3(l *lua.LState, val [2][3]lua.LNumber) lua.LValue { + l.Push(l.GetGlobal("box")) + pushVec3(l, val[0]) + pushVec3(l, val[1]) + l.Call(2, 1) + return popValue(l) +} + +func Color(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)) + l.SetField(tbl, "b", lua.LNumber(val.B)) + l.SetField(tbl, "a", lua.LNumber(val.A)) + return tbl +} + +func StringSet(l *lua.LState, val []string) lua.LValue { + tbl := l.NewTable() + for _, str := range val { + l.SetField(tbl, str, lua.LTrue) + } + return tbl +} + +func stringList[T ~string](l *lua.LState, val []T) lua.LValue { + tbl := l.NewTable() + for _, s := range val { + tbl.Append(lua.LString(s)) + } + return tbl +} + +func StringList(l *lua.LState, val []string) lua.LValue { + return stringList[string](l, val) +} + +func TextureList(l *lua.LState, val []mt.Texture) lua.LValue { + return stringList[mt.Texture](l, val) +} diff --git a/types.go b/types.go deleted file mode 100644 index 0fe1cad..0000000 --- a/types.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -import ( - "github.com/Shopify/go-lua" - "github.com/anon55555/mt" - "image/color" -) - -//go:generate ./mkconvert.lua - -func luaPushVec2(l *lua.State, val [2]float64) { - l.Global("vec2") - l.PushNumber(val[0]) - l.PushNumber(val[1]) - l.Call(2, 1) -} - -func luaPushVec3(l *lua.State, val [3]float64) { - l.Global("vec3") - l.PushNumber(val[0]) - l.PushNumber(val[1]) - l.PushNumber(val[2]) - l.Call(3, 1) -} - -func luaPushBox1(l *lua.State, val [2]float64) { - l.Global("box") - l.PushNumber(val[0]) - l.PushNumber(val[1]) - l.Call(2, 1) -} - -func luaPushBox2(l *lua.State, val [2][2]float64) { - l.Global("box") - luaPushVec2(l, val[0]) - luaPushVec2(l, val[1]) - l.Call(2, 1) -} - -func luaPushBox3(l *lua.State, val [2][3]float64) { - l.Global("box") - luaPushVec3(l, val[0]) - luaPushVec3(l, val[1]) - l.Call(2, 1) -} - -func luaPushColor(l *lua.State, val color.NRGBA) { - l.NewTable() - l.PushInteger(int(val.R)) - l.SetField(-2, "r") - l.PushInteger(int(val.G)) - l.SetField(-2, "g") - l.PushInteger(int(val.B)) - l.SetField(-2, "b") - l.PushInteger(int(val.A)) - l.SetField(-2, "a") -} - -func luaPushStringSet(l *lua.State, val []string) { - l.NewTable() - for _, str := range val { - l.PushBoolean(true) - l.SetField(-2, str) - } -} - -func luaPushStringList(l *lua.State, val []string) { - l.NewTable() - for i, str := range val { - l.PushString(str) - l.RawSetInt(-2, i+1) - } -} - -// i hate go for making me do this instead of just using luaPushStringList -// but i dont want to make an unsafe cast either -func luaPushTextureList(l *lua.State, val []mt.Texture) { - l.NewTable() - for i, str := range val { - l.PushString(string(str)) - l.RawSetInt(-2, i+1) - } -}