Iavra

Iavra Note Files

Nov 12th, 2015 (edited)
370
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*:
  2.  * @plugindesc Allows to store notetags in text files and reference them from database objects and events.
  3.  * <Iavra Note Files>
  4.  * @author Iavra
  5.  *
  6.  * @param File Path
  7.  * @desc Path of the file to load. Multiple files can be specified when separated by commas. Default: data/notes.json
  8.  * @default data/notes.json
  9.  *
  10.  * @param Notetag
  11.  * @desc Tag used to load metadata from files. Default: textnote
  12.  * @default textnote
  13.  *
  14.  * @help
  15.  * Note: This plugin has to be placed below everything else that deals with DataManager.extractMetadata().
  16.  *
  17.  * Create one or more files and store their locations inside the "File Path" parameter, separated by comma. The
  18.  * files are formatted like this:
  19.  *
  20.  * {
  21.  *     "key1" : "some notes",
  22.  *     "key2" : "some more notes",
  23.  *     "key3" : [
  24.  *         "notes with",
  25.  *         "linebreaks"
  26.  *     ]
  27.  * }
  28.  *
  29.  * JSON itself doesn't allow real linebreaks inside Strings, but you can use an array, instead, which will automatically
  30.  * be converted to a single String with linebreaks.
  31.  *
  32.  * Inside your database objects and events, you can reference these entries like this:
  33.  *
  34.  * <textnote key1>
  35.  *
  36.  * If "textnote" is already in use by another plugin or you want to use a different notetag, you can change it
  37.  * with the "Notetag" plugin parameter".
  38.  */
  39.  
  40. var Imported = Imported || {};
  41. Imported.iavra_note_files = true;
  42.  
  43. //=============================================================================
  44. // namespace IAVRA
  45. //=============================================================================
  46.  
  47. var IAVRA = IAVRA || {};
  48.  
  49. (function() {
  50.     "use strict";
  51.    
  52.     /**
  53.      * Load plugin parameters. We don't use the PluginManager to be independent from our file name.
  54.      */
  55.     var _params = $plugins.filter(function(p) { return p.description.contains('<Iavra Note Files>'); })[0].parameters;
  56.    
  57.     /**
  58.      * All files to be loaded. We use an object for two reasons. 1) It automatically eliminates duplicate entries. 2) We
  59.      * need a way to keep track of all files that have already been loaded.
  60.      */
  61.     var _files = _params['File Path'].split(/\s*,\s*/).reduce(function(map, file) {
  62.         !file || (map[file] = false); return map;
  63.     }, {});
  64.    
  65.     /**
  66.      * The notetag, that should be replaced with the loaded data.
  67.      */
  68.     var _regex = new RegExp('<[ ]*' + _params['Notetag'] + '[ ]+(.+?)[ ]*>', 'g');
  69.    
  70.     /**
  71.      * Holds the content of all loaded files.
  72.      */
  73.     var _data = {};
  74.    
  75.     /**
  76.      * Holds all callbacks to be executed, once the plugin has finished loading files.
  77.      */
  78.     var _listeners = [];
  79.    
  80.     /**
  81.      * If any file isn't loaded yet, this returns false. Otherwise it returns true. We do this by testing if any file has
  82.      * not yet finished loading and returning the inverse of it, since Array.some could be faster than Array.every for a
  83.      * lot of files, since it only has to run until it encounters the first unloaded file and not all of them.
  84.      */
  85.     var isReady = function() {
  86.         return !Object.keys(_files).some(function(key) { return !_files[key]; });
  87.     };
  88.    
  89.     /**
  90.      * Async loads a file, while keeping trace of all files not yet loaded and merges the contained JSON objects in
  91.      * a single data variable to allow for easy access. When a file gets loaded, we test if we are done loading and execute
  92.      * all listeners that have been registered in the meantime.
  93.      */
  94.     var loadFile = function(file) {
  95.         var xhr = new XMLHttpRequest();
  96.         xhr.open('GET', file);
  97.         xhr.overrideMimeType('application/json');
  98.         xhr.onload = function() {
  99.             _files[file] = true;
  100.             var result = JSON.parse(xhr.responseText);
  101.             for(var key in result) {
  102.                 _data[key] = Array.isArray(result[key]) ? result[key].join('\n') : result[key];
  103.             };
  104.             if(isReady()) {
  105.                 while (_listeners.length > 0) {
  106.                     var listener = _listeners.shift();
  107.                     listener();
  108.                 }
  109.             };
  110.         };
  111.         xhr.onerror = function() { throw new Error("There was an error loading the file '" + file + "'."); };
  112.         xhr.send();
  113.     };
  114.    
  115.     /**
  116.      * Since our note files start loading at the same time game data is loaded, we need to somehow make it stop
  117.      * processing, until we are done. We do this be adding a loadListener, which is executed after we are done. This
  118.      * also means, that this plugin has to be placed below everything else that aliases DataManager.extractMetadata.
  119.      */
  120.     var addLoadListener = function(callback) {
  121.         isReady() ? callback() : _listeners.push(callback);
  122.     };
  123.    
  124.     /**
  125.      * Recursively replaces all occurrences of our own notetag with the loaded data. Make sure to not have cyclic
  126.      * references or this will cause your game to crash.
  127.      */
  128.     var replace = function(note) {
  129.         if(_regex.test(note)) {
  130.             return replace(note.replace(_regex, function(match, key) { return _data[key] || ''; }));
  131.         }
  132.         return note;
  133.     };
  134.    
  135.     //=============================================================================
  136.     // module DataManager
  137.     //=============================================================================
  138.    
  139.     (function($) {
  140.        
  141.         /**
  142.          * We start loading our text files, when everything else is being loaded.
  143.          */
  144.         var _alias_loadDatabase = $.loadDatabase;
  145.         $.loadDatabase = function() {
  146.             for(var file in _files) { loadFile(file); };
  147.             _alias_loadDatabase.call(this);
  148.         };
  149.        
  150.         /**
  151.          * This function would originally been called the moment a data entry is loaded. However, since we have to wait until
  152.          * our own files are loaded, we register a callback, instead. This also means, that this plugin has to be listed after
  153.          * everything else that deals with DataManager.extractMetadata.
  154.          */
  155.         var _alias_extractMetadata = $.extractMetadata;
  156.         $.extractMetadata = function(data) {
  157.             addLoadListener(callback.bind(this, data));
  158.         };
  159.        
  160.         /**
  161.          * Callback to be executed, once all notetags have been loaded.
  162.          */
  163.         var callback = function(data) {
  164.             data.note = replace(data.note);
  165.             _alias_extractMetadata.call(this, data);
  166.         };
  167.        
  168.     })(DataManager);
  169.    
  170. })();
RAW Paste Data