From 5456518feb89e3fba2eeac33c910e99846e9c6e9 Mon Sep 17 00:00:00 2001 From: vilmibm Date: Fri, 23 Dec 2022 22:34:21 -0800 Subject: [PATCH] get LStates into goroutines --- server/cmd/main.go | 29 ++++++++++------- server/witch/header.go | 5 ++- server/witch/witch.go | 73 +++++++++++++++++++++++++++--------------- 3 files changed, 68 insertions(+), 39 deletions(-) diff --git a/server/cmd/main.go b/server/cmd/main.go index 05e3c57..c784137 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -74,7 +74,6 @@ type gameWorldServer struct { db db.DB msgRouterMutex sync.Mutex msgRouter map[string]func(*proto.ClientMessage) error - Gateway *witch.Gateway scripts map[int]*witch.ScriptContext scriptsMutex sync.RWMutex } @@ -105,17 +104,14 @@ func newServer() (*gameWorldServer, error) { } 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 - */ + // I think i should rethink this. sc should maybe be permanent and then they re-create LStates s.scriptsMutex.RLock() sc, ok := s.scripts[target.ID] s.scriptsMutex.RUnlock() + var err error - if !ok || sc.NeedsRefresh(target) { - sc, err := witch.NewScriptContext(target) + if !ok { + sc, err = witch.NewScriptContext() if err != nil { return err } @@ -125,7 +121,16 @@ func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Objec s.scriptsMutex.Unlock() } - return sc.Handle(verb, rest, sender, target) + vc := witch.VerbContext{ + Verb: verb, + Rest: rest, + Sender: sender, + Target: target, + } + + sc.Handle(vc) + + return nil } func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) { @@ -187,10 +192,10 @@ func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error affected, err := s.db.Earshot(*avatar) for _, o := range affected { - err = s.Gateway.VerbHandler(cmd.Verb, cmd.Rest, *avatar, o) + err = s.verbHandler(cmd.Verb, cmd.Rest, *avatar, o) } - s.HandleCmd(cmd.Verb, cmd.Rest, avatar) + //s.HandleCmd(cmd.Verb, cmd.Rest, avatar) /* @@ -355,7 +360,7 @@ func (s *gameWorldServer) HandleSay(sender *db.Object, msg string) error { // TODO figure out pointer shit for _, h := range heard { - s.Gateway.VerbHandler("hears", msg, sender, &h) + s.verbHandler("hears", msg, *sender, h) // TODO once we have a script engine, deliver the HEARS event for _, sess := range as { if sess.AccountID == h.OwnerID { diff --git a/server/witch/header.go b/server/witch/header.go index 9a5c7d3..872fbdd 100644 --- a/server/witch/header.go +++ b/server/witch/header.go @@ -1,13 +1,16 @@ package witch import ( + "log" + "github.com/vilmibm/hermeticum/server/db" lua "github.com/yuin/gopher-lua" ) func hasWrapper(obj db.Object) func(*lua.LState) int { return func(ls *lua.LState) int { - //lv := ls.ToTable(1) + lv := ls.ToTable(1) + log.Println(lv) return 0 } } diff --git a/server/witch/witch.go b/server/witch/witch.go index bd9c84a..29580c8 100644 --- a/server/witch/witch.go +++ b/server/witch/witch.go @@ -1,6 +1,8 @@ package witch import ( + "log" + "github.com/vilmibm/hermeticum/server/db" lua "github.com/yuin/gopher-lua" ) @@ -13,17 +15,6 @@ import ( */ -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 { - return sc.script != obj.Script -} - // TODO using a dummy script for now const dummyScript = ` @@ -60,21 +51,51 @@ 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) { - l := lua.NewState() - - l.SetGlobal("has", l.NewFunction(hasWrapper(obj))) - l.SetGlobal("_handlers", l.NewTable()) - - //if err := l.DoString(obj.Script); err != nil { - if err := l.DoString(dummyScript); err != nil { - return nil, err - } - - return &ScriptContext{}, nil +type VerbContext struct { + Verb string + Rest string + Sender db.Object + Target db.Object } -func (sc *ScriptContext) Handle(verb, rest string, sender, target db.Object) error { - // TODO call _handle function from the Lstate - return nil +type ScriptContext struct { + script string + incoming chan VerbContext +} + +func NewScriptContext() (*ScriptContext, error) { + sc := &ScriptContext{} + sc.incoming = make(chan VerbContext) + + go func() { + var l *lua.LState + var err error + var vc VerbContext + for { + vc = <-sc.incoming + //if vc.Target.Script != sc.script { + if dummyScript != sc.script { + //sc.script = vc.Target.Script + sc.script = dummyScript + l = lua.NewState() + l.SetGlobal("has", l.NewFunction(hasWrapper(vc.Target))) + l.SetGlobal("hears", l.NewFunction(hearsWrapper(vc.Target))) + l.SetGlobal("_handlers", l.NewTable()) + // TODO other setup + //if err := l.DoString(obj.Script); err != nil { + if err = l.DoString(dummyScript); err != nil { + log.Printf("error parsing script %s: %s", dummyScript, err.Error()) + } + } + + // TODO actually trigger the Lua script + } + }() + + return sc, nil +} + +func (sc *ScriptContext) Handle(vc VerbContext) { + log.Printf("%#v %#v", sc, vc) + sc.incoming <- vc }