Advertisement
Zalerinian

zAPI - File Tools

Nov 30th, 2015
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*:
  2.  * @plugindesc A wrapper plugin to provide other plugins with easy access to the Filesystem.
  3.  * @author Zalerinian
  4.  * @version 1.0.0
  5.  * @date November 30th, 2015
  6.  *
  7.  * @help
  8.  * ==============================================================================
  9.  *    Support
  10.  * ==============================================================================
  11.  *
  12.  * Have an issue, question, or suggestion? My preferred method of contact would
  13.  * be on the RMW forums, preferably by posting in one of my topics, but if you
  14.  * really need to reach me directly, feel free to PM me, or send me an email
  15.  * using the address below.
  16.  *
  17.  * Author: Zalerinian
  18.  * email: support at razelon.com
  19.  *
  20.  * ==============================================================================
  21.  *    Overview
  22.  * ==============================================================================
  23.  *
  24.  * This plugin is intended as a plugin API to allow plugins to have better access
  25.  * to files. This allows us to check for file/directory existence, as well as
  26.  * save and load files.
  27.  *
  28.  * Many functions work on both local and web/mobile modes, however the save,
  29.  * delete, and create directory functions are not supported for web/mobile by
  30.  * default. The load function will work on web/mobile by sending a request to
  31.  * download the file, NOT by accessing localStorage.
  32.  *
  33.  * Additionally, all functions, aside from the content path functions, have both
  34.  * Synchronous and Asynchronous versions, allowing developers to make their
  35.  * plugins how they want. For performance reasons, asynchronous calls are
  36.  * preferred. To use the synchronous version simply add 'Sync' to the end of a
  37.  * function's name, and omit the callback parameter.
  38.  *
  39.  * Please note: the function parameters in the descriptions below are based on
  40.  * the asynchronous versions of the functions, and thus have a 'callback'
  41.  * parameter. You can ignore this parameter on the synchronous version.
  42.  *
  43.  * Function names in [square braces] are aliases to the function they are with,
  44.  * and may be used to call that function.
  45.  *
  46.  *
  47.  * ==============================================================================
  48.  *    Content Paths
  49.  * ==============================================================================
  50.  *
  51.  * localContentPath()
  52.  * ------------------------------------------------------------------------------
  53.  * This will return the directory that the game is run from. It uses the same
  54.  * method to get the project's path as the default engine.
  55.  *
  56.  * localTempPath()
  57.  * ------------------------------------------------------------------------------
  58.  * This function will return the string "temp/" by default, indicating that the
  59.  * game's temporary content folder is 'temp'. This function can be changed by
  60.  * other plugins to change the temp folder always, or based on specific
  61.  * conditions.
  62.  *
  63.  *
  64.  * ==============================================================================
  65.  *    Existence Functions
  66.  * ==============================================================================
  67.  *
  68.  * [isfile] fileExists(filePath, callback)
  69.  * ------------------------------------------------------------------------------
  70.  * This function will check if the given path exists, and is a file. In web mode,
  71.  * this function uses HTTP HEAD requests to get the file headers for the given
  72.  * path. As this does not specify whether or not the path is a file or directory,
  73.  * it is up to the caller to know or guess as to what it is.
  74.  *
  75.  * [isDirectory] directoryExists(dirPath, callback)
  76.  * ------------------------------------------------------------------------------
  77.  * This function, similar to fileExists, will check if the given path exists and
  78.  * is a directory (folder). In web mode, this is no different than fileExists,
  79.  * because we cannot tell if what we're requesting is a file or folder.
  80.  *
  81.  * [isEmpty] directoryIsEmpty(dirPath, callback)
  82.  * ------------------------------------------------------------------------------
  83.  * This function will check if the given path is an empty directory or not. This
  84.  * will not ensure that the directory exists, meaning that the Synchronous
  85.  * version will throw an error, while the Asynchronous version will pass the
  86.  * error object to the callback.
  87.  *
  88.  *
  89.  * ==============================================================================
  90.  *    Manipulation Functions
  91.  * ==============================================================================
  92.  *
  93.  * saveCompressedFile(filePath, str, callback, suppress)
  94.  * ------------------------------------------------------------------------------
  95.  * This function will save the given data to the given filepath. If the game is
  96.  * not in local move, the async version of the function will send an error to the
  97.  * callback saying "The game is not in local mode.", as we cannot save files
  98.  * without a server backend with unique accounts and folders.
  99.  *
  100.  * Please note that this function only uses LZString's compressToBase64 function.
  101.  * It will not use JsonEx to create a serialized string of an object, and expects
  102.  * the inputted data to already be a string.
  103.  *
  104.  * loadCompressedFile(filePath, encoding, callback, suppress)
  105.  * ------------------------------------------------------------------------------
  106.  * This function will load and decompress the requested file. Please note that
  107.  * the function expects that the files were compressed using LZString's
  108.  * compressToBase64, as this uses decompressFromBase64 to decompress it.
  109.  *
  110.  * This function does have a web mode fallback. Since the files should already be
  111.  * compressed into the game, this function will use a GET request to get the file
  112.  * from the web server, or mobile device, and then use LZString's function to
  113.  * decode the data.
  114.  *
  115.  * [rmdir] removeDirectory(dirPath, callback)
  116.  * ------------------------------------------------------------------------------
  117.  * This function will recursively remove a directory. This means that the
  118.  * directory requested, and any files/directories in it will be gone, with no way
  119.  * to get the data back without specialized data recovery software.
  120.  *
  121.  * [del] removeFile(filePath, callback)
  122.  * ------------------------------------------------------------------------------
  123.  * This function will remove the given file. This will not work on directories.
  124.  * To remove a directory, please use the removeDirectory function instead. This
  125.  * will permanently remove the files from the user's hard drive, not by putting
  126.  * them in the recycling bin. The only way to undo this is to use specialized
  127.  * recovery software, so be sure you really want to delete a file before you do!
  128.  *
  129.  * mkdir(dirPath, mode, callback)
  130.  * ------------------------------------------------------------------------------
  131.  * This function will create the requested directory, if possible. An optional
  132.  * mode parameter allows you to change the directory's permissions on unix-based
  133.  * machines, such as Macs or Linux devices. This has no affect on windows, and
  134.  * defaults to 777 (full permissions for anyone).
  135.  *
  136.  * readDir(dirPath, callback)
  137.  * ------------------------------------------------------------------------------
  138.  * This function will check the given directory and list all the files available
  139.  * in that directory. It will not automatically check sub-folders. This has no
  140.  * web fallback, as there is no reliable way to list the contents of a folder
  141.  * on a remote web server.
  142.  */
  143.  
  144. (function(){
  145.   var Imported = Imported || {};
  146.   if(Imported.MVCommons) {
  147.     var author = [{
  148.       email: "support@razelon.com",
  149.       name: "Zalerinian",
  150.       website: "http://www.razelon.com"
  151.     }];
  152.     PluginManager.register("zAPI - File Tools", "1.0.0", PluginManager.getBasicPlugin("zAPI - File Tools").description, author, "2015-11-30");
  153.   } else {
  154.     Imported["zAPI - File Tools"] = "1.0.0";
  155.   }
  156. })();
  157.  
  158. (function($) {
  159.   "use strict";
  160.  /*
  161.   * $._clearingTemp
  162.   * A flag indicating if the temp folder is still being cleared.
  163.   *
  164.   * $.fs
  165.   * Create a class-wide instance of the File System. It's more efficient than
  166.   * creating it each time we make a call to read or write files.
  167.   */
  168.   $._clearingTemp = false;
  169.   if($.isLocalMode()) {
  170.     $.fs = require('fs');
  171.     $._clearingTemp = true;
  172.   }
  173.  
  174.   /*
  175.    * StorageManager.localContentPath()
  176.    * @note
  177.    * Returns the folder on the computer that the game is running
  178.    * from. While this works on any platform, it only really
  179.    * matters on the desktop clients, as that's where we have access
  180.    * to the filesystem.
  181.    * @return {String} The base filepath for the game.
  182.    */
  183.   $.localContentPath = function() {
  184.     var path = window.location.pathname.replace(/\/[^\/]*$/, '');
  185.     if (path.match(/^\/([A-Z]\:)/)) {
  186.       path = path.slice(1);
  187.     }
  188.     if(path.lastIndexOf("/") !== path.length - 1) {
  189.       path += "/";
  190.     }
  191.     return decodeURIComponent(path);
  192.   }
  193.  
  194.   /*
  195.    * StorageManager.localTempPath()
  196.    * @note
  197.    * Unlike localContentPath, this function does not return the whole
  198.    * path to the temporary folder, just the "temp/" part. The
  199.    * reason for this is that almost every function interally calls
  200.    * localContentPath, so using this to prepend the temp path to a
  201.    * path would cause issues with the game's base path being
  202.    * duplicated in the function.
  203.    * @return {String} A temporary working directory.
  204.    */
  205.   $.localTempPath = function() {
  206.     return "temp/";
  207.   }
  208.  
  209.  
  210.   /*
  211.    * StorageManager.fileExists(filePath, callback)
  212.    * @param {String} The path to check.
  213.    * @param {Function} callback The function that will be called.
  214.    * @note
  215.    * The callback will receive two arguments. If the first is
  216.    * not null, an error has occurred and the data could not be
  217.    * retrieved. If it is null, the second argument will be
  218.    * true if the file exists.
  219.    *
  220.    * This function is aliased as "isFile"
  221.    */
  222.   $.fileExists = function(filePath, callback) {
  223.     if(this.isLocalMode()) {
  224.       this.fs.stat(this.localContentPath() + filePath, function(e, stats) {
  225.         callback.call(this, e, e ? null : stats.isFile());
  226.       });
  227.     } else {
  228.       this.webGetFile(filePath, "HEAD", function(xhr, path, m) {
  229.         if(xhr.status >= 400){
  230.           callback.call(this, new Error(xhr.status + " " + xhr.statusText), false);
  231.         } else {
  232.           callback.call(this, null, xhr.status === 200);
  233.         }
  234.       });
  235.     }
  236.   }
  237.   $.isFile = $.fileExists;
  238.  
  239.   /*
  240.    * StorageManager.fileExistsSync(filePath)
  241.    * @param {String} filePath The path to check.
  242.    * @return {Boolean} Whether or not the path is a file.
  243.    * @note
  244.    * If the node FS object encounters an error, it is not handled
  245.    * here, you must check for errors being thrown.
  246.    *
  247.    * This function will return true if the requested path is a file.
  248.    * When using non-desktop versions of the game, this function will
  249.    * send a HEAD request to the web server/mobile device to get the
  250.    * HTTP headers of the path. This method does not distinguish
  251.    * between files and folders, and will return true as long as the
  252.    * status code returned is 200 (HTTP success code).
  253.    *
  254.    * This function is aliased as "isFileSync".
  255.    */
  256.   $.fileExistsSync = function(filePath) {
  257.     if(this.isLocalMode()) {
  258.       return this.fs.statSync(this.localContentPath() + filePath).isFile();
  259.     } else {
  260.       return this.webGetFileSync(filePath, "HEAD") === 200;
  261.     }
  262.   }
  263.   $.isFileSync = $.fileExistsSync;
  264.  
  265.   /*
  266.    * StorageManager.directoryExists(dirPath, callback)
  267.    * @param {String} dirPath The path to check
  268.    * @param {Function} callback The function to call.
  269.    * @note
  270.    * The callback will get two arguments. If the first is not null,
  271.    * an error has occurred. If it is null, the second will be a boolean
  272.    * indicating whether or not the directory exists.
  273.    *
  274.    * This function is aliased as "isDirectory".
  275.    */
  276.   $.directoryExists = function(dirPath, callback) {
  277.     if(this.isLocalMode()) {
  278.       this.fs.stat(this.localContentPath() + dirPath, function(e, stats) {
  279.         callback.call(this, e, e ? null : stats.isDirectory());
  280.       });
  281.     } else {
  282.       if(dirPath.lastIndexOf("/") !== dirPath.length - 1) {
  283.         dirPath += "/";
  284.       }
  285.       this.webGetFile(dirPath, "HEAD", function(xhr, path, m){
  286.         if(xhr.status >= 400){
  287.           callback.call(this, new Error(xhr.status + " " + xhr.statusText), false);
  288.         } else {
  289.           callback.call(this, null, xhr.status === 200);
  290.         }
  291.       });
  292.     }
  293.   }
  294.   $.isDirectory = $.directoryExists;
  295.  
  296.   /*
  297.    * StorageManager.directoryExistsSync(dirPath)
  298.    * @param {String} dirPath The path to check.
  299.    * @return {Boolean} Whether or not the path is a directory (folder).
  300.    * @note
  301.    * If the node FS object encounters an error, it is not handled
  302.    * here, you must check for errors being thrown.
  303.    *
  304.    * This function will return true if the requested path is a
  305.    * directory. When using non-desktop versions of the game, this
  306.    * function will send a HEAD request to the web server/mobile
  307.    * device to get the HTTP headers of the path. This method does not
  308.    * distinguish between files and folders, and will return true as
  309.    * long as the status code returned is 200 (HTTP success code).
  310.    *
  311.    * This function is aliased as "isDirectorySync"
  312.    */
  313.   $.directoryExistsSync = function(dirPath) {
  314.     if(this.isLocalMode()) {
  315.       return this.fs.statSync(this.localContentPath() + dirPath).isDirectory();
  316.     } else {
  317.       if(dirPath.lastIndexOf("/") !== dirPath.length - 1) {
  318.         dirPath += "/";
  319.       }
  320.       return this.webGetFileSync(dirPath, "HEAD") === 200;
  321.     }
  322.   }
  323.   $.isDirectorySync = $.directoryExistsSync;
  324.  
  325.   /*
  326.    * StorageManager.removeDirectorySync(dirPath)
  327.    * @param {String} dirPath The directory to remove.
  328.    * @return {Boolean} Whether or not the directory was removed.
  329.    * @note
  330.    * In local mode, this function will check if the path exists. If
  331.    * it doesn't, false is returned. The directory is then read and
  332.    * each file is removed. If an entry is a folder, the function
  333.    * recursively calls itself on that directory, so that it may be
  334.    * cleared out. Once a folder is empty, it is removed.
  335.    *
  336.    * In non-desktop mode, this function has no fallback, and simply
  337.    * returns true.
  338.    *
  339.    * This function is aliased as "rmdirSync".
  340.    *
  341.    * This function is adapted from:
  342.    * http://www.geedew.com/remove-a-directory-that-is-not-empty-in-nodejs/
  343.    */
  344.   $.removeDirectorySync = function(dirPath) {
  345.     if(this.isLocalMode()) {
  346.       if( this.fs.existsSync(dirPath) ) {
  347.         this.fs.readdirSync(dirPath).forEach(function(file,index){
  348.           var curPath = dirPath + "/" + file;
  349.           if(this.fs.lstatSync(curPath).isDirectory()) { // recurse
  350.             this.removeDirectorySync(curPath);
  351.           } else { // delete file
  352.             this.fs.unlinkSync(curPath);
  353.           }
  354.         }, this);
  355.         this.fs.rmdirSync(dirPath);
  356.       } else {
  357.         return false;
  358.       }
  359.     }
  360.     return true;
  361.   }
  362.   $.rmdirSync = $.removeDirectorySync;
  363.  
  364.   /*
  365.    * StorageManager.removeDirectory(dirPath, callback)
  366.    * @param {String} dirPath The path to remove.
  367.    * @param {Function} callback The function to call
  368.    * @note
  369.    * This function will asynchronously remove a folder by recusively
  370.    * calling itself on nested folders to clear them out, as trying
  371.    * to remove a non-emtpy directory will throw an ENOTEMPTY error.
  372.    * In order to simplify the funtion, instead of binding all the
  373.    * internal callbacks to 'this' in order to access the class' fs
  374.    * object, a local variable, 'fs', is created as a local reference
  375.    * to the object.
  376.    *
  377.    * This funtion is aliased as "rmdir".
  378.    *
  379.    * This function is adapted from:
  380.    * http://www.geedew.com/remove-a-directory-that-is-not-empty-in-nodejs/
  381.    */
  382.   $.removeDirectory = function(dirPath, callback) {
  383.     if(StorageManager.isLocalMode()) {
  384.       var fs = StorageManager.fs;
  385.       fs.readdir(dirPath, function(err, files) {
  386.         if(err) {
  387.           // Pass the error on to callback
  388.           callback(err, null);
  389.           return;
  390.         }
  391.         var wait = files.length,
  392.           count = 0,
  393.           folderDone = function(err) {
  394.             count++;
  395.             // If we cleaned out all the files, continue
  396.             if( count >= wait || err) {
  397.               fs.rmdir(dirPath,callback);
  398.             }
  399.           };
  400.         // Empty directory to bail early
  401.         if(!wait) {
  402.           folderDone();
  403.           return;
  404.         }
  405.         // Remove one or more trailing slash to keep from doubling up
  406.         dirPath = dirPath.replace(/\/+$/,"");
  407.         files.forEach(function(file) {
  408.           var curPath = dirPath + "/" + file;
  409.           fs.lstat(curPath, function(err, stats) {
  410.             if( err ) {
  411.               callback(err, null);
  412.               return;
  413.             }
  414.             if( stats.isDirectory() ) {
  415.               StorageManager.removeDirectory(curPath, folderDone);
  416.             } else {
  417.               fs.unlink(curPath, folderDone);
  418.             }
  419.           });
  420.         });
  421.       });
  422.     }
  423.   }
  424.   $.rmdir = $.removeDirectory;
  425.  
  426.   /*
  427.    * StorageManager.directoryIsEmpty(dirPath, callback)
  428.    * @param {String} dirPath The file path to check.
  429.    * @param {Function} callback The function to call.
  430.    * @note
  431.    * This function will call the readDir function to get a list of
  432.    * files in a folder. If there is an internal error getting the
  433.    * contents of a folder, the callback is called with the first
  434.    * argument being an error object. If there is no error, the
  435.    * callback's first argument will be null, and the second
  436.    * argument will be a boolean (true/false) indicating if the
  437.    * direcctory is empty or not.
  438.    *
  439.    * This function is aliased as "isEmpty".
  440.    */
  441.   $.directoryIsEmpty = function(dirPath, callback) {
  442.     if(this.isLocalMode()) {
  443.       this.readDir(dirPath, function(e, list) {
  444.         if(e) {
  445.           callback.call(this, e, false);
  446.         } else {
  447.           callback.call(this, null, list.length === 0);
  448.         }
  449.       });
  450.     }
  451.   }
  452.   $.isEmpty = $.directoryIsEmpty;
  453.  
  454.   /*
  455.    * StorageManager.directoryIsEmptySync(dirPath)
  456.    * @param {String} dirPath The file path to check.
  457.    * @param {Function} callback The function to call.
  458.    * @note
  459.    * If in local mode, this function will return true if the given
  460.    * drectory is empty. This internally called readDirSync to get a
  461.    * list of files in the directory, and will return true if the list
  462.    * is empty.
  463.    *
  464.    * This function is aliased as "isEmptySync".
  465.    */
  466.   $.directoryIsEmptySync = function(dirPath) {
  467.     if(this.isLocalMode()) {
  468.       return this.readDirSync(dirPath).length === 0;
  469.     }
  470.   }
  471.   $.isEmptySync = $.directoryIsEmptySync;
  472.  
  473.   /*
  474.    * StorageManager.saveCompressedFile(filePath, str, callback, suppress)
  475.    * @param {String} filePath The path to the file.
  476.    * @param {String} str The data to save.
  477.    * @param {Function} callback The function to call.
  478.    * @param {Array} suppress a list of error codes (Strings) to ignore.
  479.    * @note
  480.    * The callback will receive one argument, which will either be
  481.    * null, or an error.
  482.    * If suppress is supplied, it should be an array of error codes to
  483.    * ignore.
  484.    */
  485.   $.saveCompressedFile = function(filePath, str, callback, suppress) {
  486.     if(this.isLocalMode()) {
  487.       if(!MVC.isArray(suppress)) {
  488.         suppress = [suppress];
  489.       }
  490.       var data = LZString.compressToBase64(str);
  491.       var dirPath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
  492.       this.mkdir(dirPath, function(e){
  493.         if(e && (!suppress || suppress && !suppress.contains(e.code))) {
  494.           throw e;
  495.         }
  496.         this.fs.writeFile(this.localContentPath() + filePath, data, callback);
  497.       }.bind(this));
  498.     } else {
  499.       callback.call(this, new Error("The game is not in local mode."));
  500.     }
  501.   }
  502.  
  503.   /*
  504.    * StorageManager.saveCompressedFileSync(filePath, str, suppress)
  505.    * @param {String} filePath The path to save to.
  506.    * @param {String} str The data to save.
  507.    * @param {Array} suppress a list of error codes (Strings) to ignore.
  508.    * @return {Boolean} Whether or not the file has been saved.
  509.    * @note
  510.    * This function will save the given data to the given filepath
  511.    * after compressing it. This should not be used to serialize
  512.    * as it only uses the base JSON object to convert objects to
  513.    * strings, not the provided JsonEx class.
  514.    *
  515.    * If suppress is supplied, it should be an array of error codes
  516.    * to ignore. Such codes are returned by NodeJS' fs object, such as
  517.    * ENOENT (directory doesn't exist).
  518.    */
  519.   $.saveCompressedFileSync = function(filePath, str, suppress) {
  520.     if(this.isLocalMode()) {
  521.       if(!MVC.isArray(suppress)) {
  522.         suppress = [suppress];
  523.       }
  524.       var data = LZString.compressToBase64(str);
  525.       var dirPath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
  526.       try {
  527.         this.mkdirSync(dirPath);
  528.       } catch(e) {
  529.         if(!(suppress.contains(e.code))){
  530.           throw e;
  531.         }
  532.       }
  533.       fs.writeFileSync(this.localContentPath() + filePath, data);
  534.       return true;
  535.     } else {
  536.       return false;
  537.     }
  538.   }
  539.  
  540.   /*
  541.    * StorageManager.loadCompressedFile(filePath, callback, suppress)
  542.    * @param {String} filePath The path to load.
  543.    * @param {Function} callback The function to call.
  544.    * @param {Array} suppress a list of error codes (Strings) to ignore.
  545.    * @note
  546.    * Local Mode
  547.    * The callback will get 2 arguments, if the first is not null, it
  548.    * is an error object and the second will be null. If the first is
  549.    * not null, then no error occurred and the second argument will
  550.    * contain the decompressed data.
  551.    *
  552.    * Mobile/Web Mode
  553.    * The funciton will request the file from the mobile device/web
  554.    * server. As long as the status code is below 400, the callback
  555.    * will be called with no error, and the response string being
  556.    * decompressed. If there status code is 400 or more, then an
  557.    * error is passed as the first argument to the callback, gotten by
  558.    * combinding the status code and status text. You'll receive
  559.    * messages like 404 Not Found, or 403 Forbidden.
  560.    *
  561.    * If suppress is provided, it should be an array of strings that
  562.    * represent error codes to ignore.
  563.    */
  564.   $.loadCompressedFile = function(filePath, encoding, callback, suppress) {
  565.     if(this.isLocalMode()) {
  566.       if(!MVC.isArray(suppress)) {
  567.         suppress = [suppress];
  568.       }
  569.       this.fs.readFile(this.localContentPath() + filePath, {encoding: encoding || null}, function(e, data){
  570.         if(e && (!suppress || suppress && !suppress.contains(e.code))) {
  571.           callback.call(this, e, null);
  572.           return;
  573.         }
  574.         callback.call(this, null, LZString.decompressFromBase64(data));
  575.       });
  576.     } else {
  577.       this.webGetFile(filePath, "GET", function(xhr){
  578.         if(xhr.status >= 400) {
  579.           callback.call(this, new Error(xhr.status + " " + xhr.statusText), null);
  580.         } else {
  581.           callback.call(this, null, LZString.decompressFromBase64(xhr.responseText));
  582.         }
  583.       });
  584.     }
  585.   }
  586.  
  587.   /*
  588.    * StorageManager.loadCompressedFileSync(filePath, suppress)
  589.    * @param {String} filePath The path to load.
  590.    * @param {Array} suppress a list of error codes (Strings) to ignore.
  591.    * @note
  592.    * The data that we're loading should be a compressed string using
  593.    * LZString's compressToBase64 function.
  594.    * @return {String} The decompressed data.
  595.    */
  596.   $.loadCompressedFileSync = function(filePath, encoding, suppress) {
  597.     if(this.isLocalMode()) {
  598.       if(!MVC.isArray(suppress)) {
  599.         suppress = [suppress];
  600.       }
  601.       try {
  602.         return LZString.decompressFromBase64(this.fs.readFileSync(this.localContentPath() + filePath, {encoding: encoding || null}));
  603.       } catch(e) {
  604.         if(!suppress || suppress && !suppress.contains(e.code)) {
  605.           throw e;
  606.         } else {
  607.           return null;
  608.         }
  609.       }
  610.     } else {
  611.       return LZString.decompressFromBase64(this.webGetFileSync(filePath, "GET"));
  612.     }
  613.   }
  614.  
  615.   /*
  616.    * StorageManager.removeFile(filePath, callback)
  617.    * @param {String} filePath The path to delete.
  618.    * @param {Function} callback The function to call.
  619.    * @note
  620.    * The function will receive one argument. If it is null, the
  621.    * function succeeded. If not, the argument is an error object.
  622.    *
  623.    * This funciton is aliased as "del".
  624.    */
  625.   $.removeFile = function(filePath, callback) {
  626.     if(this.isLocalMode()) {
  627.       this.fs.unlink(this.localContentPath() + filePath, callback);
  628.     }
  629.   }
  630.   $.del = $.removeFile;
  631.  
  632.   /*
  633.    * StorageManager.removeFileSync(filePath)
  634.    * @param {String} filePath The path to delete.
  635.    * @return {Boolean} Whether or not the file has been removed.
  636.    * @note
  637.    * If the path does not exist, or the path is not a file, an error
  638.    * will be thrown.
  639.    *
  640.    * This function is aliased as "delSync".
  641.    */
  642.   $.removeFileSync = function(filePath) {
  643.     if(this.isLocalMode()) {
  644.       this.fs.unlinkSync(this.localContentPath() + filePath);
  645.     }
  646.     return true;
  647.   }
  648.   $.delSync = $.removeFileSync;
  649.  
  650.   /*
  651.    * StorageManager.mkdirSync(dirPath, mode)
  652.    * @param {String} dirPath The folder to create.
  653.    * @param {Number} mode The unix permission number to create the folder with. This has no affect on Windows.
  654.    * @note
  655.    * Synchronously creates the requested directory. If there is an
  656.    * error creating the directory, it will be thrown.
  657.    *
  658.    * 511 is the decimal equivalent to Octal 777, used for unix
  659.    * permissions.
  660.    *
  661.    * @return {Boolean} Returns true.
  662.    */
  663.   $.mkdirSync = function(dirPath, mode) {
  664.     if(this.isLocalMode()) {
  665.       this.fs.mkdirSync(this.localContentPath() + dirPath, mode || 511);
  666.     }
  667.     return true;
  668.   }
  669.  
  670.   /*
  671.    * StorageManager.mkdir(dirPath, mode, callback)
  672.    * @param {String} dirPath The folder to create.
  673.    * @param {Number} mode The unix permission number to create the folder with. This has no affect on Windows.
  674.    * @param {Function} callback The function to call.
  675.    * @note
  676.    * Asynchronously creates the requested directory. If there is an
  677.    * error creating the directory, it will be passed as an argument
  678.    * to the callback.
  679.    *
  680.    * 511 is the decimal equivalent to Octal 777, used for unix
  681.    * permissions.
  682.    *
  683.    * @return {Boolean} Returns true.
  684.    */
  685.   $.mkdir = function(dirPath, mode, callback) {
  686.     if(this.isLocalMode()) {
  687.       this.fs.mkdir(this.localContentPath() + dirPath, mode || 511, callback);
  688.     }
  689.   }
  690.  
  691.   /*
  692.    * StorageManager.readDir(dirPath, callback)
  693.    * @param {String} dirPath The directory path to read.
  694.    * @param {Function} callback The function to call.
  695.    * @note
  696.    * Calls the callback function with receive two arguments. If there
  697.    * was an error reading the directory, the first argument will be
  698.    * and error object, and the second will be invalid. If the first
  699.    * argument is null, the second will be a list of files, excluding
  700.    * the '.' and '..' special directories.
  701.    */
  702.   $.readDir = function(dirPath, callback) {
  703.     if(this.isLocalMode()) {
  704.       this.fs.readdir(this.localContentPath() + dirPath, callback);
  705.     }
  706.   }
  707.  
  708.   /*
  709.    * StorageManager.readDirSync(dirPath)
  710.    * @param {String} dirPath The directory path to read.
  711.    * @note
  712.    * Returns a list of files, excluding the '.' and '..' special
  713.    * directories. If there is an error reading the requested
  714.    * directory, it will be thrown.
  715.    */
  716.   $.readDirSync = function(dirPath) {
  717.     if(this.isLocalMode()) {
  718.       return this.fs.readdirSync(this.localContentPath() + dirPath);
  719.     }
  720.   }
  721.  
  722.   /*
  723.    * StorageManager.webGetFileSync(filePath, method)
  724.    * @param {String} filePath The path to request from.
  725.    * @param {String} method The HTTP method to use. Defaults to "GET"
  726.    * @note
  727.    * Requests the filepath from the web server or mobile device. This
  728.    * is used to determine if files exist for the existance functions,
  729.    * and the loadCompressedFile functions.
  730.    * @return The status code, if the method is HEAD, or a string if the method is GET.
  731.    */
  732.   $.webGetFileSync = function(filePath, method) {
  733.     var xhr = new XMLHttpRequest();
  734.     xhr.open(method || 'GET', filePath, false);
  735.     if (xhr.overrideMimeType) {
  736.       xhr.overrideMimeType("application/json");
  737.     }
  738.     xhr.send();
  739.     if(method.toLowerCase() === "head") {
  740.       return xhr.status;
  741.     } else {
  742.       if(xhr.status >= 400){
  743.         return xhr.status + " " + xhr.statusText;
  744.       }
  745.       return xhr.responseText;
  746.     }
  747.   }
  748.  
  749.   /*
  750.    * StorageManager.webGetFile(filePath, method, onLoad, onError)
  751.    * @param {String} filePath The path to request from.
  752.    * @param {String} method The HTTP method to use. Defaults to "GET"
  753.    * @param {Function} onLoad The function to call when the data is done loading.
  754.    * @param {Function} onError The function to call when there was an error loading.
  755.    * @note
  756.    * Requests the filepath from the web server or mobile device. This
  757.    * is used to determine if files exist for the existance functions,
  758.    * and the loadCompressedFile functions.
  759.    */
  760.   $.webGetFile = function(filePath, method, onLoad, onError){
  761.     var xhr = new XMLHttpRequest();
  762.     xhr.open(method || 'GET', filePath);
  763.     if (xhr.overrideMimeType) {
  764.       xhr.overrideMimeType("application/json");
  765.     }
  766.     xhr.onload = function() {
  767.       onLoad.call(this, xhr, filePath, method);
  768.     };
  769.     xhr.onerror = onError;
  770.     xhr.send();
  771.   }
  772.  
  773.   // Clears the temp folder on startup. The call is async so as to
  774.   // not increase the game's startup time.
  775.   // This deletes and then recreates the temp folder so that plugins
  776.   // may use it during the game's run.
  777.   StorageManager.rmdir(StorageManager.localContentPath() + "temp", function(e, list) {
  778.     if(e && e.code !== "ENOENT") {
  779.       throw e;
  780.     } else {
  781.       StorageManager.mkdir(StorageManager.localTempPath(), function(e) {
  782.         if(e) {
  783.           throw e;
  784.         }
  785.         StorageManager._clearingTemp = false;
  786.       })
  787.     }
  788.   });
  789.  
  790.   /*
  791.    * End StorageManager wrapper
  792.    */
  793. })(StorageManager);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement