$dataMap changes when opening&closing menu?

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
I made some changed to the $dataMap. I then open&close the menu (or anything that causes a SceneManager.push(..)). restores the GameMap to it's default $mapData. But I do not understand where or why this happens... A scene is pushed onto the SceneManager-stack, you do some stuff, then it get's popped and all of a sudden my $dataMap is the original one again instead of the one I modified.

I understand that this happens when I transfer between maps. But... this is weird. Where does this happen and how can I prevent it? I can't locate the code that does this.
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
863
First Language
German
Primarily Uses
There can only be 1 active scene at a time, so when you open the menu, the old Scene_Map instance gets destroyed and a new one gets created when you close it.

Scene_Map.create contains this line:

Code:
DataManager.loadMapData(mapId);
which causes the DataManager to load the map file and (re)initialize $dataMap.
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
Thank you once again.

I thought the (scenes&dataMaps) were kept intact. At least in my experience that is what you usually do in games. A scene needs to be paused so you no longer call it's update&render methods and then you update&render another scene instead. After you're done you destroy the current scene and return to the previous scene on the stack. Because it would normally make sense to keep inactive scenes intact so stuff doesn't have to be recreated upon returning. But for some reason RPG Maker chose not to.

But it makes sense because they are global and the way most variables in RPG Maker MV (and ACE) seem to have been created is that they only allow a single instance at a time. Meh.... :(

But thanks now I know where it happens and I can work around this. Hope I did it properly though, but it works:

var alias_silv_mapgen_Scene_Map_create = Scene_Map.prototype.create;Scene_Map.prototype.create = function(){ if (Silv.MapGen.StoredMapData.lastGeneratedMap !== null) { Scene_Base.prototype.create.call(this); this._transfer = $gamePlayer.isTransferring(); var mapId = this._transfer ? $gamePlayer.newMapId() : $gameMap.mapId(); $dataMap = Silv.MapGen.StoredMapData.lastGeneratedMap; // This line is sadly required. } else { alias_silv_mapgen_Scene_Map_create.call(this); }};var alias_silv_mapgen_Scene_Map_isReady = Scene_Map.prototype.isReady;Scene_Map.prototype.isReady = function(){    if (Silv.MapGen.StoredMapData.lastGeneratedMap !== null)    {        this.onMapLoaded();        this._mapLoaded = true;        return true;    }    else    {        return alias_silv_mapgen_Scene_Map_isReady.call(this);    }};
I hope they just completely change the RPG Maker code for the next version (after MV). It seems they try to keep the original RPG Maker code intact to make upgrading scripts from one maker to another easy and to keep things similar. But they also keep the limitations. Some of the code just isn't ideal.
 
Last edited by a moderator:

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,100
Reaction score
13,705
First Language
English
Primarily Uses
RMMV
In Ace there was no $dataMap - all that info was part of the $game_map object.  And I don't think it did get destroyed when you went to the menu - at least it didn't run the setup method on returning from a menu.

I was working on something the other day that gave me the impression MV does it a little differently.  Maybe it's just because $dataMap is its own entity now (but I still don't see why it'd be rebuilt unless you're changing maps).  If you had NPC events moving around, do they also get reset to their original positions when you come back from the menu?
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
And I don't think it did get destroyed when you went to the menu
I did not literally get 'destroyed', the reference was simply replaced with a new one so unless my plugin has a backup to the current $dataMap, it is collected by the GC and thus destroyed :/. This explains the (very) short game-freeze after closing the menu on super large maps (by default it reloads the entire map when returning from the menu...).

Anyway I added a global variable which contains a reference to the old $dataMap to make it persist through other scenes like the menu. It fixes the problem. But it all feels a bit weird.

Maybe RM should just check if the map-id changed instead of just reloading all of it's data.

Actually, I did notice that events are not destroyed, only the $gameMap.data (and maybe a few others) is reloaded.

If you had NPC events moving around, do they also get reset to their original positions when you come back from the menu?
NPC events and events that walk randomly around all remain correctly in place.

But I'm not sure if the code from my previous post is correct. Maybe instead of

$dataMap = Silv.MapGen.StoredMapData.lastGeneratedMap;I should just write:

$dataMap.data = Silv.MapGen.StoredMapData.lastGeneratedMap.data;Because that is the only thing that changed (I think... not sure). It doesn't seem to cause any problems after changing the code to this.
 
Last edited by a moderator:

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,100
Reaction score
13,705
First Language
English
Primarily Uses
RMMV
$dataMap is a global variable, so it should not be GC.
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
It will when $dataMap is completely overwritten by the DataManager with a new object. The old object will be GC-ed.

$dataMap = {x:'some object'};$dataMap = 0; // reference to {x:'some object'}; is now lost and can now be GC-ed unless another variable has a reference to it.
Scene_Map.create contains this line:

DataManager.loadMapData(mapId);
which causes the DataManager to load the map file and (re)initialize $dataMap.
That is the problem and causes the original data to be GC-ed in the default RM code. I do not thing there is another variable referencing this and the test-results sadly clearly show me that at least a part of the data is lost when returning from the menu. But not all of it.

There are some things in RM that I completely do not understand and this is one of 'em. Why did they implement it like this... I don't understand the reasoning.
 
Last edited by a moderator:

DarknessFalls

Rpg Maker Jesus - JS Dev.
Veteran
Joined
Jun 7, 2013
Messages
1,393
Reaction score
210
First Language
English
thats because the map is refreshed every time, its a scene and all scenes are refreshed
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
thats because the map is refreshed every time, its a scene and all scenes are refreshed
This is not true.

This has nothing to do with the map being a scene and saying that all scenes get refreshed. The data is in $dataMap, NOT in Scene_Base. On top of that Scene_Base does do nothing to this variable in any way and does not use the DataManager at all. Only Scene_Map does, which makes sense. What does NOT make sense is that Scene_Map blindly overwrites some of the data in $dataMap even when the map did not change at all. Even causing 'slowdowns'.

This is particularly annoying when working with generated maps @runtime. I have a slight feeling that this is another 'issue' with the default RM code. Maybe there is a good reason behind this code but I can't think of one right now.
 
Last edited by a moderator:

DarknessFalls

Rpg Maker Jesus - JS Dev.
Veteran
Joined
Jun 7, 2013
Messages
1,393
Reaction score
210
First Language
English
This is not true.

This has nothing to do with the map being a scene and saying that all scenes get refreshed. The data is in $dataMap, NOT in Scene_Base. On top of that Scene_Base does do nothing to this variable in any way and does not use the DataManager at all. Only Scene_Map does, which makes sense. What does NOT make sense is that Scene_Map blindly overwrites some of the data in $dataMap even when the map did not change at all. Even causing 'slowdowns'.

This is particularly annoying when working with generated maps @runtime. I have a slight feeling that this is another 'issue' with the default RM code. Maybe there is a good reason behind this code but I can't think of one right now.
the scene is redrawn, the data in the map information is refetched. Generated maps would work in MV from what I have seen because each time the Scene_Map is refreshed the data for the map is re fetched from some where - I assume the cache. Data is not over written if you are currently on the map. 

Every time you push a scene to the stack or transfer the map, when you do manage to go back to the map the data is fetched either from the cache or from the json file.
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
There is no cache and the $dataMap is completely overwritten but the Game_Map is only partially refreshed.

Let's retrace the steps RM MV takes when returning to the map again after closing the menu:

Scene_Map.prototype.create = function() { Scene_Base.prototype.create.call(this); this._transfer = $gamePlayer.isTransferring(); var mapId = this._transfer ? $gamePlayer.newMapId() : $gameMap.mapId(); DataManager.loadMapData(mapId); // <<<<<<<<<<<<<<<<<<<<<<<<};DataManager.loadMapData = function(mapId) { if (mapId > 0) { var filename = 'Map%1.json'.format(mapId.padZero(3)); this.loadDataFile('$dataMap', filename); // <<<<<<<<<<<<<<<<<<<<<<<< } else { this.makeEmptyMap(); }};DataManager.loadDataFile = function(name, src) { var xhr = new XMLHttpRequest(); var url = 'data/' + src; xhr.open('GET', url); xhr.overrideMimeType('application/json'); xhr.onload = function() { if (xhr.status < 400) { window[name] = JSON.parse(xhr.responseText); // <<<<<<<<<<<<<<<<<<<<<<<< Overwrites $dataMap completely. The old object will most likely be GC-ed unless you referenced it yourself. DataManager.onLoad(window[name]); } }; xhr.onerror = function() { DataManager._errorUrl = DataManager._errorUrl || url; }; window[name] = null; xhr.send();};Also this is called again:

Scene_Map.prototype.createDisplayObjects = function() {    this.createSpriteset(); // Wait... Even a whole new spriteset is created?    this.createMapNameWindow();    this.createWindowLayer();    this.createAllWindows();};Judging from the above code, I might have alias my minimap plugin also wrong, I aliased the Game_Map.setup instead of Scene_Map.createDisplayObjects. But the setup is not called when the map is (partially) recreated. So this may affect more plugins.

// This line of code is NOT called, which is (I think) the reason the events and such don't lose their position.// Events are reloaded in the $dataMap but this new data is not actually pushed onto the old Game_Map instance.// This causes a difference between the $dataMap and the actual data on the map...Game_Map.prototype.setup()
The whole $dataMap is completely overwritten (there is no cache that I could find). And because RM skips the Game_Map.prototype.setup() the events only work because they are simply not refreshed from the $mapData. They are still from the old Game_Map instance that simply never refreshed this part of the data. But by overwriting the $mapData there could not be a 'desynch'/difference between the $mapData and the actual events and such on the map.

This would also mean that if you change anything in the spriteset, you must manually cache this (like I did with $dataMap.data) because otherwise the menus will reset it all.

There are so many things wrong with this. I do not understand why they did this:

- Scripters will now have to manually cache their data, If multiple scripts do this, you end up with a lot of duplicate caching.

- $mapData no longer matches the actual (non-tile)-data on the map, not even with default RM code. Everyone can imagine why this is extremely bad.

- It's very confusing.

- It's not efficient. Loading the entire $dataMap from disk every time you return from a menu or such will cause hiccups for bigger and more complex maps. It does already for me in fact.
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
863
First Language
German
Primarily Uses
If you generate maps, you'll need to cache them under their map id, anyway, because otherwise you would recreate them, when the player transfers to a new map and back. It's not like cacking uses up a lot of memory, because the map will exist anyway, either in the cache or directly in $dataMap.
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
This also explains why they had to decrease max-map-size in MV. The engine would already run into performance problems lol.

Reloading it from disk every time. Even though most $dataMaps are around 50-150kb for me, some are nearly 1MB already. If you run an old 5000RPM ATA disk, good luck with opening&closing menus on big&complex maps... Because it will 'lag'.

But hey I got it to work. I hope RM changes their internal code at some point though because this is just bad and will cause problems. They should have used a cache and store it per map based on map-id indeed. But it seems they removed the Cache entirely from MV because I can't find it anywhere and I don't see anything being cached (aside from images).
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
863
First Language
German
Primarily Uses
If you aren't creating maps on the fly, you have absolutely no business tampering with $dataMap at all, since it's meant to be read-only. And having multiple plugins creating random maps at the same time makes no sense, since those are incompatible by default.
 
Last edited by a moderator:

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
I already have 2 scripts that 'tamper' with it. There are more reasons to tamper with it besides just random map generation. And even if not, the default RM-code alone is enough to 'lag'. And even if that wouldn't be the case, this RM-code is just beyond bad/ugly and then reducing max map-size (at least if this was one of the reasons, aside from higher resolutions) then that is another extremely ugly restriction&workaround for bad code. And even if that would not be the case, 'desynching' $dataMap from the actual data can't be good and makes no sense.

So many reasons. I'm once more disappointed in the default RM MV code :( .
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
863
First Language
German
Primarily Uses
The $data(...) objects contain static data, that's the same for all game runs and doesn't get saved with the save file. Their $game(...) counterparts may change and do get saved, so there's a clear reason for the split.

Your plugin is trying to tamper with the very basics of the game engine, so you shouldn't be surprised, that MV doesn't cater to your needs ;)

Besides, tell me your reasons for dealing with the $data objects. I'm sure there's a better solution for most cases.
 
Last edited by a moderator:

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
Your plugin is trying to tamper with the very basics of the game engine, so you shouldn't be surprised, that MV doesn't cater to your needs ;)
Okay fair point.

But still I think it's 'dirty code' and inefficient :p .

My reasons are random map generation, replacement of regions with objects, random enemy spawning, stuff like that. Hell I even place treasure chests on pseudo-random locations with loot based on party-level. Basically adding more variety to maps.
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
863
First Language
German
Primarily Uses
But why would you need $dataMap just for spawning a few events (for example), when you could do this with $gameMap just fine? Or region ids, there are methods available to iterate over all tiles and getting their region ids, so you could simply use these.
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
424
Reaction score
171
First Language
Dutch
Primarily Uses
RMMV
Nevermind we are miscommunicating. Forget about it. I know when to use the $dataMap.data and when to just clone events to the map based on region-id.

But sometimes one must use the actual tiledata (and change it). Like when fixing auto-tiles, closing off tunnels, stuff like that. It can be dynamically done through cloning events but that is even more dirty and costs more performance.

Just assume that for some cases there is no way around it, I have to use&alter the $dataMap.
 
Last edited by a moderator:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

"You can thank my later", "But you haven't done anything", "Well, that's why ..."
Are we allowed to post about non-RPG Maker games?
I should realize that error was produced by a outdated version of MZ so that's why it pop up like that
Ami
i can't wait to drink some ice after struggling with my illness in 9 days. 9 days is really bad for me,i can't focus with my shop and even can't do something with my project
How many hours have you got in mz so far?

Forum statistics

Threads
105,884
Messages
1,017,242
Members
137,609
Latest member
shododdydoddy
Top