CC: Tweaked

CC: Tweaked

42M Downloads

Simple state persistence using an event-based structure and global data object.

SirHall opened this issue ยท 1 comments

commented

A year ago almost to the day I opened issue #535 discussing computer state persistence and many topics regarding the problems and difficulties regarding implementing OpenComputers-style state persistence have been raised.
My suggestion is a method for implementing state persistence in a way that is more technically simple, though with a few caveats.

The idea is to utilize two new ideas within scripts, these may be some API that the player may need to subscribe to, or may require a little more elbow grease to get working.

Firstly is to make use of an event-based architecture, in this simple example each tick a on_tick event will be called which must run to completion.
Should this function take too long to complete execution, 1/20th of a second for example, it will be forcefully halted with some flag raised allowing the next event call to notice the halt on the previous tick and ideally allow the user to setup some form of recovery program.

The second component is a form of auto-serialized POD object, perhaps a reference of which is handed through the on_tick event and serialized after each tick (of course for various performance reasons this may not be the case, but should be functionally identical).

When the game is reloaded, the script executed again and the on_tick event called again the serialized data file will be deserialized back into this POD object and sent again to the on_tick object.
This serialized data may either be saved in the in-game computer's filesystem or may be 'hidden behind the scenes'.

A usage example:

example.lua:

persist.subscribe(persist.on_tick,
    function(dat, err)
        if err then
            -- Do something
        end

        -- Perform various calculations
        dat = dat or {field = 0}
        dat.field = dat.field + 1

        if dat.field > 100 then
            -- Initial idea on a simple method to unsubscribe from `on_tick`
            -- To my knowledge 'nil' is returned by default, therefore returning
            -- some value other than that may be a good idea.
            return true
        end
    end
)

Obviously the dat table may only serialize 'simple' data in that for obvious reasons, functions, co-routines, etc will not be serialized.

The mod must wait an appropriate amount of time for this function to run to completion, should it not be able to - dat will remain unmodified and on the next call the err argument will be set to an appropriate error value.
Ideally as an extension it may be optimal to have on_load and on_unload events allowing the program to run special startup and save instructions - though initially these may not be a necessity.

I feel this may be a simpler alternative to full-blown function-state serialization.
I realize there may be the issue that technically the event is called after the above example.lua script's execution has finished, so some out-of-script-execution state may be necessary specifically for this (though I am not aware of the internal workings of this mod).

I'm not aware how viable this alternative implementation suggestion may be, but it is the system I will be attempting to implement in one of my own personal projects and remembered this mod so I felt I should at least suggest it.

I appreciate your time and hope to hear opinions on the viability of this suggestion.

commented

After reading over an (old issues)[https://github.com/dan200/ComputerCraft/issues/503] it would appear Squid has already been suggested something similar to this before. Unfortunately it is not possible to pause chunk unloading and therefore it is possible for the computer to attempt to gather information from peripherals which suddenly no longer exist.

Although I believe the above would still be the best 'easy' method for solving the problem of computer persistence, (if all required information was kept in the data object as shown above) I will be closing this issue as I feel from what I have read that this topic has been done to death, and unfortunately has no 'non-workaround' solution.
Though I will state that the proposed solution above is inspired by the system I've seen Factorio use with it's modding API, which uses a 'global' object table which is serialized when the game exits.

I have been integrating Lua Eris into a project of my own so I may eventually see the difficulty in moving CC over to it. :)

For now however, I am closing this issue.