Any way to get save infos into variable?

  • Jerehmia
    4th June Member 0 Permalink

    @jacob1 (View Post)

     If you know another solution to create a lua function that returns the json for a given save id then I'm all ears. Expecting scripters with limited programming experience to handle asynchronous http requests in a time-restricted tick function seems more complicated than resuming a 6 line coroutine to me.

     

    I know how coroutines work, I'm trying to explain things as simple as possible. It's rather obvious that the http requests aren't getting blocked when the coroutine is active (in the resumed state) and is blocking the caller, that's why this works.

  • jacob1
    4th June Developer 0 Permalink
    @Jerehmia (View Post)
    I've always felt like coroutines are a pretty advanced topic. Maybe you picked them up quickly and love using them. But I do think it's a more complicated solution to the problem and not something a Lua novice could learn.

    Just as I said in my last message, http request MUST be handled asynchronously. Yes, coroutines are asynchronous. That's how yours is working. In some versions of TPT, doing a while loop that checks req:status in any location (even a coroutine) will freeze the game, so that's why you can't ever wait for the result of a web request in the same function you start it. Maybe test our your script in the web version to see if it freezes for you.

    @z4dg9ssw135 In case you need more detail / examples, here's the documentation on that, see
    evt.register
    and register the
    evt.TICK
    event to check the status in there.
    https://powdertoy.co.uk/Wiki/W/Lua_API:Event.html
  • z4dg9ssw135
    5th June Member 0 Permalink

    @jacob1 (View Post)

    sorry for forgetting the :status(). ive forgot about it.

     

    Ive tried doing it with event.register(event.tick, getjson(*save id*)), but it now says that i did not provide the save id lol.

     

    Current code snippet:

    function getjson(id)
    	local httpreq = http.get("https://powdertoy.co.uk/Browse/View.json?ID="..id)
    	if httpreq:status() == "done" then
    		do return httpreq:finish()
    		end
    		evt.unregister(evt.tick, getjson())
    	end
    end

    rawjson = event.register(evt.tick, getjson(1)) -- expected to get raw json of save 1 in var rawjson, got "bad argument #2 to 'register' (function expected, got no value)" instead

     i dont get why does it think that i gave no value, though i did

    Edited once by z4dg9ssw135. Last: 5th June
  • jacob1
    6th June Developer 0 Permalink
    @z4dg9ssw135 (View Post)
    Remember that making a function getjson is impossible. So, start by renaming it to startgetjson or something. Your evt.tick logic doesn't work because you're in the mindset of trying to handle the tick event during the getjson call, but the tick event will only ever happen outside.

    I took pieces of your code and made this.

    local httpreq = nil
    local function startgetjson(id)
        httpreq = http.get("https://powdertoy.co.uk/Browse/View.json?ID="..id)
    end

    local function tick()
        if httpreq:status() == "done" then
            do something
        end
    end
    event.register(evt.tick, tick)


    Now I don't know how the rest of your script changes, knowing that your script has to be asynchronous. But once you make the change you can figure out how to make it work the new way.
    Edited 2 times by jacob1. Last: 6th June
  • z4dg9ssw135
    6th June Member 0 Permalink

    @jacob1 (View Post)

    oh so it is this easy.

    lol my code is overcomplicated.

  • Jerehmia
    6th June Member 0 Permalink

    No, this isn't easy because a tick function runs once every frame or 60x per second. This means:

    1. Whatever you do in the tick function can't take longer than 1/60 of a second or the system will hang.
    2. You have to make sure that you handle a http request only once after it's done. The tick function provided above handles the same http request 60x per second after it's done.
    Edited 2 times by Jerehmia. Last: 6th June
  • Maticzpl
    6th June Member 1 Permalink

    @Jerehmia (View Post)

    To read the response you use :finish() on the request which changes its status to "dead".
    The request will be handled only once.
    Nothing will hang if your scripts uses too much time either. The game will prompt the user about an unresponsive script after a few seconds in the worst case. That wouldn't happen since the request gets handled once.
    If you are really worried about that one if statement running every tick, you can unregister the tick function after you handled the request which isnt hard to do at all.

  • Jerehmia
    6th June Member 0 Permalink

    @Maticzpl (View Post)

     I'll hand you the dead status, but the tick function will definitely cause trouble if it takes longer than 1/60th of a second even if happens only once, because the next call to tick() will start before the present call to tick() is finished.

    Edited once by Jerehmia. Last: 6th June
  • Maticzpl
    6th June Member 1 Permalink

    @Jerehmia (View Post)

     The entire game waits for lua to finish, so its not a problem

  • jacob1
    6th June Developer 0 Permalink
    @Jerehmia (View Post)
    As @Maticzpl pointed out, the game already waits for Lua. It's single threaded, and Lua is on the single thread just like everything else. If it doesn't hit the 60fps target that's fine. I mean, TPT doesn't hit 60fps on its own half the time anyway.

    You are correct about my tick function being wrong. It was some quick pseudocode. It should set httpreq to nil once it's done using it, and then only check httpreq:status() if httpreq isn't nil. Then it will only run once. Bonus points if you also register and unregister the tick function as needed. A tick function existing won't have any impact on performance if it's doing no work.