mirror of
https://github.com/photonstorm/phaser
synced 2024-11-10 23:24:41 +00:00
Working through new plugin structure
This commit is contained in:
parent
ade37dd35e
commit
0a46c13f4c
4 changed files with 192 additions and 116 deletions
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
* Optimized TextureTintPipeline.drawBlitter so it skips bobs that have alpha of zero and only calls `setTexture2D` if the bob sourceIndex has changed, previously it called it for every single bob.
|
* Optimized TextureTintPipeline.drawBlitter so it skips bobs that have alpha of zero and only calls `setTexture2D` if the bob sourceIndex has changed, previously it called it for every single bob.
|
||||||
* Game.context used to be undefined if running in WebGL. It is now set to be the `WebGLRenderingContext` during WebGLRenderer.init. If you provided your own custom context, it is set to this instead.
|
* Game.context used to be undefined if running in WebGL. It is now set to be the `WebGLRenderingContext` during WebGLRenderer.init. If you provided your own custom context, it is set to this instead.
|
||||||
|
* Game.onStepCallback has been removed.
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
|
@ -447,39 +447,25 @@ var Config = new Class({
|
||||||
|
|
||||||
// Plugins
|
// Plugins
|
||||||
|
|
||||||
/**
|
|
||||||
* @const {any} Phaser.Boot.Config#defaultPlugins - The plugins installed into every Scene (in addition to CoreScene and Global).
|
|
||||||
*/
|
|
||||||
this.defaultPlugins = Plugins.DefaultScene;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @const {any} Phaser.Boot.Config#installPlugins - [description]
|
|
||||||
*/
|
|
||||||
this.installPlugins = { global: [], scene: [], files: [] };
|
|
||||||
|
|
||||||
var plugins = GetValue(config, 'plugins', null);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allows `plugins` property to either be an array, in which case it just replaces
|
* Allows `plugins` property to either be an array, in which case it just replaces
|
||||||
* the default plugins like previously.
|
* the default plugins like previously, or a config object.
|
||||||
*
|
*
|
||||||
* plugins: {
|
* plugins: {
|
||||||
* install: [
|
* install: [
|
||||||
* ModPlayerPlugin,
|
* ModPlayerPlugin,
|
||||||
* WireFramePlugin
|
* WireFramePlugin
|
||||||
* ],
|
* ],
|
||||||
* filetypes: [
|
|
||||||
* MODFile
|
|
||||||
* OBJFile,
|
|
||||||
* ],
|
|
||||||
* default: [], OR
|
* default: [], OR
|
||||||
* defaultMerge: {
|
* defaultMerge: {
|
||||||
* 'ModPlayer': 'mod'
|
* 'ModPlayer'
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*
|
|
||||||
* If an object, it checks for an 'install' property,
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var plugins = GetValue(config, 'plugins', null);
|
||||||
|
var defaultPlugins = Plugins.DefaultScene;
|
||||||
|
|
||||||
if (plugins)
|
if (plugins)
|
||||||
{
|
{
|
||||||
// Old 3.7 array format?
|
// Old 3.7 array format?
|
||||||
|
@ -489,19 +475,29 @@ var Config = new Class({
|
||||||
}
|
}
|
||||||
else if (IsPlainObject(plugins))
|
else if (IsPlainObject(plugins))
|
||||||
{
|
{
|
||||||
this.installPlugins.global = GetFastValue(plugins, 'install', []);
|
// this.installPlugins.global = GetFastValue(plugins, 'install', []);
|
||||||
|
|
||||||
if (Array.isArray(plugins.default))
|
if (Array.isArray(plugins.default))
|
||||||
{
|
{
|
||||||
this.defaultPlugins = plugins.default;
|
defaultPlugins = plugins.default;
|
||||||
}
|
}
|
||||||
else if (Array.isArray(plugins.defaultMerge))
|
else if (Array.isArray(plugins.defaultMerge))
|
||||||
{
|
{
|
||||||
this.defaultPlugins = this.defaultPlugins.concat(plugins.defaultMerge);
|
defaultPlugins = defaultPlugins.concat(plugins.defaultMerge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {any} Phaser.Boot.Config#defaultPlugins - The plugins installed into every Scene (in addition to CoreScene and Global).
|
||||||
|
*/
|
||||||
|
this.defaultPlugins = defaultPlugins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @const {any} Phaser.Boot.Config#installPlugins - [description]
|
||||||
|
*/
|
||||||
|
this.installPlugins = GetValue(config, 'plugins.install', []);
|
||||||
|
|
||||||
// Default / Missing Images
|
// Default / Missing Images
|
||||||
var pngPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAg';
|
var pngPrefix = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAg';
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
|
|
||||||
var Class = require('../utils/Class');
|
var Class = require('../utils/Class');
|
||||||
|
|
||||||
|
// A Scene Level Plugin is installed into every Scene and belongs to that Scene.
|
||||||
|
// It can listen for Scene events and respond to them.
|
||||||
|
// It can map itself to a Scene property, or into the Scene Systems, or both.
|
||||||
|
//
|
||||||
|
// A Global Plugin is installed just once into the Game owned Plugin Manager.
|
||||||
|
// It can listen for Game events and respond to them.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
* [description]
|
* [description]
|
||||||
|
@ -21,19 +28,20 @@ var Plugin = new Class({
|
||||||
|
|
||||||
initialize:
|
initialize:
|
||||||
|
|
||||||
function Plugin (key, game)
|
function Plugin (key, pluginManager)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* All plugins _must_ set a key property. It's a unique string which is used by the
|
* The unique (within this game instance) name of this plugin within the Plugin Manager.
|
||||||
* PluginManager to register this plugin, return it and invoke it.
|
* This is set by the developer in their game config, although you should provide a default value.
|
||||||
* It must be unique within the scope of the game instance.
|
*
|
||||||
*
|
|
||||||
* @name Phaser.Plugins.Plugin#key
|
* @name Phaser.Plugins.Plugin#key
|
||||||
* @type {string}
|
* @type {string}
|
||||||
* @since 3.8.0
|
* @since 3.8.0
|
||||||
*/
|
*/
|
||||||
this.key = key;
|
this.key = key;
|
||||||
|
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [description]
|
* [description]
|
||||||
*
|
*
|
||||||
|
@ -41,94 +49,127 @@ var Plugin = new Class({
|
||||||
* @type {Phaser.Game}
|
* @type {Phaser.Game}
|
||||||
* @since 3.8.0
|
* @since 3.8.0
|
||||||
*/
|
*/
|
||||||
this.game = game;
|
this.game = pluginManager.game;
|
||||||
|
|
||||||
this.active = true;
|
this.active = true;
|
||||||
|
|
||||||
|
// this.sceneConfig =
|
||||||
|
|
||||||
// The Scene that owns this plugin, if any
|
// The Scene that owns this plugin, if any
|
||||||
this.scene;
|
this.scene;
|
||||||
|
|
||||||
// Scene Systems (if any)
|
// Scene Systems (if any)
|
||||||
this.systems;
|
this.systems;
|
||||||
|
|
||||||
if (game.isBooted)
|
|
||||||
{
|
|
||||||
this.gameBoot();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
game.events.once('boot', this.gameBoot, this);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [description]
|
* Called when the Game boots. Or, if already booted, called immediately by the PluginManager.
|
||||||
*
|
*
|
||||||
* @method Phaser.Plugins.Plugin#gameBoot
|
* @method Phaser.Plugins.Plugin#init
|
||||||
* @since 3.8.0
|
* @since 3.8.0
|
||||||
*/
|
*/
|
||||||
gameBoot: function ()
|
init: function ()
|
||||||
{
|
{
|
||||||
console.log('gameBoot');
|
console.log('Plugin.init');
|
||||||
|
|
||||||
this.game.events.on('pause', this.gamePause, this);
|
|
||||||
this.game.events.on('resume', this.gameResume, this);
|
|
||||||
this.game.events.on('resize', this.gameResize, this);
|
|
||||||
|
|
||||||
this.game.events.once('destroy', this.gameDestroy, this);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
gamePause: function ()
|
/**
|
||||||
|
* Called when the Game pauses.
|
||||||
|
*
|
||||||
|
* @method Phaser.Plugins.Plugin#pauseGame
|
||||||
|
* @since 3.8.0
|
||||||
|
*/
|
||||||
|
pauseGame: function ()
|
||||||
{
|
{
|
||||||
// Game instance has paused
|
|
||||||
},
|
},
|
||||||
|
|
||||||
gameResume: function ()
|
/**
|
||||||
|
* Called when the Game resumes from a paused state.
|
||||||
|
*
|
||||||
|
* @method Phaser.Plugins.Plugin#resumeGame
|
||||||
|
* @since 3.8.0
|
||||||
|
*/
|
||||||
|
resumeGame: function ()
|
||||||
{
|
{
|
||||||
// Game instance has resumed from a paused state
|
|
||||||
},
|
},
|
||||||
|
|
||||||
gameResize: function (newWidth, newHeight)
|
/**
|
||||||
|
* Called when the Game resizes.
|
||||||
|
*
|
||||||
|
* @method Phaser.Plugins.Plugin#resize
|
||||||
|
* @since 3.8.0
|
||||||
|
*/
|
||||||
|
resize: function (newWidth, newHeight)
|
||||||
{
|
{
|
||||||
// Game instance has been resized
|
// Game instance has been resized
|
||||||
},
|
},
|
||||||
|
|
||||||
step: function (time, delta)
|
|
||||||
{
|
|
||||||
// Called automatically by the PluginManager, invoked from the Game.step
|
|
||||||
// Do any continuous processing or updating that you need in here
|
|
||||||
// Not called if Plugin.active = false
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Game instance has been destroyed.
|
* Called when the Game steps.
|
||||||
|
* Called automatically by the PluginManager, invoked from the Game.step.
|
||||||
|
* Do any continuous processing or updating that you need in here.
|
||||||
|
* Not called if Plugin.active = false
|
||||||
*
|
*
|
||||||
* @method Phaser.Plugins.Plugin#gameDestroy
|
* @method Phaser.Plugins.Plugin#step
|
||||||
* @since 3.8.0
|
* @since 3.8.0
|
||||||
*/
|
*/
|
||||||
gameDestroy: function ()
|
step: function (time, delta)
|
||||||
{
|
{
|
||||||
this.game = null;
|
|
||||||
this.scene = null;
|
|
||||||
this.systems = null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Scene Level ...
|
// Scene Level ...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called automatically, only once, when the Scene is first created.
|
* This method is called automatically, only once, when the Scene is first created.
|
||||||
* Do not invoke it directly.
|
* It's only called if this is a Scene Plugin.
|
||||||
*
|
*
|
||||||
* @method Phaser.Time.Clock#boot
|
* @method Phaser.Plugins.Plugin#sceneBoot
|
||||||
* @private
|
* @since 3.8.0
|
||||||
* @since 3.5.1
|
|
||||||
*/
|
*/
|
||||||
boot: function ()
|
sceneBoot: function (scene)
|
||||||
{
|
{
|
||||||
if (this.systems)
|
this.scene = scene;
|
||||||
{
|
this.systems = scene.sys;
|
||||||
this.systems.events.once('destroy', this.destroy, this);
|
|
||||||
}
|
var eventEmitter = scene.sys.events;
|
||||||
|
|
||||||
|
eventEmitter.once('destroy', this.sceneDestroy, this);
|
||||||
|
|
||||||
|
// Listening to the following events is entirely optional, although we would recommend cleanly shutting down and destroying at least.
|
||||||
|
// If you don't need any of these events then remove the listeners and the relevant methods too.
|
||||||
|
|
||||||
|
eventEmitter.on('start', this.start, this);
|
||||||
|
|
||||||
|
eventEmitter.on('preupdate', this.preUpdate, this);
|
||||||
|
eventEmitter.on('update', this.update, this);
|
||||||
|
eventEmitter.on('postupdate', this.postUpdate, this);
|
||||||
|
|
||||||
|
eventEmitter.on('pause', this.pause, this);
|
||||||
|
eventEmitter.on('resume', this.resume, this);
|
||||||
|
|
||||||
|
eventEmitter.on('sleep', this.sleep, this);
|
||||||
|
eventEmitter.on('wake', this.wake, this);
|
||||||
|
|
||||||
|
eventEmitter.on('shutdown', this.shutdown, this);
|
||||||
|
eventEmitter.on('destroy', this.destroy, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game instance has been destroyed.
|
||||||
|
* You must release everything in here, all references, all objects, free it all up.
|
||||||
|
*
|
||||||
|
* @method Phaser.Plugins.Plugin#destroy
|
||||||
|
* @since 3.8.0
|
||||||
|
*/
|
||||||
|
destroy: function ()
|
||||||
|
{
|
||||||
|
this.game = null;
|
||||||
|
this.scene = null;
|
||||||
|
this.systems = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Class = require('../utils/Class');
|
var Class = require('../utils/Class');
|
||||||
|
var EventEmitter = require('eventemitter3');
|
||||||
|
var IsPlainObject = require('../utils/object/IsPlainObject');
|
||||||
|
var GetFastValue = require('../utils/object/GetFastValue');
|
||||||
|
|
||||||
// Contains the plugins that Phaser uses globally and locally.
|
// Contains the plugins that Phaser uses globally and locally.
|
||||||
// These are the source objects, not instantiated.
|
// These are the source objects, not instantiated.
|
||||||
|
var corePlugins = {};
|
||||||
|
|
||||||
|
// Contains the plugins that the dev has loaded into their game
|
||||||
var plugins = {};
|
var plugins = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,10 +31,14 @@ var plugins = {};
|
||||||
*/
|
*/
|
||||||
var PluginManager = new Class({
|
var PluginManager = new Class({
|
||||||
|
|
||||||
|
Extends: EventEmitter,
|
||||||
|
|
||||||
initialize:
|
initialize:
|
||||||
|
|
||||||
function PluginManager (game)
|
function PluginManager (game)
|
||||||
{
|
{
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [description]
|
* [description]
|
||||||
*
|
*
|
||||||
|
@ -38,10 +48,13 @@ var PluginManager = new Class({
|
||||||
*/
|
*/
|
||||||
this.game = game;
|
this.game = game;
|
||||||
|
|
||||||
// Plugins currently running and managed by this Plugin Manager
|
// Plugins currently running and managed by this Plugin Manager.
|
||||||
// These are Game instance specific
|
// These are Game instance specific.
|
||||||
this.activePlugins = [];
|
this.activePlugins = [];
|
||||||
|
|
||||||
|
// Plugins that should be installed into Scenes
|
||||||
|
this.scenePlugins = [];
|
||||||
|
|
||||||
if (game.isBooted)
|
if (game.isBooted)
|
||||||
{
|
{
|
||||||
this.boot();
|
this.boot();
|
||||||
|
@ -63,17 +76,15 @@ var PluginManager = new Class({
|
||||||
this.game.events.once('destroy', this.destroy, this);
|
this.game.events.once('destroy', this.destroy, this);
|
||||||
|
|
||||||
// Any plugins to install?
|
// Any plugins to install?
|
||||||
/*
|
|
||||||
var list = this.game.config.installPlugins;
|
var list = this.game.config.installPlugins;
|
||||||
|
|
||||||
if (list)
|
if (list)
|
||||||
{
|
{
|
||||||
for (var key in list)
|
for (var key in list)
|
||||||
{
|
{
|
||||||
this.add(key, list[key]);
|
// this.register(key, list[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,7 +98,7 @@ var PluginManager = new Class({
|
||||||
*/
|
*/
|
||||||
installGlobal: function (sys, globalPlugins)
|
installGlobal: function (sys, globalPlugins)
|
||||||
{
|
{
|
||||||
var game = sys.game;
|
var game = this.game;
|
||||||
var scene = sys.scene;
|
var scene = sys.scene;
|
||||||
var map = sys.settings.map;
|
var map = sys.settings.map;
|
||||||
|
|
||||||
|
@ -130,12 +141,12 @@ var PluginManager = new Class({
|
||||||
{
|
{
|
||||||
var pluginKey = scenePlugins[i];
|
var pluginKey = scenePlugins[i];
|
||||||
|
|
||||||
if (!plugins[pluginKey])
|
if (!corePlugins[pluginKey])
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var source = plugins[pluginKey];
|
var source = corePlugins[pluginKey];
|
||||||
|
|
||||||
var plugin = new source.plugin(scene);
|
var plugin = new source.plugin(scene);
|
||||||
|
|
||||||
|
@ -156,38 +167,80 @@ var PluginManager = new Class({
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a plugin with the PluginManager. This is the same as calling the
|
* Registers a plugin with the PluginManager.
|
||||||
* static function, but is available via the game pluginManager instance.
|
|
||||||
*
|
*
|
||||||
* Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin)
|
* Key is a reference used to get the plugin from the plugins object (i.e. MyPlugin)
|
||||||
* Plugin is the object to instantiate to create the plugin
|
* Plugin is the function to instantiate to create a plugin instance.
|
||||||
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
|
|
||||||
*
|
*
|
||||||
* @method Phaser.Plugins.PluginManager#register
|
* @method Phaser.Plugins.PluginManager#register
|
||||||
* @since 3.8.0
|
* @since 3.8.0
|
||||||
*
|
*
|
||||||
* @param {string} key - [description]
|
* @param {string} key - [description]
|
||||||
* @param {object} plugin - [description]
|
* @param {function} plugin - [description]
|
||||||
* @param {string} mapping - [description]
|
|
||||||
*/
|
*/
|
||||||
register: function (key, plugin, mapping)
|
register: function (key, plugin, start, isScenePlugin)
|
||||||
{
|
{
|
||||||
plugins[key] = { plugin: plugin, mapping: mapping };
|
if (start === undefined) { start = false; }
|
||||||
|
if (isScenePlugin === undefined) { isScenePlugin = false; }
|
||||||
|
|
||||||
|
if (typeof plugin !== 'function')
|
||||||
|
{
|
||||||
|
console.warn('Invalid Plugin: ' + key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plugins.hasOwnProperty(key))
|
||||||
|
{
|
||||||
|
console.warn('Plugin key in use: ' + key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add it to the plugin store
|
||||||
|
plugins[key] = plugin;
|
||||||
|
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
this.start(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isScenePlugin)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
add: function (plugin)
|
start: function (key)
|
||||||
{
|
{
|
||||||
var instance = new plugin(this.game);
|
var instance;
|
||||||
|
var plugin = this.get(key);
|
||||||
|
|
||||||
var key = instance.key;
|
if (plugin)
|
||||||
|
{
|
||||||
|
instance = new plugin(this);
|
||||||
|
|
||||||
plugins[key] = { plugin: plugin };
|
this.activePlugins.push(instance);
|
||||||
|
}
|
||||||
this.activePlugins.push(instance);
|
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setScenePlugin: function (scene)
|
||||||
|
{
|
||||||
|
},
|
||||||
|
|
||||||
|
addGameObject: function ()
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
addFileType: function ()
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [description]
|
* [description]
|
||||||
*
|
*
|
||||||
|
@ -200,22 +253,7 @@ var PluginManager = new Class({
|
||||||
*/
|
*/
|
||||||
get: function (key)
|
get: function (key)
|
||||||
{
|
{
|
||||||
return (plugins[key]) ? plugins[key].plugin : null;
|
return (plugins.hasOwnProperty(key)) ? plugins[key] : null;
|
||||||
},
|
|
||||||
|
|
||||||
update: function (time, delta)
|
|
||||||
{
|
|
||||||
var activePlugins = this.activePlugins;
|
|
||||||
|
|
||||||
for (var i = 0; i < activePlugins.length; i++)
|
|
||||||
{
|
|
||||||
var plugin = activePlugins[i];
|
|
||||||
|
|
||||||
if (plugin.active)
|
|
||||||
{
|
|
||||||
plugin.step(time, delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,7 +283,7 @@ var PluginManager = new Class({
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static method called directly by the Plugins
|
* Static method called directly by the Core internal Plugins.
|
||||||
* Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin)
|
* Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin)
|
||||||
* Plugin is the object to instantiate to create the plugin
|
* Plugin is the object to instantiate to create the plugin
|
||||||
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
|
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
|
||||||
|
@ -259,7 +297,7 @@ var PluginManager = new Class({
|
||||||
*/
|
*/
|
||||||
PluginManager.register = function (key, plugin, mapping)
|
PluginManager.register = function (key, plugin, mapping)
|
||||||
{
|
{
|
||||||
plugins[key] = { plugin: plugin, mapping: mapping };
|
corePlugins[key] = { plugin: plugin, mapping: mapping };
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = PluginManager;
|
module.exports = PluginManager;
|
||||||
|
|
Loading…
Reference in a new issue