]> git.lizzy.rs Git - hydra-dragonfire.git/blobdiff - client.go
Merge pull request #4 from Minetest-j45/master
[hydra-dragonfire.git] / client.go
index d27af337946edb5c5c3d21a409b9b555de76f4fb..b177a073844805b4942bf5b3acfef2b80f073887 100644 (file)
--- a/client.go
+++ b/client.go
@@ -2,8 +2,8 @@ package main
 
 import (
        "errors"
-       "github.com/anon55555/mt"
        "github.com/dragonfireclient/hydra-dragonfire/convert"
+       "github.com/dragonfireclient/mt"
        "github.com/yuin/gopher-lua"
        "net"
        "sync"
@@ -25,28 +25,43 @@ type Component interface {
 }
 
 type Client struct {
-       mu         sync.Mutex
        address    string
        state      clientState
        conn       mt.Peer
-       queue      chan *mt.Pkt
-       wildcard   bool
-       subscribed map[string]struct{}
+       muConn     sync.Mutex
+       queue      chan Event
        components map[string]Component
+       muComp     sync.Mutex
+       table      *lua.LTable
        userdata   *lua.LUserData
 }
 
 var clientFuncs = map[string]lua.LGFunction{
-       "address":     l_client_address,
-       "state":       l_client_state,
-       "connect":     l_client_connect,
-       "poll":        l_client_poll,
-       "close":       l_client_close,
-       "enable":      l_client_enable,
-       "subscribe":   l_client_subscribe,
-       "unsubscribe": l_client_unsubscribe,
-       "wildcard":    l_client_wildcard,
-       "send":        l_client_send,
+       "address": l_client_address,
+       "state":   l_client_state,
+       "connect": l_client_connect,
+       "poll":    l_client_poll,
+       "close":   l_client_close,
+       "enable":  l_client_enable,
+       "send":    l_client_send,
+}
+
+type EventError struct {
+       err string
+}
+
+func (evt EventError) handle(l *lua.LState, val lua.LValue) {
+       l.SetField(val, "type", lua.LString("error"))
+       l.SetField(val, "error", lua.LString(evt.err))
+}
+
+type EventDisconnect struct {
+       client *Client
+}
+
+func (evt EventDisconnect) handle(l *lua.LState, val lua.LValue) {
+       l.SetField(val, "type", lua.LString("disconnect"))
+       evt.client.state = csDisconnected
 }
 
 func getClient(l *lua.LState) *Client {
@@ -65,20 +80,9 @@ func getClients(l *lua.LState) []*Client {
        return clients
 }
 
-func getStrings(l *lua.LState) []string {
-       n := l.GetTop()
-
-       strs := make([]string, 0, n-1)
-       for i := 2; i <= n; i++ {
-               strs = append(strs, l.CheckString(i))
-       }
-
-       return strs
-}
-
 func (client *Client) closeConn() {
-       client.mu.Lock()
-       defer client.mu.Unlock()
+       client.muConn.Lock()
+       defer client.muConn.Unlock()
 
        if client.state == csConnected {
                client.conn.Close()
@@ -90,9 +94,8 @@ func l_client(l *lua.LState) int {
 
        client.address = l.CheckString(1)
        client.state = csNew
-       client.wildcard = false
-       client.subscribed = map[string]struct{}{}
        client.components = map[string]Component{}
+       client.table = l.NewTable()
        client.userdata = l.NewUserData()
        client.userdata.Value = client
        l.SetMetatable(client.userdata, l.GetTypeMetatable("hydra.client"))
@@ -105,7 +108,9 @@ func l_client_index(l *lua.LState) int {
        client := getClient(l)
        key := l.CheckString(2)
 
-       if fun, exists := clientFuncs[key]; exists {
+       if key == "data" {
+               l.Push(client.table)
+       } else if fun, exists := clientFuncs[key]; exists {
                l.Push(l.NewFunction(fun))
        } else if component, exists := client.components[key]; exists {
                l.Push(component.push())
@@ -154,46 +159,39 @@ func l_client_connect(l *lua.LState) int {
 
        client.state = csConnected
        client.conn = mt.Connect(conn)
-       client.queue = make(chan *mt.Pkt, 1024)
+       client.queue = make(chan Event, 1024)
 
        go func() {
                for {
                        pkt, err := client.conn.Recv()
 
                        if err == nil {
-                               client.mu.Lock()
-                               for _, component := range client.components {
-                                       component.process(&pkt)
-                               }
-                               _, subscribed := client.subscribed[string(convert.PushPktType(&pkt))]
-                               client.mu.Unlock()
-
-                               if subscribed || client.wildcard {
-                                       client.queue <- &pkt
+                               client.muComp.Lock()
+                               for _, comp := range client.components {
+                                       comp.process(&pkt)
                                }
+                               client.muComp.Unlock()
                        } else if errors.Is(err, net.ErrClosed) {
-                               close(client.queue)
+                               client.queue <- EventDisconnect{client: client}
                                return
+                       } else {
+                               client.queue <- EventError{err: err.Error()}
                        }
                }
        }()
 
-       client.mu.Lock()
-       for _, component := range client.components {
-               component.connect()
+       client.muComp.Lock()
+       for _, comp := range client.components {
+               comp.connect()
        }
-       client.mu.Unlock()
+       client.muComp.Unlock()
 
        return 0
 }
 
 func l_client_poll(l *lua.LState) int {
        client := getClient(l)
-       _, pkt, timeout := doPoll(l, []*Client{client})
-
-       l.Push(convert.PushPkt(l, pkt))
-       l.Push(lua.LBool(timeout))
-       return 2
+       return doPoll(l, []*Client{client})
 }
 
 func l_client_close(l *lua.LState) int {
@@ -204,59 +202,40 @@ func l_client_close(l *lua.LState) int {
 
 func l_client_enable(l *lua.LState) int {
        client := getClient(l)
-       client.mu.Lock()
-       defer client.mu.Unlock()
+       n := l.GetTop()
+
+       client.muComp.Lock()
+       defer client.muComp.Unlock()
+
+       for i := 2; i <= n; i++ {
+               name := l.CheckString(i)
 
-       for _, compname := range getStrings(l) {
-               if component, exists := client.components[compname]; !exists {
-                       switch compname {
+               if comp, exists := client.components[name]; !exists {
+                       switch name {
                        case "auth":
-                               component = &Auth{}
+                               comp = &CompAuth{}
+                       case "map":
+                               comp = &CompMap{}
+                       case "pkts":
+                               comp = &CompPkts{}
                        default:
-                               panic("invalid component: " + compname)
+                               panic("invalid component: " + name)
                        }
 
-                       client.components[compname] = component
-                       component.create(client, l)
+                       client.components[name] = comp
+                       comp.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_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)
 
+       client.muConn.Lock()
+       defer client.muConn.Unlock()
+
        if client.state != csConnected {
                panic("not connected")
        }
@@ -264,12 +243,9 @@ func l_client_send(l *lua.LState) int {
        cmd := convert.ReadCmd(l)
        doAck := l.ToBool(4)
 
-       client.mu.Lock()
-       defer client.mu.Unlock()
-
        if client.state == csConnected {
                ack, err := client.conn.SendCmd(cmd)
-               if err != nil {
+               if err != nil && !errors.Is(err, net.ErrClosed) {
                        panic(err)
                }