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
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 {

View File

@ -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
}
}

View File

@ -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
}