Noah Petherbridge
99eab19c5b
* Implement the pub/sub message passing system that lets the JavaScript VM of one actor (say, a Button) send messages to other linked actors in the level (say, an Electric Door) * Buttons now emit a "power(true)" message while pressed and "power(false)" when released. Sticky Buttons do not release and so do not send the power(false) message. * Electric Doors listen for the "power" event and open or close themselves based on the boolean value received. * If a Sticky Button receives power and is currently pressed down, it will pop back up (reset to "off" position) and notify its linked actors that they have lost power too. So if a Sticky Button held an Electric Door open, and another Button powers the Sticky Button, it would pop back up and also close the Electric Door.
61 lines
1.5 KiB
Go
61 lines
1.5 KiB
Go
package scripting
|
|
|
|
import (
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
|
"github.com/robertkrimen/otto"
|
|
)
|
|
|
|
// Message holds data being published from one script VM with information sent
|
|
// to the linked VMs.
|
|
type Message struct {
|
|
Name string
|
|
Args []interface{}
|
|
}
|
|
|
|
/*
|
|
RegisterPublishHooks adds the pub/sub hooks to a JavaScript VM.
|
|
|
|
This adds the global methods `Message.Subscribe(name, func)` and
|
|
`Message.Publish(name, args)` to the JavaScript VM's scope.
|
|
*/
|
|
func RegisterPublishHooks(vm *VM) {
|
|
// Goroutine to watch the VM's inbound channel and invoke Subscribe handlers
|
|
// for any matching messages received.
|
|
go func() {
|
|
for msg := range vm.Inbound {
|
|
log.Warn("vm: %s msg: %+v", vm.Name, msg)
|
|
if _, ok := vm.subscribe[msg.Name]; ok {
|
|
for _, callback := range vm.subscribe[msg.Name] {
|
|
callback.Call(otto.Value{}, msg.Args...)
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Register the Message.Subscribe and Message.Publish functions.
|
|
vm.vm.Set("Message", map[string]interface{}{
|
|
"Subscribe": func(name string, callback otto.Value) {
|
|
log.Error("SUBSCRIBE: %s", name)
|
|
if !callback.IsFunction() {
|
|
log.Error("SUBSCRIBE(%s): callback is not a function", name)
|
|
return
|
|
}
|
|
if _, ok := vm.subscribe[name]; !ok {
|
|
vm.subscribe[name] = []otto.Value{}
|
|
}
|
|
|
|
vm.subscribe[name] = append(vm.subscribe[name], callback)
|
|
},
|
|
|
|
"Publish": func(name string, v ...interface{}) {
|
|
log.Error("PUBLISH: %s %+v", name, v)
|
|
for _, channel := range vm.Outbound {
|
|
channel <- Message{
|
|
Name: name,
|
|
Args: v,
|
|
}
|
|
}
|
|
},
|
|
})
|
|
}
|