Noah Petherbridge
0518df226c
* The Anvil doodad is affected by gravity and becomes dangerous when falling. If it lands on the player character, you die! If it lands on any other mobile doodad, it destroys it! It can land on solid doodads such as the Electric Trapdoor and the Crumbly Floor. It will activate a Crumbly Floor if it lands on one, and can activate buttons and switches that it passes. * JavaScript API: FailLevel(message) can be called from a doodad to kill the player character. The Anvil does this if it collides with the player while it's been falling.
81 lines
1.9 KiB
Go
81 lines
1.9 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(s *Supervisor, vm *VM) {
|
|
log.Error("RegisterPublishHooks called with %+v %+v", s, 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 {
|
|
vm.muSubscribe.RLock()
|
|
defer vm.muSubscribe.RUnlock()
|
|
|
|
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) {
|
|
vm.muSubscribe.Lock()
|
|
defer vm.muSubscribe.Unlock()
|
|
|
|
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{}) {
|
|
for _, channel := range vm.Outbound {
|
|
channel <- Message{
|
|
Name: name,
|
|
Args: v,
|
|
}
|
|
}
|
|
},
|
|
|
|
"Broadcast": func(name string, v ...interface{}) {
|
|
// Send the message to all actor VMs.
|
|
for _, toVM := range s.scripts {
|
|
if vm.Name == toVM.Name {
|
|
log.Debug("Broadcast(%s): skip to vm '%s' cuz it is the sender", name, toVM.Name)
|
|
continue
|
|
}
|
|
|
|
toVM.Inbound <- Message{
|
|
Name: name,
|
|
Args: v,
|
|
}
|
|
}
|
|
},
|
|
})
|
|
}
|