aboutsummaryrefslogtreecommitdiff
path: root/hydra.go
blob: c8f1e6778363355c4600319b9f78407aa52b3e85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main

import (
	_ "embed"
	"github.com/dragonfireclient/hydra-dragonfire/convert"
	"github.com/yuin/gopher-lua"
	"os"
	"os/signal"
	"syscall"
	"time"
)

var lastTime = time.Now()
var canceled = false

var serializeVer uint8 = 28
var protoVer uint16 = 39

//go:embed builtin/luax/init.lua
var builtinLuaX string

//go:embed builtin/vector.lua
var builtinVector string

//go:embed builtin/escapes.lua
var builtinEscapes string

//go:embed builtin/client.lua
var builtinClient string

var builtinFiles = []string{
	builtinLuaX,
	builtinVector,
	builtinEscapes,
	builtinClient,
}

var hydraFuncs = map[string]lua.LGFunction{
	"client":   l_client,
	"dtime":    l_dtime,
	"canceled": l_canceled,
	"poll":     l_poll,
	"close":    l_close,
}

func signalChannel() chan os.Signal {
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
	return sig
}

func l_dtime(l *lua.LState) int {
	l.Push(lua.LNumber(time.Since(lastTime).Seconds()))
	lastTime = time.Now()
	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))
	l.Push(convert.PushPkt(l, pkt))
	if client == nil {
		l.Push(lua.LNil)
	} else {
		l.Push(client.userdata)
	}
	l.Push(lua.LBool(timeout))
	return 3
}

func l_close(l *lua.LState) int {
	for _, client := range getClients(l) {
		client.closeConn()
	}

	return 0
}

func main() {
	if len(os.Args) < 2 {
		panic("missing filename")
	}

	go func() {
		<-signalChannel()
		canceled = true
	}()

	l := lua.NewState(lua.Options{IncludeGoStackTrace: true})
	defer l.Close()

	arg := l.NewTable()
	for i, a := range os.Args {
		l.RawSetInt(arg, i-1, lua.LString(a))
	}
	l.SetGlobal("arg", arg)

	hydra := l.SetFuncs(l.NewTable(), hydraFuncs)
	l.SetField(hydra, "BS", lua.LNumber(10.0))
	l.SetField(hydra, "serialize_ver", lua.LNumber(serializeVer))
	l.SetField(hydra, "proto_ver", lua.LNumber(protoVer))
	l.SetGlobal("hydra", hydra)

	l.SetField(l.NewTypeMetatable("hydra.auth"), "__index", l.SetFuncs(l.NewTable(), authFuncs))
	l.SetField(l.NewTypeMetatable("hydra.client"), "__index", l.NewFunction(l_client_index))

	for _, str := range builtinFiles {
		if err := l.DoString(str); err != nil {
			panic(err)
		}
	}

	if err := l.DoFile(os.Args[1]); err != nil {
		panic(err)
	}
}