IncludeNotesFromFile.js v1.0.0 - by _neverGiveUp
Introduction
This plugin allows you to load notes or parts of notes from text files.
With IncludeNotesFromFile.js, any tag of the form <include: ____> in the notes field of any game object will be swapped out with the contents of the file data/notes/____.txt. So <include: a> would load a.txt from folder data/notes, <include: b/c> would load c.txt from folder data/notes/b, etc.
The intention here is to effectively allow the construction of load-time mixins with respect to note tag code for other plugins, so as to reduce code duplication across database entries. For instance, if you used this plugin with an enemy traits plugin, you could create prefab'd collections of enemy traits, and mix and match them with just a single note tag (<include: ...>) per collection, rather than copying and pasting them all over the place.
Features
This plugin is an overhaul of Victor Sant's VE_NotesTextFile.js (
https://victorenginescripts.wordpress.com/rpg-maker-mv/notes-text-file/ ). Huge thanks to Victor Sant, of course, for writing the original plugin and giving me something to study and adapt to my own needs.
The distinguishing features of this plugin versus VE_NotesTextFile.js are that IncludeNotesFromFile.js is able to cache loaded text files and perform recursive parsing and loading. By "cache loaded text files" I mean that it will only have to fetch any given data/notes/*.txt a single time during loading, even if it's <include:>'d multiple times, and by "recursive parsing and loading" I mean that files in data/notes can reference other files, e.g. if a note directly contains the tag <include: a> and a.txt contains the tag <include: b>, then b.txt will be loaded, rather than the raw text <include: b> being substituted into the note.
How to Use
The folder data/notes will have to be created and manually populated with any .txt files you want to be able to load into note fields. Other than that, I believe I've adequately described the usage of this plugin under
Introduction. Its feature set is really very small.
One thing I should mention is that this plugin should be placed at or near the top of the list of plugins -- at least before any plugins you want it to be compatible with. The reason is that many plugins parse note tags by overriding database load behavior, and this plugin does as well, but the overrides it provides
modify the note tags, and other plugins need to be able to see those modifications if you want them to see and use the tags contained in your data/notes/*.txt files.
Script
Spoiler JavaScript:
- /*:
- * @plugindesc Note tag text file loader supporting recursive loading.
- * Credit to Victor Sant for his plugin VE_NotesTextFile.js,
- * whose code I studied for this.
- * @author _neverGiveUp
- * @help
- * To ensure that other plugins' DataManager overrides
- * do not procede those defined here,
- * and thus that the note data that other plugins see
- * is that produced by parsing the includes,
- * you should place this plugin at the top of the list.
- *
- * To include a text file in a note tag, use <include: FILENAME>,
- * where FILENAME is a text file in data/notes,
- * without the preceding data/notes or the following .txt.
- *
- * For example: <include: myNote> would include data/notes/myNote.txt.
- *
- * Subdirectories are also supported.
- *
- * For example: <include: myDir/myNote>
- * would include data/notes/myDir/myNote.txt.
- *
- * The distinguishing feature of this plugin versus Victor's implementation
- * is that this plugin supports recursively processing include tags
- * that were loaded in by processing other include tags,
- * thus allowing one note prefab file to include another.
- *
- * You should not abuse this functionality to create recursive include loops
- * or else the game will crash on load.
- */
- (() => {
-
- let INFF = {};
- INFF.Cache = {};
- INFF.Jobs = [];
- INFF.Regex = new RegExp('<include:\\s*(.+)>');
- INFF.Status = {};
- INFF.Status.Parsing = 0;
- INFF.Status.Loading = 1;
- INFF.Status.Done = 2;
- INFF.DEBUG = false;
- INFF.debug = function () {
- if (INFF.DEBUG) {
- console.log(arguments);
- }
- };
-
- let monkeyPatch = function (
- object,
- methodName,
- newImplementation
- ) {
- object[methodName] = newImplementation.bind(
- object, object[methodName].bind(object)
- );
- };
-
- let classMonkeyPatch = function (
- classFunction,
- methodName,
- newImplementation
- ) {
- monkeyPatch(
- classFunction.prototype,
- methodName,
- newImplementation
- );
- }
-
- monkeyPatch(DataManager, 'isDatabaseLoaded', function (old) {
- return INFF.isLoaded() && old();
- });
-
- monkeyPatch(DataManager, 'isMapLoaded', function (old) {
- return INFF.isLoaded() && old();
- });
-
- monkeyPatch(DataManager, 'extractMetadata', function (old, data) {
- if (data.INFF === undefined) {
- INFF.Jobs.push(data);
- data.INFF = {};
- data.INFF.extractMetadata = old.bind(null, data);
- }
- INFF.parseMetadataForIncludes(data);
- });
-
- INFF.parseMetadataForIncludes = function (data) {
- INFF.debug('parsing', data);
- data.INFF.Status = INFF.Status.Parsing;
- let match = INFF.Regex.exec(data.note);
- if (match !== null) {
- INFF.loadIncludeFromFile(match[0], match[1], data);
- }
- if (data.INFF.Status != INFF.Status.Loading) {
- data.INFF.Status = INFF.Status.Done;
- data.INFF.extractMetadata();
- }
- };
-
- INFF.loadIncludeFromFile = function (includeTag, includeName, data) {
- INFF.debug('loading include', includeTag, includeName, data);
- data.INFF.Status = INFF.Status.Loading;
- if (INFF.Cache[includeName]) {
- INFF.replaceIncludeFromCache(includeTag, includeName, data);
- } else {
- let req = new XMLHttpRequest();
- req.open('GET', 'data/notes/' + includeName + '.txt');
- req.onload = function () {
- INFF.Cache[includeName] = req.responseText;
- INFF.replaceIncludeFromCache(includeTag, includeName, data);
- };
- req.onerror = function () {
- throw new Error(
- 'Failed to load data/notes/' + includeName + '.txt'
- );
- };
- req.send();
- }
- };
-
- INFF.replaceIncludeFromCache = function (includeTag, includeName, data) {
- INFF.debug('doing replacement', includeTag, includeName, data);
- data.note = data.note.replace(includeTag, INFF.Cache[includeName]);
- INFF.parseMetadataForIncludes(data);
- };
-
- INFF.isLoaded = function () {
- for (let job of INFF.Jobs) {
- if (job.INFF.Status != INFF.Status.Done) {
- return false;
- }
- }
- return true;
- };
-
- })();
复制代码
Credit and Thanks
To reiterate, big thanks to Victor Sant for his original plugin VE_NotesTextFile.js.
Author's Notes
NOTE: The following features are not yet available.
I am considering expanding this plugin to support a feature I'm tentatively deeming load-time variables (LTV). The game data object format ($dataActors[...], $dataItems[...], etc) would be updated to include a property LTV ($dataActors[_].LTV, $dataItems[_].LTV, etc). Values could be inserted into a data object's LTV by including the note tag <define key=value> which would be equivalent to $dataWhatever[_].LTV[key] = value;, and then whenever the expression $(key) is encountered in the notes, value would be interpolated in its place. A note tag <staticinit></staticinit> would also be provided, which would run arbitrary javascript code while loading the data object, and replace the entire note tag and its contents with whatever is returned from the javascript code if it includes a return statement, or with nothing if there is none. Inside <staticinit>, "this" would refer to the data object, so this.LTV would be the current set of load-time variables, in case there's any need to use them programmatically. In case there's a need to just
define an LTV programmatically, a variant of define would be provided as <define key></define>, which would follow the same rules as staticinit, except instead of replacing the note tag with the return value if there is any, it would set this.LTV[key] to the return value. Includes would be processed prior to staticinits and defines, so that staticinits and defines would be processed even if they are loaded from inside note mixins. Perhaps I'd even make the entire process fully recursive, so that, e.g., staticinits can return include tags that prompt further loading of note mixins.
The intention of this prospective update would be to provide a complete load-time scripting system for programmatically initializing data object notes, and, optionally, for further initializing other data object properties based on those notes in certain trivial ways that one might not think would warrant their own plugins.
本贴来自国际rpgmaker官方论坛作者:_neverGiveUp处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:
https://forums.rpgmakerweb.com/threads/load-notes-or-parts-of-notes-from-text-files-includenotesfromfile-js.135396/