Legacy GM Resource addresses [SOLVED]

Simon Gust

Member
I'm in the making of a custom room editor and I've broken my head over how I want to enlist, place and save/load resources (sprites, objects).

I used to save the index of the resource. That plan was bad as if I restructure my resource tree it would swap out sprites. The new plan is to use the name via sprite_get_name and asset_get_index. But that too isn't as save as I want it. If I change the name of a resource my save can be considered corrupted.

Is there some form of address that never changes and I don't have control over?
It's not a big deal but it would be most optimal if there is.
 

CMAllen

Member
As far as I know, there isn't. It's either the resource index or the resource name. All other values are dynamic. That being said, it's not as if the intended values of old name strings aren't known. So it should be easy enough to remap an old, invalid name string to its new one. You just need to code in the exceptions when using those values. Games have to handle these types of conversions all the time as they migrate save files from one game version to the next. Might as well get used to thinking about your file structures and save/load system in that way.
 

NicoFIDI

Member
I have 4 solutions.

1- if the game will have only 1 vertion without updates, don't worry, the onlyone suffering this are the developers until it's released.

2- make vertions, and treat older vertions like if they are corrupted and ignore them

3- make vertions, check if the saved vertion it's older add the scipt scr_vertion_fixer(oldVertion, olddata);
that script will have how to upgrade vertions 1 by 1 until the current

4- make 2 dictionaries.
Code:
spriteToSaveID[? spr_player] = 1; saveIDToSprite[? 1] = spr_player;
And add a line for every saved data. not the best, not the worst. :/
just make sure to keep them together so any update it's focused
 
Last edited:

Simon Gust

Member
As far as I know, there isn't. It's either the resource index or the resource name. All other values are dynamic. That being said, it's not as if the intended values of old name strings aren't known. So it should be easy enough to remap an old, invalid name string to its new one. You just need to code in the exceptions when using those values. Games have to handle these types of conversions all the time as they migrate save files from one game version to the next. Might as well get used to thinking about your file structures and save/load system in that way.
Kinda hard to do. Say I have a sprite name "spr_wall_01", my save file is going to have hundreds of these. Suddenly I change their name to "spr_wall_A", now if I call asset_get_index I get -1 presumably. So I have to tell all created instances that if their asset is -1 set it to the new name. So every save / load cycle I can rename one asset. That is good enough for me. Was that your idea?

I have 2 solutions.

1- if the game will have only 1 vertion without updates, don't worry, the onlyone suffering this are the developers until it's released.
2- if you do plan to make multiple releases then make 2 dictionaries.
Code:
spriteToSaveID[? spr_player] = 1; saveIDToSprite[? 1] = spr_player;
And add a line for every saved data. not the best, not the worst. :/
just make sure to keep them together so any update it's focused
I would have to save both name and index then but if accidentally renamed AND changed the order of assets I would be f***ed anyway.
Double protection is better than single protection but I don't think it's worth the hassle.
 

NicoFIDI

Member
no, the dictionaries are only on runtime, and they exists only when you save and load your data.
inside your game you use spr_player.
but when you save it you save

ini_write_real("player", "sprite", spriteToSaveID[? player.sprite_index]);

and then when you load your player

player.sprite_index = saveIDToSprite[? (ini_read_real("player", "sprite", 0))];

And if you accidentally change the names...
You can't expect the code to know that...
 

CMAllen

Member
Kinda hard to do. Say I have a sprite name "spr_wall_01", my save file is going to have hundreds of these. Suddenly I change their name to "spr_wall_A", now if I call asset_get_index I get -1 presumably. So I have to tell all created instances that if their asset is -1 set it to the new name. So every save / load cycle I can rename one asset. That is good enough for me. Was that your idea?
Before reading in specific values, you check the save file version. This tells your editor which dictionary of string names to use/check specific to that version of the file format. This value is then *parsed* into the new, correct string name for the version of the editor being run. When the editor then saves the file, it uses the new file format version, and the old strings are thus updated to the new string names. This is part and parcel of version control. The only thing you need to do is keep track of which old string names correspond to whatever string names they've been changed to with each version of your editor. If you only ever have a couple versions, it's no big deal. In your example case, when the editor reads in 'spr_wall_01' it checks that against the string dictionary for the file version being read, and changes that string to 'spr_wall_A' instead. The string dictionaries are the key -- they translate one file format version into another one.
 

Gamebot

Member
Game maker addresses for resources are like arrays. You can call them by number. The first sprite is 0, the second 1...works for all other resources too. In code it's like calling them like this. image_index = 0; or object_index = 1; A quick example, in a new project.


I have two sprites:
spr_red
spr_blue

In obj_test:

Create:
Code:
sprite_index = 0;
Space Bar pressed Event:
Code:
sprite_index = 1;
So your object will look like spr_red until you press the space bar which is spr_blue. Calling them in the order they are placed. If your very careful about knowing which sprite goes with what you could actually set up a system, like this. Saving data as numbers. Actually one number in some cases if you can align sprite_index with object_index....Should work but not tested with save files.

EDIT: A system like this takes planning!
 
Last edited:

Simon Gust

Member
Game maker addresses for resources are like arrays. You can call them by number. The first sprite is 0, the second 1...works for all other resources too. In code it's like calling them like this. image_index = 0; or object_index = 1; A quick example, in a new project.


I have two sprites:
spr_red
spr_blue

In obj_test:

Create:
Code:
sprite_index = 0;
Space Bar pressed Event:
Code:
sprite_index = 1;
So your object will look like spr_red until you press the space bar which is spr_blue. Calling them in the order they are placed. If your very careful about knowing which sprite goes with what you could actually set up a system, like this. Saving data as numbers. Actually one number in some cases if you can align sprite_index with object_index....Should work but not tested with save files.

EDIT: A system like this takes planning!
I know it takes planing, this is the 3rd version. I've made my expieriences.
I know that resources are numbered by their order but that was the problem with version 1 and 2.
I used to save spr_red and spr_blue just like that into a save file, where they belong to and on what layer they were.
Now I would order my sprites into subfolders and add several sprites in between. Suddenly I load my old file and all my sprites that used to be spr_blue are now spr_green even though I never placed any spr_greens in my room. The superior method would be saving the asset name as a string. I'm way less likely to change an asset name than to reorder the assets. Using the function asset_get_index gets me the index of the asset
"spr_red" -> 0
"spr_green" -> 1
"spr_blue" -> 2
etc.
 

Gamebot

Member
Well if that doesn't work for your system I would use a ds_map. This is ONLY an outline. You will need a parse or string split script also.

Code:
var save, file, map, inst, inst_map, inst_json;

if (file_exists())
map = file_text_open_write("file.txt"); 

for(i = 0; i < instance_count; i++)
{
inst_map = ds_map_create();
ds_map_add(inst_map, "x", inst.x);
ds_map_add(inst_map, "y", inst.y);
ds_map_add(inst_map, "obj_index", object_index);
ds_map_add(inst_map, "spr_index", sprite_index);
ds_map_add(inst_map, "img_index", image_index);
.
.
inst_json = json_encode(inst_map);

file_text_write_string(map, inst_json);
ds_map_write_string(map, "|");
}
ds_map_destroy(inst_map);
To load:

Code:
var load, string, array, count;

if (file_exists(file.txt))
{
load = file_text_open_read(file.txt);
if (!file_text_eof(file.txt))
{
string  = file_text_open_read_string(file.txt)
array = scr_parse(str, "|", true); //Whatever script you use.
count = array_length_1d(file.txt);
if (count > 0)
{
for(i=0; i < count; i++)
{
var json = array[i];
var decode = json_decode(json);

var _x = ds_map_find_value(decode, "x");
var _y = ds_map_find_value(decode, "y");
var obj = ds_map_find_value(decode, "obj_index");
var spr = ds_map_find_value(decode, "sprite_index");
var img = ds_map_find_value(decode, "image_index");
 
var inst = instance_create(_x, _y, obj);
inst.sprite_index = spr;
inst.image_index = img;
}
}
}
ds_map_destroy(json);
file_text_close(file.txt);
 

CMAllen

Member
That, again, is saving out the resource ID value, which is then dependent on its load order or its position in the resource tree. If those change, the value is no longer correct, and it now maps to a different resource. You can use a resource ID just as easily as strings, so long as you don't just load it and move on. You need to load it and check what version of file is being read so that the old values can be remapped to the new values. It's just that resource names are less likely to be changed than resource IDs.
 

Simon Gust

Member
I doubt that json is even fast enough. There are going to be 30000 tiles on the average and some other data. The asset index is just not a good idea.
I like the remapping idea with file versions much more.
 
Yo my dog. Just don't change your sprite names, lmao. I don't think I've ever changed a resource name in my game once. Don't overthink things too much. It's bad for your health!

My advice as a lazy ****ty developer, lol. ;D
 

Simon Gust

Member
Yo my dog. Just don't change your sprite names, lmao. I don't think I've ever changed a resource name in my game once. Don't overthink things too much. It's bad for your health!

My advice as a lazy ****ty developer, lol. ;D
You sound drunk. I'll take you're advice though, thank you.
I haven't renamed an asset too, it just bugs me that I could screw up something potentially.
 
You sound drunk. I'll take you're advice though, thank you.
I haven't renamed an asset too, it just bugs me that I could screw up something potentially.
Not drunk, just playing the clown for a second, heheh. It *was* serious advice, though. You can spend hours worrying about every little thing that could go wrong with your game, but I think a lot of the time, "perfect is the enemy of good enough." Like you said, you've never renamed an asset, either. Neither have I, after years of working on my game.

I think it's important to focus on things and make them as tight as possible when it's needed, but I think it's also important to be happy letting well enough alone - we only have so much time in the day!

Everyone else was giving you good advice on how to patch up the problem, so I figured it'd be good to have at least one person remind you that "it's okay not to fix it too, if you want," haha! X'D
 

Simon Gust

Member
Not drunk, just playing the clown for a second, heheh. It *was* serious advice, though. You can spend hours worrying about every little thing that could go wrong with your game, but I think a lot of the time, "perfect is the enemy of good enough." Like you said, you've never renamed an asset, either. Neither have I, after years of working on my game.

I think it's important to focus on things and make them as tight as possible when it's needed, but I think it's also important to be happy letting well enough alone - we only have so much time in the day!

Everyone else was giving you good advice on how to patch up the problem, so I figured it'd be good to have at least one person remind you that "it's okay not to fix it too, if you want," haha! X'D
What an inspirational speech you're holding. You're right, good enough should really be good enough. My game has already taken so long and it is taking even longer the better I get. My problem is that the bar for good enough steadily increases. But if I don't stop trying to make it better I'll not finish before I head off for military service.
 

cidwel

Member
kudos for not renaming resources.

Surely you could create a library for binding resources into arrays/variables when the game is launched. I do something similar for mapping my sprite subimages (yeah, I started doing things needlessy complicated). That way you would have a library of resources mapped in names that will not change in a controlled script.

....still think that the best aim is to keep your resources named accordingly a pattern and never change them since their names doesn't have to represent the logic involving them

My problem is that the bar for good enough steadily increases
do not get yourself boxed in, we wanna see your game finished :)
 
Last edited:

Simon Gust

Member
kudos for not renaming resources.

Surely you could create a library for binding resources into arrays/variables when the game is launched. I do something similar for mapping my sprite subimages (yeah, I started doing things needlessy complicated). That way you would have a library of resource names in a controlled script.

....still think that the best aim is to keep your resources named accordingly a pattern and never change them since their names doesn't have to represent the logic involving them

do not get yourself boxed in, we wanna see your game finished :)
I did create a library with assets as an array but only so I could iterate them to present them in the editor. I am still going to save the asset name as a string because what if I managed to change the order of the array or had to insert new assets. Thank you, I too want to see my game finished.
I think I'll flag this topic this topic is solved. There are more important things to discuss like the ds_stack is slower than ds_list issue.
 
Top