WIP on emotes; need to fix client side / command verb parsing

trunk
vilmibm 2022-12-29 00:22:18 -05:00
parent e085fa0fd1
commit 6d6e6d5726
5 changed files with 64 additions and 104 deletions

View File

@ -60,6 +60,7 @@ func (cs *ClientState) HandleInput(input string) error {
var verb string var verb string
rest := input rest := input
if strings.HasPrefix(input, "/") { if strings.HasPrefix(input, "/") {
// TODO this is def broken lol
input = input[1:] input = input[1:]
parts := strings.SplitN(input, " ", 1) parts := strings.SplitN(input, " ", 1)
verb = parts[0] verb = parts[0]
@ -105,7 +106,14 @@ func (cs *ClientState) AddMessage(msg *proto.ClientMessage) {
// TODO look into using the SetChangedFunc thing. // TODO look into using the SetChangedFunc thing.
cs.App.QueueUpdateDraw(func() { cs.App.QueueUpdateDraw(func() {
// TODO trim content of messagesView /or/ see if tview has a buffer size that does it for me. use cs.messages to re-constitute. // TODO trim content of messagesView /or/ see if tview has a buffer size that does it for me. use cs.messages to re-constitute.
switch msg.Type {
case proto.ClientMessage_OVERHEARD:
fmt.Fprintf(cs.messagesView, "%s: %s\n", msg.GetSpeaker(), msg.GetText()) fmt.Fprintf(cs.messagesView, "%s: %s\n", msg.GetSpeaker(), msg.GetText())
case proto.ClientMessage_EMOTE:
fmt.Fprintf(cs.messagesView, "%s %s\n", msg.GetSpeaker(), msg.GetText())
default:
fmt.Fprintf(cs.messagesView, "%#v\n", msg)
}
cs.messagesView.ScrollToEnd() cs.messagesView.ScrollToEnd()
}) })
} }

View File

@ -110,32 +110,44 @@ func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Objec
var err error var err error
sid, _ := s.db.SessionIDForAvatar(target) sid, _ := s.db.SessionIDForAvatar(target)
tell := func(_ int, _ string) {} serverAPI := witch.ServerAPI{
Show: func(_ int, _ string) {},
Tell: func(_ int, _ string) {},
}
if sid != "" { if sid != "" {
send := s.msgRouter[sid] send := s.msgRouter[sid]
tell = func(senderID int, msg string) { getSenderName := func(senderID int) *string {
senderName := "a mysterious stranger" senderName := "a mysterious stranger"
sender, err := s.db.GetObjectByID(senderID) sender, err := s.db.GetObjectByID(senderID)
if err == nil { if err == nil {
log.Printf("%#v", sender)
senderName = sender.Data["name"] senderName = sender.Data["name"]
} else { } else {
log.Println(err.Error()) log.Println(err.Error())
} }
return &senderName
}
serverAPI.Show = func(senderID int, msg string) {
cm := proto.ClientMessage{
Type: proto.ClientMessage_EMOTE,
Text: msg,
Speaker: getSenderName(senderID),
}
send(&cm)
}
serverAPI.Tell = func(senderID int, msg string) {
cm := proto.ClientMessage{ cm := proto.ClientMessage{
Type: proto.ClientMessage_OVERHEARD, Type: proto.ClientMessage_OVERHEARD,
Text: msg, Text: msg,
Speaker: &senderName, Speaker: getSenderName(senderID),
} }
send(&cm) send(&cm)
} }
} }
if !ok { if !ok {
sc, err = witch.NewScriptContext(tell) sc, err = witch.NewScriptContext(serverAPI)
if err != nil { if err != nil {
return err return err
} }
@ -161,26 +173,6 @@ func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) {
// TODO // TODO
} }
/*
what's the flow for when i'm at a computer and type /say hi ?
- server gets "SAY hi" from vilmibm
- server gets all objects in earshot (including vilmibm's avatar)
- for each object:
- call whatever handler it has for "hears"
and then that's it, right? over in witch land:
- hears handler for an avatar has:
tellMe(sender.get("name") + " says " + msg)
- tellMe somehow calls a method on the gameWorldServer that can look up a
session ID and thus use the msgRouter to send a message. I'm going to sleep
on this so I can think about the right way to structure those dependencies.
*/
func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error { func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error {
var sid string var sid string
for { for {
@ -220,42 +212,6 @@ func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error
} }
//s.HandleCmd(cmd.Verb, cmd.Rest, avatar) //s.HandleCmd(cmd.Verb, cmd.Rest, avatar)
/*
switch cmd.Verb {
case "say":
if err = s.HandleSay(avatar, cmd.Rest); err != nil {
s.HandleError(func(_ *proto.ClientMessage) error { return nil }, err)
}
default:
msg := &proto.ClientMessage{
Type: proto.ClientMessage_WHISPER,
Text: fmt.Sprintf("unknown verb: %s", cmd.Verb),
}
if err = send(msg); err != nil {
s.HandleError(send, err)
}
}
*/
/*
msg := &proto.ClientMessage{
Type: proto.ClientMessage_OVERHEARD,
Text: fmt.Sprintf("%s sent command %s with args %s",
sid, cmd.Verb, cmd.Rest),
}
speaker := "ECHO"
msg.Speaker = &speaker
err = send(msg)
if err != nil {
log.Printf("failed to send %v to %s: %s", msg, sid, err)
}
*/
} }
} }

View File

@ -184,6 +184,10 @@ func (db *pgDB) createAccount(account *Account) (err error) {
hears(".*", function() hears(".*", function()
tellMe(msg) tellMe(msg)
end) end)
sees(".*", function()
showMe(msg)
end)
`, hasInvocation(av)) `, hasInvocation(av))
stmt = "INSERT INTO objects ( avatar, data, owner, script ) VALUES ( $1, $2, $3, $4 ) RETURNING id" stmt = "INSERT INTO objects ( avatar, data, owner, script ) VALUES ( $1, $2, $3, $4 ) RETURNING id"

View File

@ -9,17 +9,19 @@ import (
func witchHas(l *lua.LState) int { func witchHas(l *lua.LState) int {
lv := l.ToTable(1) lv := l.ToTable(1)
log.Println(lv) log.Println(lv)
// TODO
return 0 return 0
} }
// TODO provides
func witchHears(l *lua.LState) int { func witchHears(l *lua.LState) int {
// TODO register handler return addHandler(l, "say")
handlers := l.GetGlobal("_handlers").(*lua.LTable) }
log.Println(handlers)
pattern := l.ToString(1) func witchSees(l *lua.LState) int {
cb := l.ToFunction(2) log.Println("adding handler for emote")
addHandler(l, "say", pattern, cb) return addHandler(l, "emote")
return 0
} }
func witchDoes(ls *lua.LState) int { func witchDoes(ls *lua.LState) int {
@ -29,27 +31,10 @@ func witchDoes(ls *lua.LState) int {
return 0 return 0
} }
/* func addHandler(l *lua.LState, verb string) int {
string -> fn does not work because there might be multiple handlers for a given verb. pattern := l.ToString(1)
cb := l.ToFunction(2)
i can:
- have a list of handlers. call each one. it is the handler's
responsibility to decide if it's a match or not.
- store string -> map[string]fn. do the matching in Go.
handlers = {
"hear" = {
"*eat*" = cbfn0
"*slurp*" = cbfn1
}
"see" = {
"*fork*" = cbfn2
}
}
*/
func addHandler(l *lua.LState, verb, pattern string, cb *lua.LFunction) int {
handlers := l.GetGlobal("_handlers").(*lua.LTable) handlers := l.GetGlobal("_handlers").(*lua.LTable)
verbHandlers, ok := handlers.RawGetString(verb).(*lua.LTable) verbHandlers, ok := handlers.RawGetString(verb).(*lua.LTable)
@ -58,9 +43,6 @@ func addHandler(l *lua.LState, verb, pattern string, cb *lua.LFunction) int {
handlers.RawSetString(verb, verbHandlers) handlers.RawSetString(verb, verbHandlers)
} }
log.Println("addHandler")
log.Printf("%#v", cb)
verbHandlers.RawSetString(pattern, cb) verbHandlers.RawSetString(pattern, cb)
return 0 return 0

View File

@ -23,6 +23,11 @@ end)
` `
*/ */
type ServerAPI struct {
Tell func(int, string)
Show func(int, string)
}
type VerbContext struct { type VerbContext struct {
Verb string Verb string
Rest string Rest string
@ -33,12 +38,12 @@ type VerbContext struct {
type ScriptContext struct { type ScriptContext struct {
script string script string
incoming chan VerbContext incoming chan VerbContext
tell func(int, string) serverAPI ServerAPI
} }
func NewScriptContext(tell func(int, string)) (*ScriptContext, error) { func NewScriptContext(sAPI ServerAPI) (*ScriptContext, error) {
sc := &ScriptContext{ sc := &ScriptContext{
tell: tell, serverAPI: sAPI,
} }
sc.incoming = make(chan VerbContext) sc.incoming = make(chan VerbContext)
@ -53,6 +58,7 @@ func NewScriptContext(tell func(int, string)) (*ScriptContext, error) {
l = lua.NewState() l = lua.NewState()
l.SetGlobal("has", l.NewFunction(witchHas)) l.SetGlobal("has", l.NewFunction(witchHas))
l.SetGlobal("hears", l.NewFunction(witchHears)) l.SetGlobal("hears", l.NewFunction(witchHears))
l.SetGlobal("sees", l.NewFunction(witchSees))
l.SetGlobal("_handlers", l.NewTable()) l.SetGlobal("_handlers", l.NewTable())
if err := l.DoString(vc.Target.Script); err != nil { if err := l.DoString(vc.Target.Script); err != nil {
log.Printf("error parsing script %s: %s", vc.Target.Script, err.Error()) log.Printf("error parsing script %s: %s", vc.Target.Script, err.Error())
@ -60,17 +66,22 @@ func NewScriptContext(tell func(int, string)) (*ScriptContext, error) {
} }
l.SetGlobal("tellMe", l.NewFunction(func(l *lua.LState) int { l.SetGlobal("tellMe", l.NewFunction(func(l *lua.LState) int {
// TODO not getting senderID properly here
sender := l.GetGlobal("sender").(*lua.LTable) sender := l.GetGlobal("sender").(*lua.LTable)
senderID := int(lua.LVAsNumber(sender.RawGetString("ID"))) senderID := int(lua.LVAsNumber(sender.RawGetString("ID")))
msg := l.ToString(1) sc.serverAPI.Tell(senderID, l.ToString(1))
log.Printf("%#v %s\n", sender, msg) return 0
log.Println(senderID) }))
sc.tell(senderID, msg)
l.SetGlobal("showMe", l.NewFunction(func(l *lua.LState) int {
log.Println("showMe called")
sender := l.GetGlobal("sender").(*lua.LTable)
senderID := int(lua.LVAsNumber(sender.RawGetString("ID")))
sc.serverAPI.Show(senderID, l.ToString(1))
return 0 return 0
})) }))
// TODO check execute permission and bail out potentially // TODO check execute permission and bail out potentially
log.Printf("%#v", vc)
senderT := l.NewTable() senderT := l.NewTable()
senderT.RawSetString("name", lua.LString(vc.Sender.Data["name"])) senderT.RawSetString("name", lua.LString(vc.Sender.Data["name"]))
@ -103,6 +114,5 @@ func NewScriptContext(tell func(int, string)) (*ScriptContext, error) {
} }
func (sc *ScriptContext) Handle(vc VerbContext) { func (sc *ScriptContext) Handle(vc VerbContext) {
log.Printf("%#v %#v", sc, vc)
sc.incoming <- vc sc.incoming <- vc
} }