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
rest := input
if strings.HasPrefix(input, "/") {
// TODO this is def broken lol
input = input[1:]
parts := strings.SplitN(input, " ", 1)
verb = parts[0]
@ -105,7 +106,14 @@ func (cs *ClientState) AddMessage(msg *proto.ClientMessage) {
// TODO look into using the SetChangedFunc thing.
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.
fmt.Fprintf(cs.messagesView, "%s: %s\n", msg.GetSpeaker(), msg.GetText())
switch msg.Type {
case proto.ClientMessage_OVERHEARD:
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()
})
}

View File

@ -110,32 +110,44 @@ func (s *gameWorldServer) verbHandler(verb, rest string, sender, target db.Objec
var err error
sid, _ := s.db.SessionIDForAvatar(target)
tell := func(_ int, _ string) {}
serverAPI := witch.ServerAPI{
Show: func(_ int, _ string) {},
Tell: func(_ int, _ string) {},
}
if sid != "" {
send := s.msgRouter[sid]
tell = func(senderID int, msg string) {
getSenderName := func(senderID int) *string {
senderName := "a mysterious stranger"
sender, err := s.db.GetObjectByID(senderID)
if err == nil {
log.Printf("%#v", sender)
senderName = sender.Data["name"]
} else {
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{
Type: proto.ClientMessage_OVERHEARD,
Text: msg,
Speaker: &senderName,
Speaker: getSenderName(senderID),
}
send(&cm)
}
}
if !ok {
sc, err = witch.NewScriptContext(tell)
sc, err = witch.NewScriptContext(serverAPI)
if err != nil {
return err
}
@ -161,26 +173,6 @@ func (s *gameWorldServer) HandleCmd(verb, rest string, sender *db.Object) {
// 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 {
var sid string
for {
@ -220,42 +212,6 @@ func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error
}
//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()
tellMe(msg)
end)
sees(".*", function()
showMe(msg)
end)
`, hasInvocation(av))
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 {
lv := l.ToTable(1)
log.Println(lv)
// TODO
return 0
}
// TODO provides
func witchHears(l *lua.LState) int {
// TODO register handler
handlers := l.GetGlobal("_handlers").(*lua.LTable)
log.Println(handlers)
pattern := l.ToString(1)
cb := l.ToFunction(2)
addHandler(l, "say", pattern, cb)
return 0
return addHandler(l, "say")
}
func witchSees(l *lua.LState) int {
log.Println("adding handler for emote")
return addHandler(l, "emote")
}
func witchDoes(ls *lua.LState) int {
@ -29,27 +31,10 @@ func witchDoes(ls *lua.LState) int {
return 0
}
/*
string -> fn does not work because there might be multiple handlers for a given verb.
func addHandler(l *lua.LState, verb string) int {
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)
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)
}
log.Println("addHandler")
log.Printf("%#v", cb)
verbHandlers.RawSetString(pattern, cb)
return 0

View File

@ -23,6 +23,11 @@ end)
`
*/
type ServerAPI struct {
Tell func(int, string)
Show func(int, string)
}
type VerbContext struct {
Verb string
Rest string
@ -31,14 +36,14 @@ type VerbContext struct {
}
type ScriptContext struct {
script string
incoming chan VerbContext
tell func(int, string)
script string
incoming chan VerbContext
serverAPI ServerAPI
}
func NewScriptContext(tell func(int, string)) (*ScriptContext, error) {
func NewScriptContext(sAPI ServerAPI) (*ScriptContext, error) {
sc := &ScriptContext{
tell: tell,
serverAPI: sAPI,
}
sc.incoming = make(chan VerbContext)
@ -53,6 +58,7 @@ func NewScriptContext(tell func(int, string)) (*ScriptContext, error) {
l = lua.NewState()
l.SetGlobal("has", l.NewFunction(witchHas))
l.SetGlobal("hears", l.NewFunction(witchHears))
l.SetGlobal("sees", l.NewFunction(witchSees))
l.SetGlobal("_handlers", l.NewTable())
if err := l.DoString(vc.Target.Script); err != nil {
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 {
// TODO not getting senderID properly here
sender := l.GetGlobal("sender").(*lua.LTable)
senderID := int(lua.LVAsNumber(sender.RawGetString("ID")))
msg := l.ToString(1)
log.Printf("%#v %s\n", sender, msg)
log.Println(senderID)
sc.tell(senderID, msg)
sc.serverAPI.Tell(senderID, l.ToString(1))
return 0
}))
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
}))
// TODO check execute permission and bail out potentially
log.Printf("%#v", vc)
senderT := l.NewTable()
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) {
log.Printf("%#v %#v", sc, vc)
sc.incoming <- vc
}