Astrabit-ST / ModShot-Core

A fork of mkxp, forked for OneShot, forked for OneShot mods, (not to be confused with the ModShot server)
https://nowaffles.com
GNU General Public License v2.0
19 stars 9 forks source link

Add ability to run fiber coroutines in a script command #5

Closed rkevin-arch closed 3 years ago

rkevin-arch commented 3 years ago

With this change, you should be able to invoke fibers as coroutines inside an event. If you have a Script command inside an event page and it evaluates to a fiber, that fiber will be executed to completion before your event page continues running. For now, if the fiber yields, it will resume execution in the next frame. We can add more features like "yield until timeout" or "yield until I/O operation complete" if you want.

Example: Bouncer.rb (inside xScripts.rxdata):

def getWindowPos
    result = ModWindow.GetWindowPosition()
    @x = result[0]
    @y = result[1]
end
def createBounceFiber(length, acceleration)
    return Fiber.new do
        velocity = 0
        while velocity < length
            getWindowPos
            @y += velocity
            velocity += acceleration
            ModWindow.SetWindowPosition(@x, @y)
            Fiber.yield
        end
        while velocity > 0
            getWindowPos
            @y += velocity
            velocity -= acceleration
            ModWindow.SetWindowPosition(@x, @y)
            Fiber.yield
        end
        while velocity > -length
            getWindowPos
            @y += velocity
            velocity -= acceleration
            ModWindow.SetWindowPosition(@x, @y)
            Fiber.yield
        end
        while velocity < 0
            getWindowPos
            @y += velocity
            velocity += acceleration
            ModWindow.SetWindowPosition(@x, @y)
            Fiber.yield
        end
    end
end

Some random parallel processing event:

Text: Before fiber
Script: "createBounceFiber(5, 0.25)"
Text: After fiber

Since createBounceFiber returned a fiber, it will finish executing before "After fiber" is displayed. Each time Fiber.yield is called, the coroutine gives up execution and will resume from there on the next frame. All other events / graphics updates / etc can proceed as normal in the meantime.

(You probably have to merge the changes in the interpreter manually into OSFM-Github, but at least git gives you a diff to show what I changed)