Legacy GM Reading in ds_grid from ini file throws array error?

Nitex

Member
I'm a bit stuck. I'm currently trying to save and pull a ds_grid and a ds_map from an ini file. I save them like so (other code surrounds these):

GML:
ini_open(file_name_text)

ini_write_string("LevelData","RoomGrid",ds_grid_write(global.grid))

ini_write_string("LevelData","RoomMap",ds_map_write(global.map))

ini_close()
And read them like so, function calls formed up straight from the docs:

GML:
ds_grid_read(global.grid, ini_read_string("LevelData","RoomGrid", ""))
ds_map_read(global.map, ini_read_string("LevelData","RoomMap",""))
This is the error:

GML:
trying to index a variable which is not an array
at gml_Script_gl_vector_transform (line 18) - var a = m[0];
stack frame is
gml_Script_gl_vector_transform (line 18)
called from - gml_Script_gl_flathex_world2grid (line 12) - var v = gl_vector_transform(v_raw, map[? "inverse"]);
called from - gml_Script_gl_map_world2grid (line 13) - return gl_flathex_world2grid(map, world_point);
called from - gml_Object_oCursor_DrawEvent_1 (line 6) -     grid_vector = gl_map_world2grid(global.map, gl_mouse_get_position()); //turn mouse pos into hex position
I'm trying to do hexes, and I'm using the grids package but at this point there's not really a file I haven't mucked about with. I was thinking the problem might be the original data type isn't actually a grid or something, but typeof doesn't work I suppose in GMS 1. At any rate, the actual creation of global.grid occurs here:

GML:
var grid = ds_map_create();
var grid_data = ds_grid_create(width, height);
grid[? "grid_data"] = grid_data;
grid[? "bottom_left"] = bottom_left;
grid[? "width"] = width;
grid[? "height"] = height;
grid[? "shape"] = shape;
grid[? "neighbors"] = global.gl_flathex_neighbor_directions;
var principle_directions = ds_list_create();
ds_list_add(principle_directions,
    global.gl_flathex_ne,
    global.gl_flathex_n,
    global.gl_flathex_nw);
grid[? "principles"] = principle_directions;
return grid;
So it does appear to be a grid. Global.map is similarly is a map:

GML:
var map = ds_map_create();

map[? "cell_dimensions"] = cell_dimensions;
map[? "base_transform"] =
    gl_matrix3_create(
        3/4*cx, cy/2, 0,
        0, cy, 0,
        0, 0, 1);

map[? "transform"] = gl_matrix3_identity();
map[? "inverse"] = gl_matrix3_identity();
map[? "type"] = global.gl_gridtype_flathex;

return map;
This is what gets saved to my file:

GML:
[LevelData]
RoomMap="1:696E7665727365:0000000009B69710,1:74797065:4008,1:63656C6C5F64696D656E73696F6E73:0000000009B6A598,1:7472616E73666F726D:0000000009B698A0,1:626173655F7472616E73666F726D:0000000009B6A868"
RoomGrid="590200000A0000000F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E06BF8400000000000000000806CF8400000000000000000206DF8400000000000000000C06DF8400000000000000000606EF8400000000000000000006FF8400000000000000000906FF84000000000000000000070F84000000000000000005070F84000000000000000008070F8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F06BF8400000000000000000906CF8400000000000000000306DF8400000000000000000D06DF8400000000000000000706EF8400000000000000000106FF8400000000000000000A06FF84000000000000000001070F84000000000000000006070F8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000606BF8400000000000000000006CF8400000000000000000A06CF8400000000000000000406DF8400000000000000000E06DF8400000000000000000806EF8400000000000000000206FF8400000000000000000B06FF84000000000000000002070F84000000000000000007070F8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000706BF8400000000000000000106CF8400000000000000000B06CF8400000000000000000506DF8400000000000000000F06DF8400000000000000000906EF8400000000000000000306FF8400000000000000000C06FF84000000000000000003070F8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006BF8400000000000000000806BF8400000000000000000206CF8400000000000000000C06CF8400000000000000000606DF8400000000000000000006EF8400000000000000000A06EF8400000000000000000406FF8400000000000000000D06FF84000000000000000004070F8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000106BF8400000000000000000906BF8400000000000000000306CF8400000000000000000D06CF8400000000000000000706DF8400000000000000000106EF8400000000000000000B06EF8400000000000000000506FF8400000000000000000E06FF8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C06AF8400000000000000000206BF8400000000000000000A06BF8400000000000000000406CF8400000000000000000E06CF8400000000000000000806DF8400000000000000000206EF8400000000000000000C06EF8400000000000000000606FF8400000000000000000F06FF8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D06AF8400000000000000000306BF8400000000000000000B06BF8400000000000000000506CF8400000000000000000F06CF8400000000000000000906DF8400000000000000000306EF8400000000000000000D06EF8400000000000000000706FF8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A06AF8400000000000000000E06AF8400000000000000000406BF8400000000000000000C06BF8400000000000000000606CF8400000000000000000006DF8400000000000000000A06DF8400000000000000000406EF8400000000000000000E06EF8400000000000000000806FF8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B06AF8400000000000000000F06AF8400000000000000000506BF8400000000000000000D06BF8400000000000000000706CF8400000000000000000106DF8400000000000000000B06DF8400000000000000000506EF8400000000000000000F06EF840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
But I honestly have no bloody idea if that's what it's supposed to look like. Google hasn't been a ton of help on this one. Printing what ini_read grabs to the console shows it is indeed getting those monstrous strings, but somehow ds_grid and ds_map aren't actually populating global.grid and global.map with the values they should be?

They're getting read in in a code block in a dialogue event. I'm not sure if that matters or not. They're placed in the file in a left_click event of that same object. Printing global.grid before and after the load just returns 0. Printing global.map before/after returns 1 both times, so that's not helping me. Running:

GML:
print("1 ", gl_grid_get(global.grid, array(1,1)))
Before and after returns the same thing, 100041, so I'm guessing the load isn't working, but I already knew that lol
Is it because the ds_grid has objects in it?

I can't think of what else to add, but if you need more detail I'll toss it in.
 
Last edited:

Nidoking

Member
Did you read the error message that you copied and pasted here?

at gml_Script_gl_vector_transform (line 18) - var a = m[0];
I don't see this script anywhere in your post. So how did you expect anyone to provide an answer?
 

chamaeleon

Member
I would not trust the read and write functions for data structures to do the right thing for embedded data structures, which is only applicable to the json_read() and json_write() functions as far as I know. Outside the that particular scope, I would assume the only thing included in serialization is the data structure id value itself (0, 1, 2, ...), not what it represents as an identifier for a data structure.
 

Nitex

Member
@ chamaeleon:
Ah okay, I should probably then look up how to spit out the guts of a ds_grid and a ds_map, write those to the ini file, and then add them back to the ds_grid and ds_map, I suppose. Do you think I will need to list out the attributes of the objects they hold? I mean essentially, these hold the whole game state, as it's a boardgame effectively, so the objects they've got also have attributes... do I need to also list those out?

@ nidoking:
yeah I read it, but the specific error there has nothing to do with my actual problem - that script functions perfectly with global.grid and global.map before I try to save/load data into them, which I probably should have clarified but I figured was decently apparent from the issue being about the saving and loading, my bad. (As in, I can run my whole game and do everything, except for save/load, which means the problem as I asked is with the save/load code I have tried.)

Since I wrote it, I've also tried this for saving (you don't need to read it line for line, I just swapped to using ds_map_secure_save/load):
Code:
if(mouse_x > bbox_left && mouse_x < bbox_right && mouse_y > bbox_top && mouse_y < bbox_bottom)
{
    if (mouse_check_button_pressed (mb_left)){
        for (i = 0; i < 999; i += 1){
        file_name_text = "saved_level"+"_"+string(i)+".ini"
        if (file_exists(file_name_text)){
            //pass
        }
        else{
            //put the level code in there
            i = 999
            map_drop = ds_map_create()
            ini_open(file_name_text)
            ini_write_real("hello","hello",1)
            ini_close()
            file_name_text = "saved_level"+"_"+string(i)+"_a"+".ini"
            ini_open(file_name_text)
            ds_map_add(map_drop,0,ds_grid_write(global.grid))
            ds_map_secure_save(map_drop,file_name_text)
            ds_map_destroy(map_drop);
            ini_close()
            file_name_text = "saved_level"+"_"+string(i)+"_b"+".ini"
            ini_open(file_name_text)
            ds_map_secure_save(global.map,file_name_text)
            ini_close()
        }
        }
    }
  
}
And this for loading:
Code:
if(ds_map_find_value(async_load, "status") == true){
       if(ds_map_find_value(async_load, "result") != ""){
          global.LevelToGet = ds_map_find_value(async_load, "result");
          file_name_text = "saved_level"+"_"+string(global.LevelToGet)+".ini"
          ini_open(file_name_text)
          global.grid = ds_map_secure_load("saved_level"+"_"+string(global.LevelToGet)+"_a"+".ini")
          ini_close()
          ini_open(file_name_text)
          global.map = ds_map_secure_load("saved_level"+"_"+string(global.LevelToGet)+"_b"+".ini")
          ini_close()       
          }
       }
(And I'm aware that this will right now auto-jump to save file 999, but that's trivial to fix and I'll do it later lol)
But the issue is that even using ds_map_secure_save/load, I still get the same error.

So I will try to put all the ds_grid and ds_map stuff into the file and restore it, but if I have to also write out the attributes of each of those nested objects that might get dicey. I'm surprised that this issue has no stock solution. Do people not often make lists of objects that need to be saved or something?
 

chamaeleon

Member
Do you think I will need to list out the attributes of the objects they hold? I mean essentially, these hold the whole game state, as it's a boardgame effectively, so the objects they've got also have attributes... do I need to also list those out?
If you mean instances when you say objects, you will need to store their attributes explicitly, as they are also just numbers as far as grid and map values are concerned with no inherent meaning. I'd recommend encapsulating the (de)serialization of instances with pairs of read/write scripts that you call for each instance the given script is applicable to.
 
Top