More Editor – An Icy Night In Snowman’s Land

LastĀ  time I talked about the level editor. Today I’m going to talk a bit more about the editor, because I’ve spent a lot of time lately working on it and I need to write down some of this for my own benefit.

The game will be released on Android and HTML5. I’ve been developing on Linux, and I’ve been testing builds for all three targets. Now, the level editor has been “done” for awhile, at least for Android and desktop. Editing, testing in the editor, saving, loading, and everything else was implemented. However, the HTML5 build had an additional challenge.

On the other platforms, saving and loading levels require accessing the local storage of the device and allowing the player to choose a level to load or a location in which to save the level. However, the HTML5 version of the game isn’t running on the player’s device at all. It’s hosted on a webserver that the player will connect to through their web browser, and so it doesn’t make sense (and indeed would be a major security issue) to give players access to files and directories stored on the webserver. To allow the player to save and load levels, it was necessary to transmit data between the webserver and their local machine.

Eventually, I bit the bullet and got down to implementing saving ad loading in the HTML5 editor. I didn’t need anything fancy; from the player’s perspective all I needed was to display a dialog letting the player choose a file to upload and a dialog to save the level file. I thought “That’s easy! Obviously I can’t do anything filesystem-related, but since I’m using (HaxePunk on top of) OpenFL and Lime, and lime.ui.FileDialog exists, this should be pretty straightforward!”

Unfortunately, lime.ui.FileDialog currently doesn’t support loading of files on HTML5. That’s pretty unfortunate, as that’s half of what the level editor needs to do with files. I was at a loss for awhile, until I found these examples of creating a file dialog and invoking it through javascript. Now, I tried these examples in jsfiddle to confirm that they worked, and so I implemented the examples in the game and it worked in all browsers I tested… except Firefox.

Now, Firefox has valid reasons to limit what can happen programmatically. I wasn’t surprised that I ran into a limitation for security reasons; I was surprised that the code only failed to work correctly on one browser (and a non-Microsoft browser at that). In the end, I did manage to get saving and loading on HTML5 working, after being pointed toward open.net.FileReference. If you got here from a search engine and want to know how to make this work, here is the solution that worked for me:

I created an instance of openfl.net.FileReference (called fr in this case), then I added the following code (only compiling it for the HTML5 build):

 
 
  1. private function stageClicked(e:Event)
  2. {
  3. if(isMouseOver(myUIButton))
  4. {
  5. fr.browse();
  6. }
  7. }
  8. private function startLoad(e:Event)
  9. {
  10. fr.load();
  11. }

TheĀ  important thing to note is that fr.browse() is being called in response to a stage click event. This is necessary for the file browser to work; without being called in direct response to user input, it may be blocked for security reasons.

Once the file the user selected has been loaded, you can access the data like so:

 
 
  1. private function loadComplete(e:Event)
  2. {
  3. var data = fr.data.toString();
  4. if(!Levels.isLevelValid(data))
  5. {
  6. //not a valid level
  7. return;
  8. }
  9. //parse the level file
  10. }

The result? Working saving and loading of levels on HTML5!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.