I Need Professional Help With This One!

This 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.


This 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+"'/>");
};

Bump.


I'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.


While it's loading, what do you get if you enter $('body > img'); in your browser's javascript console?


@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.


Not 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.


How would I get at the console in the offline version?


I 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.


Ctrl+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).


When 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.


Just bumping this so KV can find this : )


Just 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 :)


Done! Thank you Cheese!


K.V.

Hello!

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?


When 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.

As 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.


Actually, 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.


$('body > img').length; gives a result of zero.

$('body > img'); gives empty square brackets.


I 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.


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums