refactor Gateway out
parent
9824fecaa2
commit
d006c992ec
|
@ -71,10 +71,12 @@ func _main() (err error) {
|
|||
type gameWorldServer struct {
|
||||
proto.UnimplementedGameWorldServer
|
||||
|
||||
db db.DB
|
||||
mu sync.Mutex // for msgRouter
|
||||
msgRouter map[string]func(*proto.ClientMessage) error
|
||||
Gateway *witch.Gateway
|
||||
db db.DB
|
||||
msgRouterMutex sync.Mutex
|
||||
msgRouter map[string]func(*proto.ClientMessage) error
|
||||
Gateway *witch.Gateway
|
||||
scripts map[int]*witch.ScriptContext
|
||||
scriptsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func newServer() (*gameWorldServer, error) {
|
||||
|
@ -93,15 +95,39 @@ func newServer() (*gameWorldServer, error) {
|
|||
}
|
||||
|
||||
s := &gameWorldServer{
|
||||
msgRouter: make(map[string]func(*proto.ClientMessage) error),
|
||||
db: db,
|
||||
msgRouter: make(map[string]func(*proto.ClientMessage) error),
|
||||
db: db,
|
||||
scripts: make(map[int]*witch.ScriptContext),
|
||||
scriptsMutex: sync.RWMutex{},
|
||||
}
|
||||
gw := witch.NewGateway(s.HandleCmd)
|
||||
s.Gateway = gw
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Object) error {
|
||||
/*
|
||||
So right here is a problem: we are definitely making >1 LuaState per
|
||||
goroutine. Top priority before anything else is getting a goroutine made
|
||||
for the script contexts
|
||||
*/
|
||||
s.scriptsMutex.RLock()
|
||||
sc, ok := s.scripts[target.ID]
|
||||
s.scriptsMutex.RUnlock()
|
||||
|
||||
if !ok || sc.NeedsRefresh(target) {
|
||||
sc, err := witch.NewScriptContext(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.scriptsMutex.Lock()
|
||||
s.scripts[target.ID] = sc
|
||||
s.scriptsMutex.Unlock()
|
||||
}
|
||||
|
||||
return sc.Handle(verb, rest, sender, target)
|
||||
}
|
||||
|
||||
func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) {
|
||||
// TODO
|
||||
}
|
||||
|
@ -213,9 +239,9 @@ func (s *gameWorldServer) Ping(ctx context.Context, _ *proto.SessionInfo) (*prot
|
|||
}
|
||||
|
||||
func (s *gameWorldServer) Messages(si *proto.SessionInfo, stream proto.GameWorld_MessagesServer) error {
|
||||
s.mu.Lock()
|
||||
s.msgRouterMutex.Lock()
|
||||
s.msgRouter[si.SessionID] = stream.Send
|
||||
s.mu.Unlock()
|
||||
s.msgRouterMutex.Unlock()
|
||||
|
||||
// TODO this is clearly bad but it works. I should refactor this so that messages are received on a channel.
|
||||
for {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package witch
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/vilmibm/hermeticum/server/db"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
)
|
||||
|
@ -15,14 +13,14 @@ import (
|
|||
|
||||
*/
|
||||
|
||||
type scriptContext struct {
|
||||
type ScriptContext struct {
|
||||
script string
|
||||
l *lua.LState
|
||||
incoming chan string
|
||||
// TODO whatever is needed to support calling a Go API
|
||||
}
|
||||
|
||||
func (sc *scriptContext) NeedsRefresh(obj db.Object) bool {
|
||||
func (sc *ScriptContext) NeedsRefresh(obj db.Object) bool {
|
||||
return sc.script != obj.Script
|
||||
}
|
||||
|
||||
|
@ -62,7 +60,7 @@ end)
|
|||
// - do i inject from Go or prepend some Lua code?
|
||||
// TODO figure out how the Lua code can affect Go and thus the database
|
||||
|
||||
func newScriptContext(obj db.Object) (*scriptContext, error) {
|
||||
func NewScriptContext(obj db.Object) (*ScriptContext, error) {
|
||||
l := lua.NewState()
|
||||
|
||||
l.SetGlobal("has", l.NewFunction(hasWrapper(obj)))
|
||||
|
@ -73,49 +71,10 @@ func newScriptContext(obj db.Object) (*scriptContext, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &scriptContext{}, nil
|
||||
return &ScriptContext{}, nil
|
||||
}
|
||||
|
||||
func (sc *scriptContext) Handle(verb, rest string, sender, target *db.Object) error {
|
||||
|
||||
func (sc *ScriptContext) Handle(verb, rest string, sender, target db.Object) error {
|
||||
// TODO call _handle function from the Lstate
|
||||
return nil
|
||||
}
|
||||
|
||||
type Gateway struct {
|
||||
// maps game object IDs to script contexts
|
||||
m map[int]*scriptContext
|
||||
mu sync.RWMutex
|
||||
cb func(string, string, *db.Object)
|
||||
}
|
||||
|
||||
func NewGateway(cb func(string, string, *db.Object)) *Gateway {
|
||||
return &Gateway{
|
||||
m: map[int]*scriptContext{},
|
||||
mu: sync.RWMutex{},
|
||||
// TODO use cb from scriptContext
|
||||
cb: cb,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) VerbHandler(verb, rest string, sender, target db.Object) error {
|
||||
var sc *scriptContext
|
||||
g.mu.RLock()
|
||||
sc, ok := g.m[target.ID]
|
||||
g.mu.RUnlock()
|
||||
|
||||
if !ok || sc.NeedsRefresh(target) {
|
||||
sc, err := newScriptContext(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.mu.Lock()
|
||||
g.m[target.ID] = sc
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
sc.Handle(verb, rest, &sender, &target)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue