refactor Gateway out
parent
9824fecaa2
commit
d006c992ec
|
@ -72,9 +72,11 @@ type gameWorldServer struct {
|
||||||
proto.UnimplementedGameWorldServer
|
proto.UnimplementedGameWorldServer
|
||||||
|
|
||||||
db db.DB
|
db db.DB
|
||||||
mu sync.Mutex // for msgRouter
|
msgRouterMutex sync.Mutex
|
||||||
msgRouter map[string]func(*proto.ClientMessage) error
|
msgRouter map[string]func(*proto.ClientMessage) error
|
||||||
Gateway *witch.Gateway
|
Gateway *witch.Gateway
|
||||||
|
scripts map[int]*witch.ScriptContext
|
||||||
|
scriptsMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newServer() (*gameWorldServer, error) {
|
func newServer() (*gameWorldServer, error) {
|
||||||
|
@ -95,13 +97,37 @@ func newServer() (*gameWorldServer, error) {
|
||||||
s := &gameWorldServer{
|
s := &gameWorldServer{
|
||||||
msgRouter: make(map[string]func(*proto.ClientMessage) error),
|
msgRouter: make(map[string]func(*proto.ClientMessage) error),
|
||||||
db: db,
|
db: db,
|
||||||
|
scripts: make(map[int]*witch.ScriptContext),
|
||||||
|
scriptsMutex: sync.RWMutex{},
|
||||||
}
|
}
|
||||||
gw := witch.NewGateway(s.HandleCmd)
|
|
||||||
s.Gateway = gw
|
|
||||||
|
|
||||||
return s, nil
|
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) {
|
func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) {
|
||||||
// TODO
|
// 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 {
|
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.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.
|
// TODO this is clearly bad but it works. I should refactor this so that messages are received on a channel.
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package witch
|
package witch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/vilmibm/hermeticum/server/db"
|
"github.com/vilmibm/hermeticum/server/db"
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
)
|
)
|
||||||
|
@ -15,14 +13,14 @@ import (
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type scriptContext struct {
|
type ScriptContext struct {
|
||||||
script string
|
script string
|
||||||
l *lua.LState
|
l *lua.LState
|
||||||
incoming chan string
|
incoming chan string
|
||||||
// TODO whatever is needed to support calling a Go API
|
// 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
|
return sc.script != obj.Script
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +60,7 @@ end)
|
||||||
// - do i inject from Go or prepend some Lua code?
|
// - do i inject from Go or prepend some Lua code?
|
||||||
// TODO figure out how the Lua code can affect Go and thus the database
|
// 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 := lua.NewState()
|
||||||
|
|
||||||
l.SetGlobal("has", l.NewFunction(hasWrapper(obj)))
|
l.SetGlobal("has", l.NewFunction(hasWrapper(obj)))
|
||||||
|
@ -73,49 +71,10 @@ func newScriptContext(obj db.Object) (*scriptContext, error) {
|
||||||
return nil, err
|
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
|
// TODO call _handle function from the Lstate
|
||||||
return nil
|
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