mako
Member
Hi, guys!
First post here, though I've learned a LOT from the forums since the Gamemaker 7.0 days. (Ah, youth...)
Anyway, I'm working on a small MMO in Gamemaker Studio 2.0 (please, no "network games are crap in Gamemaker" comments, I've read them all and am just having fun with my hobby).
I'm pretty experienced with GML (no D&D since my first try 10+ years ago) but I ran into a really weird issue with a FOR loop and ds_lists in GML 2.0. I already figured out a work around, but I still don't know WHY the workaround works and I'd like to find out. Hopefully someone here will have already seen this and be able to point out which particular stupid mistake I've been making.
So, I'm tracking objects with "collision_rectangle_list" and sorting through the list, comparing it to a previous list, then finding any new objects that weren't on the previous one.
Now, this all looked, good, compiled with NO ERRORS, and the server started fine. (I forgot to mention, this is on the server-side, but is isolated from the server/client network matrix, so the issue doesn't come from that end of things.) Once a client connects, this code is called, but after that the code runs with no inputs. It's just the call that is networked.
As soon as this code ran... the game would hang. It wouldn't throw an error. It would just hang. So, out came the trusty debug tool and... RAM usage is skyrocketing. Normal server-side RAM usage with two connected clients is 2.95 MB of RAM, peaking at 3MB of RAM. Once this code is put into the loop, the RAM usage would climb at a rate of 1MB per second, up until something crashed or I closed the game.
Now, my assumption was that I had a memory leak somewhere, but I checked that exhaustively. No leak that I could see.
I wondered if maybe checking the ds_list without putting values in them first might be causing an issue. That shouldn't cause an issue, because an empty list would just return "undefined" (which it did, during testing, several times and ways) or throw an error, but who knows?
Nope, that wasn't the problem. Filling the lists with random values did nothing.
Finally, after several coding sessions, I had this:
If you didn't catch it... the ONLY difference is that instead of writing the stop value in the FOR loops as "i < ds_list_size(currentList)-1" and "i<ds_list_size(pastList)-1" to account for the difference between "ds_list_size" returning the length (ie, a quantity of 3 contained values) and the ds_list being numbered from 0 (ie, indexes 0, 1, 2), I wrote it them as "i < ds_list_size(currentList)" and "i<ds_list_size(pastList)". That's exactly what you would do if you were using an array, right? Which I've done many times in previous versions of GML, but ds_lists have a couple of useful features that I like using in this context.
Now (if my understanding is correct), my code is now checking for ds_list indexes "0", "1", "2" and an non-existing "3" (which being nonexistent, just returns "undefined") and is perfectly happy with that. The RAM usage stays right at 3MB and never stutters and the game runs as expected. What... the... heck... is... this? Black MAGIC!!! Or maybe I'm just misunderstanding something fundamental here....?
My game is working, none the wiser, but my brain is now lying awake at night, haunted by the thought that my understanding of the GML has been founded on a lie....
Someone help me....
EDIT: This code isn't copy/paste from the IDE, it's handwritten to the forum, so there may be some mistakes in argument #s or such. Please trust me; it wasn't a typo or something simple like that: Studio would have put up a stink in the error reporting if that was the case.
First post here, though I've learned a LOT from the forums since the Gamemaker 7.0 days. (Ah, youth...)
Anyway, I'm working on a small MMO in Gamemaker Studio 2.0 (please, no "network games are crap in Gamemaker" comments, I've read them all and am just having fun with my hobby).
I'm pretty experienced with GML (no D&D since my first try 10+ years ago) but I ran into a really weird issue with a FOR loop and ds_lists in GML 2.0. I already figured out a work around, but I still don't know WHY the workaround works and I'd like to find out. Hopefully someone here will have already seen this and be able to point out which particular stupid mistake I've been making.
So, I'm tracking objects with "collision_rectangle_list" and sorting through the list, comparing it to a previous list, then finding any new objects that weren't on the previous one.
GML:
//in creation event
currentList = ds_list_create();
pastList = ds_list_create();
updateList = ds_list_create();
//in alarm[0], runs every 30 steps
//check for objects in player area
collision_rectangle_list(x-500, y-500, x+500, y+500, otherPlayerObject, true, currentList, false);
for (i=0; i < (ds_list_size(currentList))-1; i++))
{
var currentUnit = ds_list_find_value(currentList, i);
var inList = false;
for (i=0; i < (ds_list_size(pastList))-1; i ++))
{
if currentUnit == ds_list_find_value(pastList, i)
{
inList = true;
break;
}
}
If inList == true
{
ds_list_add(updateList, currentUnit);
}
}
ds_list_copy(pastList, currentList);
ds_list_clear(currentList);
//do useful stuff with updateList, then...
ds_list_clear(currentList);
As soon as this code ran... the game would hang. It wouldn't throw an error. It would just hang. So, out came the trusty debug tool and... RAM usage is skyrocketing. Normal server-side RAM usage with two connected clients is 2.95 MB of RAM, peaking at 3MB of RAM. Once this code is put into the loop, the RAM usage would climb at a rate of 1MB per second, up until something crashed or I closed the game.
Now, my assumption was that I had a memory leak somewhere, but I checked that exhaustively. No leak that I could see.
I wondered if maybe checking the ds_list without putting values in them first might be causing an issue. That shouldn't cause an issue, because an empty list would just return "undefined" (which it did, during testing, several times and ways) or throw an error, but who knows?
Nope, that wasn't the problem. Filling the lists with random values did nothing.
Finally, after several coding sessions, I had this:
GML:
//in creation event
currentList = ds_list_create();
pastList = ds_list_create();
updateList = ds_list_create();
//in alarm[0], runs every 30 steps
//check for objects in player area
collision_rectangle_list(x-500, y-500, x+500, y+500, otherPlayerObject, true, currentList, false);
for (i=0; i < (ds_list_size(currentList)); i++))
{
var currentUnit = ds_list_find_value(currentList, i);
var inList = false;
for (i=0; i = (ds_list_size(pastList)); i ++))
{
if currentUnit = ds_list_find_value(pastList, i)
{
inList = true;
break;
}
}
If inList == true
{
ds_list_add(updateList, currentUnit);
}
}
ds_list_copy(pastList, currentList);
ds_list_clear(currentList);
//do useful stuff with updateList, then...
ds_list_clear(currentList);
Now (if my understanding is correct), my code is now checking for ds_list indexes "0", "1", "2" and an non-existing "3" (which being nonexistent, just returns "undefined") and is perfectly happy with that. The RAM usage stays right at 3MB and never stutters and the game runs as expected. What... the... heck... is... this? Black MAGIC!!! Or maybe I'm just misunderstanding something fundamental here....?
My game is working, none the wiser, but my brain is now lying awake at night, haunted by the thought that my understanding of the GML has been founded on a lie....
Someone help me....
EDIT: This code isn't copy/paste from the IDE, it's handwritten to the forum, so there may be some mistakes in argument #s or such. Please trust me; it wasn't a typo or something simple like that: Studio would have put up a stink in the error reporting if that was the case.
Last edited: