OutlandsMud/web/static/webclient/js/webclient_gui.js

307 lines
9.5 KiB
JavaScript

/*
*
* Evennia Webclient GUI component
*
* This is used in conjunction with the main evennia.js library, which
* handles all the communication with the Server.
*
* The job of this code is to coordinate between listeners subscribed to
* evennia messages and any registered plugins that want to process those
* messages and send data back to Evennia
*
* This is done via Evennia.emitter.on(cmdname, listener) and calling
* each plugin's init() function to give each plugin a chance to register
* input handlers or other events on startup.
*
* Once a plugin has determined it wants to send a message back to the
* server, it generates an onSend() function event which allows all
* other plugins a chance to modify the event and then uses
* Evennia.msg(cmdname, args, kwargs, [callback]) to finally send the data.
*
*/
//
// Global Plugins system
//
var options = {}; // Global "settings" object that all plugins can use to
// save/pass data to each other and the server.
// format should match:
// { 'plugin_name': { 'option_key': value, ... }, ... }
var plugins = {}; // Global plugin objects by name.
// Each must have an init() function.
//
// Global plugin_handler
//
var plugin_handler = (function () {
"use strict"
var ordered_plugins = new Array; // plugins in <html> loaded order
//
// Plugin Support Functions
//
// Add a new plugin
var add = function (name, plugin) {
plugins[name] = plugin;
ordered_plugins.push( plugin );
}
//
// GUI Event Handlers
//
// catch all keyboard input, handle special chars
var onKeydown = function (event) {
// cycle through each plugin's keydown
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
// does this plugin handle keydown events?
if( 'onKeydown' in plugin ) {
// yes, does this plugin claim this event exclusively?
if( plugin.onKeydown(event) ) {
// 'true' claims this event has been handled
return;
}
}
}
console.log('NO plugin handled this Keydown');
}
// Ask if user really wants to exit session when closing
// the tab or reloading the page. Note: the message is not shown
// in Firefox, there it's a standard error.
var onBeforeUnload = function () {
// cycle through each plugin to look for unload handlers
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onBeforeUnload' in plugin ) {
plugin.onBeforeUnload();
}
}
}
//
// Evennia Public Event Handlers
//
// Handle onLoggedIn from the server
var onLoggedIn = function (args, kwargs) {
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onLoggedIn' in plugin ) {
plugin.onLoggedIn(args, kwargs);
}
}
}
// Handle onGotOptions from the server
var onGotOptions = function (args, kwargs) {
// does any plugin handle Options?
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onGotOptions' in plugin ) {
plugin.onGotOptions(args, kwargs);
}
}
}
// Handle text coming from the server
var onText = function (args, kwargs) {
// does this plugin handle this onText event?
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onText' in plugin ) {
if( plugin.onText(args, kwargs) ) {
// True -- means this plugin claims this Text exclusively.
return;
}
}
}
console.log('NO plugin handled this Text');
}
// Handle prompt output from the server
var onPrompt = function (args, kwargs) {
// does this plugin handle this onPrompt event?
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onPrompt' in plugin ) {
if( plugin.onPrompt(args, kwargs) ) {
// True -- means this plugin claims this Prompt exclusively.
return;
}
}
}
console.log('NO plugin handled this Prompt');
}
// Handle unrecognized commands from server
var onDefault = function (cmdname, args, kwargs) {
// does this plugin handle this UnknownCmd?
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onUnknownCmd' in plugin ) {
if( plugin.onUnknownCmd(args, kwargs) ) {
// True -- means this plugin claims this UnknownCmd exclusively.
return;
}
}
}
console.log('NO plugin handled this Unknown Evennia Command');
}
// Handle the server connection closing
var onConnectionClose = function (args, kwargs) {
// give every plugin a chance to do stuff onConnectionClose
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onConnectionClose' in plugin ) {
plugin.onConnectionClose(args, kwargs);
}
}
onText(["The connection was closed or lost."], {'cls': 'err'});
}
// Silences events we don't do anything with.
var onSilence = function (cmdname, args, kwargs) {}
//
// Global onSend() function to iterate through all plugins before sending text to the server.
// This can be called by other plugins for "Triggers", <enter>, and other automated sends
//
var onSend = function (line) {
if (!Evennia.isConnected()) {
var reconnect = confirm("Not currently connected. Reconnect?");
if (reconnect) {
onText(["Attempting to reconnnect..."], {cls: "sys"});
Evennia.connect();
}
// Don't try to send anything until the connection is back.
return;
}
// default output command
var cmd = {
command: "text",
args: [ line ],
kwargs: {}
};
// Give each plugin a chance to use/modify the outgoing command for aliases/history/etc
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'onSend' in plugin ) {
var outCmd = plugin.onSend(line);
if( outCmd ) {
cmd = outCmd;
}
}
}
// console.log('sending: ' + cmd.command + ', [' + cmd.args[0].toString() + '], ' + cmd.kwargs.toString() );
Evennia.msg(cmd.command, cmd.args, cmd.kwargs);
}
//
// call each plugins' init function (the only required function)
//
var init = function () {
for( let n=0; n < ordered_plugins.length; n++ ) {
ordered_plugins[n].init();
}
}
//
// normally init() is all that is needed, but some cases may require a second
// pass to avoid chicken/egg dependencies between two plugins.
var postInit = function () {
// does this plugin need postInit() to be called?
for( let n=0; n < ordered_plugins.length; n++ ) {
let plugin = ordered_plugins[n];
if( 'postInit' in plugin ) {
plugin.postInit();
}
}
}
return {
add: add,
onKeydown: onKeydown,
onBeforeUnload: onBeforeUnload,
onLoggedIn: onLoggedIn,
onText: onText,
onGotOptions: onGotOptions,
onPrompt: onPrompt,
onDefault: onDefault,
onSilence: onSilence,
onConnectionClose: onConnectionClose,
onSend: onSend,
init: init,
postInit: postInit,
}
})();
//
// Webclient Initialization
//
// Event when client finishes loading
$(document).ready(function() {
// This is safe to call, it will always only
// initialize once.
Evennia.init();
// register listeners
Evennia.emitter.on("logged_in", plugin_handler.onLoggedIn);
Evennia.emitter.on("text", plugin_handler.onText);
Evennia.emitter.on("webclient_options", plugin_handler.onGotOptions);
Evennia.emitter.on("prompt", plugin_handler.onPrompt);
Evennia.emitter.on("default", plugin_handler.onDefault);
Evennia.emitter.on("connection_close", plugin_handler.onConnectionClose);
// silence currently unused events
Evennia.emitter.on("connection_open", plugin_handler.onSilence);
Evennia.emitter.on("connection_error", plugin_handler.onSilence);
// Event when closing window (have to have Evennia initialized)
$(window).bind("beforeunload", plugin_handler.onBeforeUnload);
// Event when any key is pressed
$(document).keydown(plugin_handler.onKeydown)
// set an idle timer to send idle every 3 minutes,
// to avoid proxy servers timing out on us
setInterval( function() { // Connect to server
Evennia.msg("text", ["idle"], {});
},
60000*3
);
// Initialize all plugins
plugin_handler.init();
// Finish Initializing any plugins that need a second stage
plugin_handler.postInit();
console.log("Completed Webclient setup");
});