Noah Petherbridge
c5353df211
Instead of the loadscreen eager-loading ALL level chunks to Go Images, only load the chunks within the "LoadingViewport" - which is the on-screen Viewport plus a margin of chunks off the screen edges. During gameplay, every few ticks, reevaluate which chunks are inside or outside the LoadingViewport; for chunks outside, free their SDL2 textures and free their cached bitmaps to keep overall memory usage down. The AzulianTag-Forest level now stays under 200 Textures at any given time and the loadscreen goes faster as it doesn't have to load every chunk's images up front. The LoadUnloadChunk feature can be turned on/off with feature flags. If disabled the old behavior is restored: loadscreen loads all images and the LoadUnloadChunks function is not run. Other changes: * loadscreen: do not free textures in the Hide() function as this runs on a different goroutine and may break. The 4 wallpaper textures are OK to keep in memory anyway, the loadscreen is reused often! * Free more leaked textures: on the Inventory frame and when an actor calls Self.Destroy() * Stop leaking goroutines in the PubSub feature of the doodad script engine; scripting.Supervisor.Teardown() sends a stop signal to all scripts to clean up neatly. Canvas.Destroy() tears down its scripting supervisor automatically.
105 lines
2.5 KiB
Go
105 lines
2.5 KiB
Go
package scripting
|
|
|
|
import (
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
|
"github.com/dop251/goja"
|
|
)
|
|
|
|
// Message holds data being published from one script VM with information sent
|
|
// to the linked VMs.
|
|
type Message struct {
|
|
Name string
|
|
SenderID string
|
|
Args []goja.Value
|
|
}
|
|
|
|
/*
|
|
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) {
|
|
// Goroutine to watch the VM's inbound channel and invoke Subscribe handlers
|
|
// for any matching messages received.
|
|
go func() {
|
|
// Catch any exceptions raised by the JavaScript VM.
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
// TODO EXCEPTIONS
|
|
log.Error("RegisterPublishHooks(%s): %s", vm.Name, err)
|
|
}
|
|
}()
|
|
|
|
// Watch the Inbound channel for PubSub messages and the stop channel for Teardown.
|
|
for {
|
|
select {
|
|
case <-vm.stop:
|
|
log.Info("JavaScript VM %s stopping PubSub goroutine", vm.Name)
|
|
return
|
|
case msg := <-vm.Inbound:
|
|
vm.muSubscribe.Lock()
|
|
|
|
if _, ok := vm.subscribe[msg.Name]; ok {
|
|
for _, callback := range vm.subscribe[msg.Name] {
|
|
log.Debug("PubSub: %s receives from %s: %s", vm.Name, msg.SenderID, msg.Name)
|
|
if function, ok := goja.AssertFunction(callback); ok {
|
|
function(goja.Undefined(), msg.Args...)
|
|
}
|
|
}
|
|
}
|
|
|
|
vm.muSubscribe.Unlock()
|
|
}
|
|
}
|
|
}()
|
|
|
|
// Register the Message.Subscribe and Message.Publish functions.
|
|
vm.vm.Set("Message", map[string]interface{}{
|
|
"Subscribe": func(name string, callback goja.Value) {
|
|
vm.muSubscribe.Lock()
|
|
defer vm.muSubscribe.Unlock()
|
|
|
|
if _, ok := goja.AssertFunction(callback); !ok {
|
|
log.Error("SUBSCRIBE(%s): callback is not a function", name)
|
|
return
|
|
}
|
|
if _, ok := vm.subscribe[name]; !ok {
|
|
vm.subscribe[name] = []goja.Value{}
|
|
}
|
|
|
|
vm.subscribe[name] = append(vm.subscribe[name], callback)
|
|
},
|
|
|
|
"Publish": func(name string, v ...goja.Value) {
|
|
for _, channel := range vm.Outbound {
|
|
channel <- Message{
|
|
Name: name,
|
|
SenderID: vm.Name,
|
|
Args: v,
|
|
}
|
|
}
|
|
},
|
|
|
|
"Broadcast": func(name string, v ...goja.Value) {
|
|
// Send the message to all actor VMs.
|
|
for _, toVM := range s.scripts {
|
|
if toVM == nil {
|
|
continue
|
|
}
|
|
|
|
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,
|
|
SenderID: vm.Name,
|
|
Args: v,
|
|
}
|
|
}
|
|
},
|
|
})
|
|
}
|