aboutsummaryrefslogtreecommitdiffstats
path: root/client/quake/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'client/quake/client.go')
-rw-r--r--client/quake/client.go107
1 files changed, 107 insertions, 0 deletions
diff --git a/client/quake/client.go b/client/quake/client.go
new file mode 100644
index 0000000..7b48e6c
--- /dev/null
+++ b/client/quake/client.go
@@ -0,0 +1,107 @@
+package quake
+
+import (
+ "errors"
+ "log"
+ "net"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/osm/quake/client"
+ "github.com/osm/quake/common/context"
+ "github.com/osm/quake/common/rand"
+ "github.com/osm/quake/common/sequencer"
+ "github.com/osm/quake/packet"
+ "github.com/osm/quake/packet/command"
+ "github.com/osm/quake/packet/command/stringcmd"
+ "github.com/osm/quake/protocol"
+)
+
+var (
+ ErrNoName = errors.New("no name supplied")
+ ErrNoTeam = errors.New("no team supplied")
+)
+
+const connectReadDeadline = time.Duration(13)
+
+type Client struct {
+ conn *net.UDPConn
+ logger *log.Logger
+ ctx *context.Context
+ cmdsMu sync.Mutex
+ cmds []command.Command
+ seq *sequencer.Sequencer
+ handlers []func(packet.Packet) []command.Command
+
+ addrPort string
+ qPort uint16
+
+ serverCount int32
+ readDeadline time.Duration
+
+ clientVersion string
+ isSpectator bool
+ mapName string
+ name string
+ ping int16
+ team string
+ bottomColor byte
+ topColor byte
+
+ fteEnabled bool
+ fteExtensions uint32
+ fte2Enabled bool
+ fte2Extensions uint32
+ mvdEnabled bool
+ mvdExtensions uint32
+ zQuakeEnabled bool
+ zQuakeExtensions uint32
+}
+
+func New(name, team string, opts ...Option) (client.Client, error) {
+ if name == "" {
+ return nil, ErrNoName
+ }
+
+ if team == "" {
+ return nil, ErrNoTeam
+ }
+
+ c := &Client{
+ ctx: context.New(context.WithProtocolVersion(protocol.VersionQW)),
+ logger: log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime),
+ seq: sequencer.New(),
+ readDeadline: connectReadDeadline,
+ qPort: rand.Uint16(),
+ name: name,
+ ping: 999,
+ team: team,
+ }
+
+ for _, opt := range opts {
+ opt(c)
+ }
+
+ c.seq.SetPing(c.ping)
+
+ return c, nil
+}
+
+func (c *Client) Enqueue(cmds []command.Command) {
+ c.cmdsMu.Lock()
+ c.cmds = append(c.cmds, cmds...)
+ c.cmdsMu.Unlock()
+}
+
+func (c *Client) HandleFunc(h func(h packet.Packet) []command.Command) {
+ c.handlers = append(c.handlers, h)
+}
+
+func (c *Client) Quit() {
+ c.cmds = append(c.cmds, &stringcmd.Command{String: "drop"})
+
+ if c.seq.GetState() == sequencer.Connected {
+ time.Sleep(time.Duration(c.ping) * time.Millisecond)
+ }
+}