I Need Professional Help With This One!

Dcoder
06 Oct 2018, 11:58This is the last major issue I'm trying to resolve before uploading my Map Demo 2.0. This involves KV's Grid Image library with accompanying js script, which together display image files for each room on the map.
In short, when restoring a saved game, it takes way too long, depending on how much of the explored map is being restored. If only a quarter of the map has been explored, reloading is pretty fast. If half of the map needs to be reloaded, it takes several seconds. But if the whole map needs to be reloaded, it takes up to a minute and a half! So reloading time is exponential, not linear!
The entire map is about 400 rooms, each with its own grid image. I'm pretty sure that the problem lies in the accumulating image files that have to be reloaded. But because of the exponential reloading time, it's possible that image files are somehow being "cached" unnecessarily -- this was, in fact, an issue that had occurred before that KV tried to fix, but it's possible that he only partially fixed it (I have indicated, under "GridImageLib.js (js script)", the lines of code where he addressed this).
To be sure, I have reduced all of the image file sizes. Strangely, this seems to make no difference in reloading time.
KV's grid image code consists of 2 parts: GridImageLib.aslx (library), and GridImageLib.js (js script). The library also modifies the built-in Grid_DrawRoom function. Loading the grid images starts with calling the SetupGridImages function (located near the bottom of the library), which is done once in the Start tab in a new game, and once in the InitUI tab in a restored game (so only once in either a new or restored game).
GridImageLib.aslx (library)
<library>
<function name="SetGridImgPath" parameters="filename">
JS.setImagePath (GetFileUrl("_FILENAME_"))
</function>
<function name="Grid_DrawRoom" parameters="room, redraw, playerobject"><![CDATA[
if (room.grid_render) {
if (redraw or not Grid_GetRoomBooleanForPlayer(playerobject, room, "grid_isdrawn")) {
if (room.parent <> null) {
Grid_DrawRoom (room.parent, redraw, playerobject)
}
// +++++++++++++++ THE ONLY CHANGES KV MADE TO GRID_DRAWROOM START HERE +++++++++++++++++
gridx = Grid_GetGridCoordinateForPlayer(game.pov, room, "x")
gridy = Grid_GetGridCoordinateForPlayer(game.pov, room, "y")
JS.Grid_DrawBox (gridx, gridy, Grid_GetGridCoordinateForPlayer(game.pov, room, "z"), room.grid_width, room.grid_length, room.grid_border, room.grid_borderwidth, room.grid_fill, room.grid_bordersides)
if (HasString(room, "grid_image")) {
imgfile = false
imgexts = Split(".png;.jpeg;.gif;.jpg;svg",";")
room.imageid = room.name+"-grid-image"
JS.eval ("var roomImageId = '"+room.imageid+"';var gridX = '"+gridx+"';var gridY = '"+gridy+"';var roomGridWidth = '"+room.grid_width+"';var roomGridHeight = '"+room.grid_length+"';customDrawImage('"+room.grid_image+"');")
}
// +++++++++++++++ THE ONLY CHANGES KV MADE TO GRID_DRAWROOM END HERE +++++++++++++++++
if (LengthOf(room.grid_label) > 0) {
label_x = Grid_GetGridCoordinateForPlayer(game.pov, room, "x") + room.grid_width/2.0
label_y = (Grid_GetGridCoordinateForPlayer(game.pov, room, "y") + room.grid_length/2.0) - 0.5
JS.Grid_DrawLabel (label_x, label_y, Grid_GetGridCoordinateForPlayer(game.pov, room, "z"), room.grid_label, room.grid_label_colour)
}
foreach (exit, AllExits()) {
if (exit.grid_render and exit.parent = room and exit.grid_length > 0) {
Grid_DrawLine (Grid_GetGridCoordinateForPlayer(game.pov, exit, "x"), Grid_GetGridCoordinateForPlayer(game.pov, exit, "y"), Grid_GetGridCoordinateForPlayer(game.pov, exit, "end_x"), Grid_GetGridCoordinateForPlayer(game.pov, exit, "end_y"), game.mapexitcolour, game.mapexitwidth)
}
}
Grid_SetRoomBooleanForPlayer (playerobject, room, "grid_isdrawn", true)
}
}
]]></function>
<function name="FinishTurn">
if (HasAttribute(game,"runturnscripts")) {
if (GetBoolean(game,"runturnscripts")) {
if (not GetBoolean(game, "suppressturnscripts")) {
RunTurnScripts
game.runturnscripts = false
}
}
}
else {
if (not GetBoolean(game, "suppressturnscripts")) {
RunTurnScripts
}
}
game.suppressturnscripts = false
UpdateStatusAttributes
CheckDarkness
UpdateObjectLinks
</function>
<function name="AslSet" parameters="data">
//game.suppressturnscripts = true
data = Split(data,"||")
foreach (bit, data) {
stuff = Split(bit,"=")
obj_attr = stuff[0]
obj_attr = Split(obj_attr,".")
if (ListCount(obj_attr)>2){
exclude = obj_attr[ListCount(obj_attr)-1]
obj = Join(ListExclude(obj_attr,exclude),".")
obj_attr = NewStringList()
list add (obj_attr, obj)
list add (obj_attr, exclude)
}
else {
obj = obj_attr[0]
}
obj = GetObject(obj)
attr = obj_attr[1]
val = stuff[1]
if (EndsWith(val,"_toInt")) {
val = ToInt(Replace(val,"_toInt",""))
}
if(LCase(val)="true"){
val = true
}
else if(LCase(val)="false"){
val = false
}
else if (EndsWith(val,"_toDouble")) {
val = ToDouble(Replace(val,"_toDouble",""))
}
set (obj, attr, val)
}
</function>
// +++++++++++++++ THIS IS WHERE THE LOADING OF IMAGE FILES STARTS +++++++++++++++++
<function name="SetupGridImages"><![CDATA[
SetGridImgPath("")
foreach (room, AllObjects()) {
if (HasAttribute(room,"grid_image")) {
JS.eval ("imagesToCheck.push('"+room.grid_image+"');checkImages();")
}
}
]]></function>
<javascript src="GridImageLib.js" />
</library>
GridImageLib.js (js script)
var questImagePath = "";
setImagePath = function(path) {
questImagePath = path;
};
getFileUrlJS = function(filename){
if(filename.indexOf("://") > 0) {
return (filename);
} else {
return questImagePath.replace("_FILENAME_", filename);
}
};
var imagesToCheck = [];
function checkImages(){
imagesToCheck.forEach(function(img){
isFileGood(img)
});
};
var failedImgs = [];
function imgFail(imgFailed){
failedImgs.push(imgFailed.src);
};
// The function below was updated by KV to clear out image elements that were caching and slowing a restored game.
function isFileGood(url){
imgFile = getFileUrlJS(url);
$('body').append("<img style='display:none' onload='$(this).remove();' onerror='imgFail(this);$(this).remove();' src='"+imgFile+"'/>");
};
customDrawImage = function(url){
var imgFile = getFileUrlJS(url);
var failnumber = failedImgs.indexOf(imgFile);
if(failnumber === -1){
ASLEvent('AslSet', roomImageId.replace("-",".").replace("grid-image","grid_image")+"="+imgFile);
gridApi.drawCustomLayerImage(roomImageId, imgFile, parseFloat(gridX), parseFloat(gridY), parseInt(roomGridWidth), parseInt(roomGridHeight));
}
};
So is there anywhere in the code where image files are being inefficiently or unnecessarily "cached", thus increasing reload time?
Other than further reducing the image files, is there any way to make the game reload faster? (I have eliminated most exits in the game and each room is fairly bare bones, so those things should not be issues.)
I can provide all the files for inspection if that helps. Thank you.

Dcoder
07 Oct 2018, 08:51This code near the bottom of GridImageLib.js may be at the crux of the issue:
function isFileGood(url){
imgFile = getFileUrlJS(url);
$('body').append("<img style='display:none' onload='$(this).remove();' onerror='imgFail(this);$(this).remove();' src='"+imgFile+"'/>");
};

Dcoder
12 Oct 2018, 13:21Bump.

CheeseMyBaby
13 Oct 2018, 06:10I'm neither a professional nor one who knows much about the grid.
Hope you'll get help from someone who knows how too!
Looking forward to see what you've accomplished.
mrangel
13 Oct 2018, 11:04While it's loading, what do you get if you enter $('body > img');
in your browser's javascript console?

Dcoder
13 Oct 2018, 13:47@CMB
Thanks for the encouragement. I look forward to seeing your game too.
@MA
Actually, I've only run this demo offline. Haven't even uploaded it yet.
mrangel
13 Oct 2018, 13:51Not sure if you can get at the console in the offline version; but would be interesting to know if the slowdown is within Quest itself, or in the browser.

Dcoder
13 Oct 2018, 14:34How would I get at the console in the offline version?
mrangel
13 Oct 2018, 16:46I haven't tried it, but there's a chance Ctrl+Shift+J or Ctrl+Shift+I might bring up developer tools.
But this could be one of the places where desktop and online behave completely differently, because I believe data between the frontend and backend is synchronised differently.

Dcoder
13 Oct 2018, 21:21Ctrl+Shift+J or I doesn't do anything in-game or in the editor (desktop mode). However, I'm looking at HTML tools in-game to see if I can get a clue about anything (don't understand most of this stuff though).

Dcoder
14 Oct 2018, 04:22When in-game, under the "HTML Tools" menu button, under the "Profiles" tab, there is a radio button set to "Collect Javascript CPU Profile". Near the bottom, I pressed on the "Start" button, which causes a "Profile 1" to be recorded in the background. When you press "Stop", the profile stops recording and you can see any error messages, as well as a table of resource allocations.
So I started a new game in desktop. Before doing any commands, I started a new "Profile 1" recording and then stopped it after several seconds, still without running any commands (just idling). These 2 error messages came up:
Failed to clear temp storage: It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources. SecurityError
Failed to create temp file 2 : It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources.
I restarted the recording again (now in "Profile 2") and moved the player around, running other commands, etc. Then I stopped recording "Profile 2" and looked at the error messages. The only thing added was a repeat of the second error message:
Failed to create temp file 2 : It was determined that certain files are unsafe for access within a Web application, or that too many calls are being made on file resources.
This will continue ad nauseum each time you restart the recording, do stuff, and stop it again; i.e., another copy of the second error message will appear each time. Other than that, there were no other messages.
This sounds pertinent, but I have no idea what, if anything, can be done about it. Any ideas? Thanks.

Dcoder
19 Oct 2018, 11:22Just bumping this so KV can find this : )

CheeseMyBaby
19 Oct 2018, 11:41Just bumping this so KV can find this : )
Send the link to the thread in a PM to him. He's not here as much but he checks in every now and then. That way you can be sure that he don't miss it :)

Dcoder
19 Oct 2018, 12:34Done! Thank you Cheese!

K.V.
20 Oct 2018, 03:22Hello!
When you open the HTML tools click on 'Console', then try mrangel's thing:
While it's loading, what do you get if you enter
$('body > img');
in your browser's javascript console?

Dcoder
20 Oct 2018, 08:14When I was in the HTML Console in-game (offline), I tried the Ctrl-Shift-I and Ctrl-Shift-J thing. Nothing happened. I input $('body > img');
into the HTML Console, but I don't see anything happening (it goes away the next time you open the HTML Console).
As for the javascript console, how do I get to it? I've only been testing this demo offline so far. I can upload it and try it online too if that helps.

K.V.
20 Oct 2018, 14:27As for the javascript console, how do I get to it?
When you open the HTML tools click on 'Console'. Then, you're there.
Nothing happened. I input
$('body > img');
into the HTML Console, but I don't see anything happening (it goes away the next time you open the HTML Console).
I don't know what that's supposed to do. mrangel knows a lot about JS than I do.
If you pasted it into the HTML tools window with the Console tab selected and pressed ENTER, you successfully followed mrangel's instructions.
Ctrl-Shift-I
and Ctrl-Shift-J
only works in a browser. Ctrl+Shift+I
is the equivalent of opening the HTML tools. Ctrl-Shift-J
just opens the JS console in a browser. That has no equivalent in Quest.
To get to the JS console in Quest, we can only open the HTML tools and click on Console.
Oh... I'm rusty...
I think $('body > img');
should show a list of loaded images in the body element.
mrangel
20 Oct 2018, 21:13Actually, my brain must be a little rusty. $('body > img').length;
would probably be more useful (see if it's 0). Or console.log($('body > img'));
if the former gives no output at all.
My intention is basically to see if any of the temporary images used for URL testing have been created; if they're all created at once, they could end up blocking each other due to the browser's maximum concurrent requests. If they don't exist during the slowdown you described, it likely means that the code is running slowly within Quest, before being passed to the browser.

Dcoder
22 Oct 2018, 08:26$('body > img').length;
gives a result of zero.
$('body > img');
gives empty square brackets.
mrangel
22 Oct 2018, 08:55I guess the problem must be on the Quest side then. I'll have to dig into the script and work out what will be run in what order when the save is restored. Unfortunately I'm kind of snowed under with work-related stuff right now, but I'm sure I'll be able to find time sooner or later.