Skip to content

Instantly share code, notes, and snippets.

@hakupaku
Last active December 22, 2015 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakupaku/11834aac8746d8f0dde7 to your computer and use it in GitHub Desktop.
Save hakupaku/11834aac8746d8f0dde7 to your computer and use it in GitHub Desktop.
A quick gist of thoughts on the websocket messaging for Evennia
/*
Evennia websocket webclient (javascript component)
The client is composed of two parts:
/server/portal/websocket_client.py - the portal-side component
this file - the javascript component handling dynamic content
messages sent to the client is one of two modes:
OOB("func1",args, "func2",args, ...) - OOB command executions, this will
call unique javascript functions
func1(args), func2(args) etc.
text - any other text is considered a normal text output in the main output window.
*/
//
// Custom OOB functions
// functions defined here can be called by name by the server. For
// example input OOB{"echo":(args),{kwargs}} will trigger a function named
// echo(args, kwargs). The commands the server understands is set by
// settings.OOB_PLUGIN_MODULES
(function() {
var id = 0;
var map = {};
var Evennia = {
debug: true,
// called by the frontend to send a command to the backend
cmd: function (cmd, params, callback) {
var msg = params ? [cmd, [params], {}] : [cmd, [], {}];
params.id = id++;
log('cmd called with following args:', cmd, params, callback);
websocket.send('OOB' + JSON.stringify(msg));
if (typeof callback === 'function') {
map[id] = callback;
}
},
// called by the backend to emit an event to the global emitter
emit: function (event, data) {
if (data.id) {
map[data.id].apply(this, [event, data]);
delete map[data.id];
}
Evennia.emitter.emit(event, data);
},
// startup Evennia emitter and connection
init: function (opts) {
opts = opts || {};
Evennia.emitter = opts.emitter || new Emitter();
Evennia.websocket = new Connection();
}
};
// wrapper for websocket setup
var Connection = function () {
var websocket = new WebSocket(wsurl);
websocket.onopen = function (event) {
Evennia.emit('socket:open', event);
};
websocket.onclose = function (event) {
log('WebSocket connection closed.')
Evennia.emit('socket:close', event);
};
websocket.onmessage = function (event) {
if (typeof event.data !== 'string' && event.data.length < 0) {
return;
}
// only acceptable mode is OOB
var mode = event.data.substr(0, 3);
if (mode === 'OOB') {
// parse the rest of the response
var res = JSON.parse(event.data.substr(3));
log(res);
var cmd = res[0];
var args = res[1];
Evennia.emit(cmd, args[0]);
}
};
websocket.onerror = function (event) {
log("Websocket error to ", wsurl, event);
Evennia.emit('socket:error', data);
};
return websocket;
}
// basic emitter, can be overridden in evennia init
var Emitter = function () {
var map = {};
// emit to listeners of given event
var emit = function (event, params) {
log('emit', event, params);
if (map[event] && map[event] === Array) {
map[event].forEach(function (val) {
val.apply(this, params);
});
}
};
// bind listener to event, only allow one instance of handler
var on = function (event, handler) {
if (!map[event]) {
map[event] = [];
}
if (map[event].indexOf(handler) >= 0) {
return;
}
map[event].push(handler);
};
// remove handler from event
var off = function (event, handler) {
if (map[event]) {
var listener = map[event].indexOf(handler);
if (listener >= 0) {
map[event].splice(listener, 1);
}
}
};
return {
emit: emit,
on: on,
off: off
};
};
window.Evennia = Evennia;
})();
function log() {
if (Evennia.debug) {
console.log(arguments);
}
}
// Callback function - called when page has finished loading (kicks the client into gear)
$(document).ready(function(){
// remove the "no javascript" warning, since we obviously have javascript
$('#noscript').remove();
// a small timeout to stop 'loading' indicator in Chrome
setTimeout(function () {
log('Evennia initialized...')
Evennia.init();
}, 500);
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() {
log('Idle tick.');
}, 60000*3);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment