towards exits, provides

trunk
nate smith 2023-04-30 23:19:20 -07:00
parent dd5c377144
commit e86ac5875a
4 changed files with 69 additions and 5 deletions

View File

@ -47,6 +47,26 @@ aside: i want to think through why exits shouldn't be on a room but it's a prett
so i'm going back to the tildemush approach. the next question is; is the exit maps a useful thing? couldn't the go handler just add a second, mirrored go handler? a handler that checks room directionality? so i'm going back to the tildemush approach. the next question is; is the exit maps a useful thing? couldn't the go handler just add a second, mirrored go handler? a handler that checks room directionality?
i've added a WITCH function, goes, which takes a direction and two rooms. this WITCH function adds two `go` verb handlers--one for the direction in the `goes` invocation and then one for the reverse. i like this more than the exit map, but it does mean that exits could compete each other. can't remember if that could happen in tildemush (was the exits map stored per exit? was that guarded?).
i think the competing is fine. i'm actually fine with it. i think that goes() could also add an invocation of `provides()` like this:
```lua
provides("use $this", function(args)
move_sender("target_room")
end)
```
A nice idea is the ability for an exit to add flavor to an entity transitioning through it; for this I can maybe add:
```lua
goesAnd(east, "ossuary", "gallery", function(args)
tellSender("the door squeals harshly as you move it but allows you passage")
end)
```
The movement is still generated.
## server beta ## server beta
- [x] grpc server - [x] grpc server

View File

@ -176,10 +176,7 @@ func (db *pgDB) Ensure() error {
oakDoor = &Object{ oakDoor = &Object{
Data: data, Data: data,
Script: ` Script: `
go("north", function() goes(north, "pub")
tellSender("the heavy door swings forward with ease. It creaks gently")
moveSender("system", "pub")
end)
`, `,
} }
if err = db.CreateObject(sysAcc, oakDoor); err != nil { if err = db.CreateObject(sysAcc, oakDoor); err != nil {

View File

@ -1,6 +1,16 @@
package witch package witch
/*
This file contains the definitions of functions that are injected into scope for WITCH scripts. See witch.go's ScriptContext to see how they are actually added to a LuaState.
TODO: consider making this (or witch.go) a different package entirely. the `witch` prefix for the function names in this file is a little annoying.
*/
import ( import (
"strings"
lua "github.com/yuin/gopher-lua" lua "github.com/yuin/gopher-lua"
) )
@ -9,7 +19,20 @@ func witchHas(l *lua.LState) int {
return 0 return 0
} }
// TODO provides func witchProvides(l *lua.LState) int {
// TODO test this manually
verbAndPattern := l.ToString(1)
l.Pop(1)
split := strings.SplitN(verbAndPattern, " ", 2)
verb := split[0]
pattern := split[1]
l.Push(lua.LString(pattern))
return addPatternHandler(l, verb)
}
func witchHears(l *lua.LState) int { func witchHears(l *lua.LState) int {
return addPatternHandler(l, "say") return addPatternHandler(l, "say")

View File

@ -1,5 +1,11 @@
package witch package witch
/*
This file is the interface between the game server and WITCH execution
*/
import ( import (
"fmt" "fmt"
"log" "log"
@ -127,18 +133,36 @@ func NewScriptContext(db db.DB, getSend func(string) func(*proto.ClientMessage)
// TODO clear this object out of the exits table // TODO clear this object out of the exits table
sc.script = vc.Target.Script sc.script = vc.Target.Script
l = lua.NewState() l = lua.NewState()
// direction constants
l.SetGlobal("east", lua.LString("_DIR_EAST"))
l.SetGlobal("west", lua.LString("_DIR_WEST"))
l.SetGlobal("north", lua.LString("_DIR_NORTH"))
l.SetGlobal("south", lua.LString("_DIR_SOUTH"))
l.SetGlobal("above", lua.LString("_DIR_ABOVE"))
l.SetGlobal("below", lua.LString("_DIR_BELOW"))
l.SetGlobal("up", lua.LString("_DIR_ABOVE"))
l.SetGlobal("down", lua.LString("_DIR_BELOW"))
// witch object behavior functions
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("sees", l.NewFunction(witchSees))
l.SetGlobal("goes", l.NewFunction(witchGoes)) l.SetGlobal("goes", l.NewFunction(witchGoes))
l.SetGlobal("seen", l.NewFunction(witchSeen)) l.SetGlobal("seen", l.NewFunction(witchSeen))
l.SetGlobal("my", l.NewFunction(witchMy)) l.SetGlobal("my", l.NewFunction(witchMy))
l.SetGlobal("provides", l.NewFunction(witchProvides))
// witch helpers
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())
} }
} }
// witch action functions relative to calling context
l.SetGlobal("tellMe", l.NewFunction(func(l *lua.LState) int { l.SetGlobal("tellMe", l.NewFunction(func(l *lua.LState) int {
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")))