GMS 2 Decoding a ds map populated with ds lists not working on existing file

Discussion in 'Programming' started by NimonoSolenze, Jan 13, 2020 at 7:00 PM.

  1. NimonoSolenze

    NimonoSolenze Member

    Joined:
    Jul 25, 2017
    Posts:
    25
    I'm having some trouble with my code. I'm trying to set up some basic configs in a .ini file, things like volume, window size, and most importantly, controls. Since my controls are all arrays, I thought it easiest to transfer them into ds_lists, and then add those ds_lists to a ds_map and encode to json to put them all in the .ini, as I read in the documentation. My code:

    Code:
    var wintrols = ini_open(working_directory + "config.ini");
    var hasControls = true;
    if(!ini_key_exists("settings", "scale"))
    {
       hasControls = false;
       ini_write_real("settings", "scale", 1);
       ini_write_real("settings", "sfx volume", 100);
       ini_write_real("settings", "music volume", 100);
    
       var k_trl = ds_list_create();
       ds_list_add(k_trl, ord("Z")); //A
       ds_list_add(k_trl, ord("X")); //B
       ds_list_add(k_trl, ord("V")); //X
       ds_list_add(k_trl, ord("C")); //Y
       ds_list_add(k_trl, ord("A")); //L
       ds_list_add(k_trl, ord("S")); //R
       ds_list_add(k_trl, vk_up); //Up
       ds_list_add(k_trl, vk_down); //Down
       ds_list_add(k_trl, vk_left); //Left
       ds_list_add(k_trl, vk_right); //Right
       ds_list_add(k_trl, vk_enter); //Pause
    
       var p_trl_padnum = ds_list_create();
       var p_trl_control = ds_list_create();
       var p_trl_dir = ds_list_create();
    
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
       ds_list_add(p_trl_padnum, 4);
    
       ds_list_add(p_trl_control, gp_face2);
       ds_list_add(p_trl_control, gp_face1);
       ds_list_add(p_trl_control, gp_face4);
       ds_list_add(p_trl_control, gp_face3);
       ds_list_add(p_trl_control, gp_shoulderl);
       ds_list_add(p_trl_control, gp_shoulderr);
       ds_list_add(p_trl_control, gp_axislv);
       ds_list_add(p_trl_control, gp_axislv);
       ds_list_add(p_trl_control, gp_axislh);
       ds_list_add(p_trl_control, gp_axislh);
       ds_list_add(p_trl_control, gp_start);
    
       ds_list_add(p_trl_dir, 0);
       ds_list_add(p_trl_dir, 0);
       ds_list_add(p_trl_dir, 0);
       ds_list_add(p_trl_dir, 0);
       ds_list_add(p_trl_dir, 0);
       ds_list_add(p_trl_dir, 0);
       ds_list_add(p_trl_dir, -1);
       ds_list_add(p_trl_dir, 1);
       ds_list_add(p_trl_dir, -1);
       ds_list_add(p_trl_dir, 1);
       ds_list_add(p_trl_dir, 0);
    
       var controls = ds_map_create();
       ds_map_add_list(controls, "padaxis", p_trl_dir);
       ds_map_add_list(controls, "padnum", p_trl_padnum);
       ds_map_add_list(controls, "padbutton", p_trl_control);
       ds_map_add_list(controls, "keyboard", k_trl);
    
       var encode = json_encode(controls);
       ini_write_string("settings", "controls", encode);
       ds_map_destroy(controls);
       ds_list_destroy(k_trl);
       ds_list_destroy(p_trl_padnum);
       ds_list_destroy(p_trl_control);
       ds_list_destroy(p_trl_dir);
    }
    global.scale = ini_read_real("settings", "scale", 1);
    global.sfxvolume = ini_read_real("settings", "sfx volume", 100);
    global.musicvolume = ini_read_real("settings", "music volume", 100);
    
    var ctrls = json_decode(ini_read_string("settings", "controls", ""));
    var p_trls_axis = ds_map_find_value(ctrls, "padaxis");
    var p_trls_num = ds_map_find_value(ctrls, "padnum");
    var k_trls = ds_map_find_value(ctrls, "keyboard");
    var p_trls_button = ds_map_find_value(ctrls, "padbutton");
    
    for(var i = 0; i < 11; i++)
    {
       var pad = global.controls_gamepad[i];
       global.controls_keyboard[i] = ds_list_find_value(k_trls, i);
       pad[0] = ds_list_find_value(p_trls_num, i);
       pad[1] = ds_list_find_value(p_trls_button, i);
       pad[2] = ds_list_find_value(p_trls_axis, i);
       global.controls_gamepad[i] = pad;
    }
    ds_list_destroy(k_trls);
    ds_list_destroy(p_trls_num);
    ds_list_destroy(p_trls_button);
    ds_list_destroy(p_trls_axis);
    ds_map_destroy(ctrls);
    
    ini_close();
    All of this works perfectly... when the .ini doesn't exist. When it's created on ini_close() and I reopen the project, suddenly the only key "ctrls" has is "default", which from what I'm told, is not supposed to happen since the json opened with a ds_map object... Odder still, the value for the key "default" is... {. A curly brace is the value of "default", which makes no sense- isn't that supposed to be the opener of the map?? I've looked up info on this, but I'm finding all the information hard to understand. I'm baffled as to why this code works only on first run without the file present, and breaks when the file exists. The .ini's code:

    Code:
    [settings]
    controls="{ "padaxis": [ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, -1.000000, 1.000000, -1.000000, 1.000000, 0.000000 ], "padnum": [ 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000 ], "keyboard": [ 90.000000, 88.000000, 86.000000, 67.000000, 65.000000, 83.000000, 38.000000, 40.000000, 37.000000, 39.000000, 13.000000 ], "padbutton": [ 32770.000000, 32769.000000, 32772.000000, 32771.000000, 32773.000000, 32774.000000, 32786.000000, 32786.000000, 32785.000000, 32785.000000, 32778.000000 ] }"
    music volume="100.000000"
    sfx volume="100.000000"
    scale="1.000000"
    
    Is it possible it's interpreting the "{ " as the only string in that key despite the space? Maybe I shouldn't be doing this when I don't fully understand what it is I'm doing, but from all other info I can find, this feels like it should work...
     
  2. NimonoSolenze

    NimonoSolenze Member

    Joined:
    Jul 25, 2017
    Posts:
    25
    Quick update: At the recommendation of a friend, I manually removed the first and last quotes from the "controls" key- and now it works perfectly! Adding them back in and storing the result of ini_read_string to a temp variable says the result of the function is literally "{ ", space included- so the ini genuinely cuts off after the second quotation mark.

    So now the question becomes: How on earth do I tell the ini *automatically* to NOT make surround the values in quotation marks, since that's completely screwing up the json store? I want to use a similar system (though not on .ini files) for save data, but 99% of the stuff I want to save is arrays- I can't just tell people "ok when you close the game, make sure to remove the opening and closing quotes around arrays" so the game doesn't break, I need to make it work all on its own without outside input. As it stands right now, with these stupid automatic quotation marks, I'd have to separate everything into its own unique entry, and that's a LOT of data to do that for manually...
     
  3. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,469
    General options:
    - base64_encode/base64_decode
    - string_replace_all the quotes with some magic string (e.g. two regular quotes), then back.
    - A custom INI reader via file_text_ functions (and then you can make it act like you want), though this is a higher effort for result).
     
  4. NimonoSolenze

    NimonoSolenze Member

    Joined:
    Jul 25, 2017
    Posts:
    25
    base64 encoding/decoding didn't work at all- it'd encode, but the decode wouldn't give back the ds_map, only giving "0".
    string_replace_all didn't work, either- same result as before: it says the only entry that exists in the ds_map is "default"...which contains the entire string itself.

    Is there really no way to make the .ini reader/writer not add its own quotes around the entries? Because that's genuinely THE problem here- if it just did not do that, this would be a good method of storing info, but as it is, I genuinely have to separate an array out into multiple entries to make it work, which just seems silly to me when storing arrays is supposed to be possible.
     
  5. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,469
    With both it'd be json_encode -> transformation -> ini_write_string, then ini_read_string -> back transformation -> json_decode. Show write/read code if that doesn't work

    I don't think there is with built-in - I made a custom INI extension few years ago (post) specifically because there were various mishaps that I kept running into.
     
  6. NimonoSolenze

    NimonoSolenze Member

    Joined:
    Jul 25, 2017
    Posts:
    25
    *facepalm* I forgot it said it takes a string, not an object....whoops.

    EDIT: Tested it, that worked!! I'd likely use the text-file functions for save files, where the quotation marks aren't an issue, but this can come in handy still! Thank you so much!
     
    Last edited: Jan 13, 2020 at 11:15 PM

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice