get LStates into goroutines

trunk
vilmibm 2022-12-23 22:34:21 -08:00
parent d006c992ec
commit 5456518feb
3 changed files with 68 additions and 39 deletions

View File

@ -74,7 +74,6 @@ type gameWorldServer struct {
db db.DB db db.DB
msgRouterMutex sync.Mutex msgRouterMutex sync.Mutex
msgRouter map[string]func(*proto.ClientMessage) error msgRouter map[string]func(*proto.ClientMessage) error
Gateway *witch.Gateway
scripts map[int]*witch.ScriptContext scripts map[int]*witch.ScriptContext
scriptsMutex sync.RWMutex scriptsMutex sync.RWMutex
} }
@ -105,17 +104,14 @@ func newServer() (*gameWorldServer, error) {
} }
func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Object) error { func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Object) error {
/* // I think i should rethink this. sc should maybe be permanent and then they re-create LStates
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() s.scriptsMutex.RLock()
sc, ok := s.scripts[target.ID] sc, ok := s.scripts[target.ID]
s.scriptsMutex.RUnlock() s.scriptsMutex.RUnlock()
var err error
if !ok || sc.NeedsRefresh(target) { if !ok {
sc, err := witch.NewScriptContext(target) sc, err = witch.NewScriptContext()
if err != nil { if err != nil {
return err return err
} }
@ -125,7 +121,16 @@ func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Objec
s.scriptsMutex.Unlock() 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) { 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) affected, err := s.db.Earshot(*avatar)
for _, o := range affected { 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 // TODO figure out pointer shit
for _, h := range heard { 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 // TODO once we have a script engine, deliver the HEARS event
for _, sess := range as { for _, sess := range as {
if sess.AccountID == h.OwnerID { if sess.AccountID == h.OwnerID {

View File

@ -1,13 +1,16 @@
package witch package witch
import ( import (
"log"
"github.com/vilmibm/hermeticum/server/db" "github.com/vilmibm/hermeticum/server/db"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
func hasWrapper(obj db.Object) func(*lua.LState) int { func hasWrapper(obj db.Object) func(*lua.LState) int {
return func(ls *lua.LState) int { return func(ls *lua.LState) int {
//lv := ls.ToTable(1) lv := ls.ToTable(1)
log.Println(lv)
return 0 return 0
} }
} }

View File

@ -1,6 +1,8 @@
package witch package witch
import ( import (
"log"
"github.com/vilmibm/hermeticum/server/db" "github.com/vilmibm/hermeticum/server/db"
lua "github.com/yuin/gopher-lua" 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 // TODO using a dummy script for now
const dummyScript = ` const dummyScript = `
@ -60,21 +51,51 @@ 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) { type VerbContext struct {
l := lua.NewState() Verb string
Rest string
l.SetGlobal("has", l.NewFunction(hasWrapper(obj))) Sender db.Object
l.SetGlobal("_handlers", l.NewTable()) Target db.Object
//if err := l.DoString(obj.Script); err != nil {
if err := l.DoString(dummyScript); err != nil {
return nil, err
}
return &ScriptContext{}, nil
} }
func (sc *ScriptContext) Handle(verb, rest string, sender, target db.Object) error { type ScriptContext struct {
// TODO call _handle function from the Lstate script string
return nil 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
} }