Any way to get save infos into variable?

  • z4dg9ssw135
    24th May Member 1 Permalink

    Hello.

    Is there any way to get infos about save like the name, description, creator nickname, votes amount etc into an array or variable?

    I want to challange myself making a save related script that needs to get these infos.

  • GigaCars
    24th May Member 0 Permalink

    TPT mods like Cracker1000 or Jacob1's mod can show ratings amount on saves, as for name, descriptions and the rest i doubt it, but i'm not a coder so take the opinion with a grain of salt

     

    TLDR: you can try to replicate the vote showing system from the 2 mods i mentioned and try to do the thing with them, but otherwise idk

  • Maticzpl
    24th May Member 0 Permalink

    You can look into the http part of the lua api
    I recommend using the .json endpoints like https://powdertoy.co.uk/Browse/View.json?ID=2198
    You can use smth like this to parse the json and get all the info like that

    Edited 2 times by Maticzpl. Last: 24th May
  • jacob1
    24th May Developer 1 Permalink
    And if you need to know what save is open, you can use
    sim.getSaveID()
    . After that, do what @Maticzpl said.

    Do avoid mass scraping the server. But if you have a script that makes a request whenever a save is opened, that's fine.
  • z4dg9ssw135
    26th May Member 0 Permalink

    Thanks for feedback guys.

    Appreciate yalls help

  • z4dg9ssw135
    29th May Member 0 Permalink

    ...i have got an unexpected problem.

    every time i try to get anything with http.get gives me userdata and i cant use it in any way.

    any idea how do i fix that ?

    edit: i probably didnt understand the article on tpt wiki.

    Edited once by z4dg9ssw135. Last: 29th May
  • jacob1
    29th May Developer 0 Permalink
    It returns an HTTPRequest object. You have to call methods on this object to check when it's done and get the data.

    Very rough code, be sure to not block to check the status (check it in a tick function or something) and check if there were errors before you use data.

    local req = http.get("https://something")
    ...
    if req:status() ~= "running" do
        local data, status = req:finish()
    end
  • z4dg9ssw135
    4th June Member 0 Permalink

    @jacob1 (View Post)

    Using a code like yours for some reason gave me nothing.

    example code snippet (remade from scratch bc deleted in orig script so forgive weird names) :

     

    json = request("scripts/json")

     

    function getusername(saveid)

      request = http.get("https://powdertoy.co.uk/Browse/View.json?ID="..saveid)

      if request == "done" then

        rawjson = request:finish()

        savetable = json.decode(rawjson)

        print(savestable["Username"])

      end

    end

     

    Expected output is the creator's name, but i always get "" printed.

    And after writing print(savestable["username"]) i always get nil (didnt use locals so i could "debug" this way)

     

    Meanwhile, if i use these commands in console one after another it works perfectly:

    saveid = *number*

    request = http.get("https://powdertoy.co.uk/Browse/View.json?ID="..saveid)

    rawjson = request:finish

    savestable = json.decode(rawjson)

    print(savestable["Username"])

     

    I have got no idea what to do lol

    Edited 2 times by z4dg9ssw135. Last: 4th June
  • Jerehmia
    4th June Member 1 Permalink

    You have to wait for the http request to finish somehow. The easiest way would be to use a coroutine (this creates a new execution thread and waits for the thread to finish, the thread itself waits as long as the request is running).

     

    Something like this:

    json = request('scripts/json')
    
    http_waiter = coroutine.create(function(http_request)
    	while true do
    		while http_request:status() == 'running' do end    -- Busy waiting, not ideal
    		http_request = coroutine.yield(http_request)
    	end
    end)
    
    function get_save_json(id)
    	local _, http_request = coroutine.resume(http_waiter, http.get("https://powdertoy.co.uk/Browse/View.json?ID=" .. id))
    	if http_request:status() == 'dead' then
    		error('http request died')
    	end
    	local http_body, http_response_code = http_request:finish()
    	if http_response_code >= 400 then
    		error('http error ' .. http_response_code)
    	end
    	return json.decode(http_body)
    end
    Edited 6 times by Jerehmia. Last: 4th June
  • jacob1
    4th June Developer 1 Permalink
    @z4dg9ssw135 (View Post)
    There's a core detail to understand that should help you fix it. When you start an http request, it takes a while to finish. Lets say 1 second. 1 second sounds short, but it's actually very long for the game to be frozen. Long enough that the only correct way to handle it is to start the request, and check back later if it's done.

    So that means, you can never start a request and use the results in the same function. Your script MUST be asynchronous.

    Try listening on evt.tick and checking every frame if your download finished yet. Also, change
    if request == "done" then
    to
    if request:status() == "done" then
    . Your other function calls look fine, you just need to split it into starting the request and checking it later every frame.

    Addendum: the reason it worked when you wrote it in the console is because enough time passed that the request completed before you entered the 2nd command.

    @Jerehmia (View Post)
    coroutines are overkill and unnecessary here. Please also don't add busy waiting in your coroutines, that negates the purpose of using them. Coroutines are also not the same as threads, there's still only one thread but they swap contexts when one of them has nothing to do.
    (Besides all those issues, I can't check if your coroutine logic is correct or not because it's been years since I actually used them).
    Edited once by jacob1. Last: 4th June