More work on the new js lib, added client-side support for ajax/comet, which will be using JSON and OOB commands, same as websocket version.

This commit is contained in:
Griatch 2016-02-08 18:13:29 +01:00
parent 7fa088c036
commit da52380b0f

View file

@ -25,10 +25,14 @@ functions:
- Evennia.init(options) - Evennia.init(options)
This must be called by the frontend to intialize the library. The This must be called by the frontend to intialize the library. The
argument is an js object with the following possible keys: argument is an js object with the following possible keys:
'connection': Either 'websocket' or 'comet'. 'connection': This defaults to Evennia.WebsocketConnection but
can also be set to Evennia.CometConnection for backwards
compatibility with old browsers. Each connection must have
a 'msg(data)' method that should handle the conversion to
JSON before sending across the wire.
'cmdhandler': An optional custom command handler for 'cmdhandler': An optional custom command handler for
managing outgoing commands from the server. If not managing outgoing commands from the server. If not
supplied, the default will be used. It must have a msg() function. supplied, the default will be used. It must have an emit(data) function.
- Evennia.msg(funcname, [args,...], callback) - Evennia.msg(funcname, [args,...], callback)
Send a command to the server. You can also provide a function Send a command to the server. You can also provide a function
to call with the return of the call (not all commands will return to call with the return of the call (not all commands will return
@ -37,6 +41,7 @@ functions:
Evennia websocket webclient (javascript component) Evennia websocket webclient (javascript component)
The client is composed of two parts: The client is composed of two parts:
@ -55,8 +60,29 @@ messages sent to the client is one of two modes:
var cmdid = 0; var cmdid = 0;
var cmdmap = {}; var cmdmap = {};
var Evennia = { var evennia = {
debug: true, debug: true,
// Initialize.
// startup Evennia emitter and connection.
//
// Args:
// opts (obj):
// emitter - custom emitter. If not given,
// will use a default emitter. Must have
// an "emit" function.
// connection - This defaults to a WebsocketConnection,
// but could also be the CometConnection or another
// custom protocol. Must have a 'send' method and
// make use of Evennia.emit to return data to Client.
//
init: function(opts) {
opts = opts || {};
this.emitter = opts.emitter || new DefaultEmitter();
this.connection = opts.connection || new WebsocketConnection();
},
// Client -> Evennia. // Client -> Evennia.
// Called by the frontend to send a command to Evennia. // Called by the frontend to send a command to Evennia.
// //
@ -66,14 +92,14 @@ messages sent to the client is one of two modes:
// callback (func): If given, will be given an eventual return // callback (func): If given, will be given an eventual return
// value from the backend. // value from the backend.
// //
send: function (cmdname, kwargs, callback) { msg: function (cmdname, kwargs, callback) {
kwargs.cmdid = cmdid++; kwargs.cmdid = cmdid++;
var data = kwargs ? [cmdname, kwargs] : [cmdname, {}]; var data = kwargs ? [cmdname, kwargs] : [cmdname, {}];
if (typeof callback === 'function') { if (typeof callback === 'function') {
this.cmdmap[cmdid] = callback; this.cmdmap[cmdid] = callback;
} }
this.connection.send(JSON.stringify(kwargs)); this.connection.msg(data);
log('cmd called with following args:', cmd, params, callback); log('cmd called with following args:', cmd, params, callback);
}, },
@ -95,24 +121,52 @@ messages sent to the client is one of two modes:
} }
}, },
// Initializer. }; // end of evennia object
// startup Evennia emitter and connection.
// Basic emitter to distribute data being sent to the client from
// the Server. An alternative can be overridden in Evennia.init.
//
var DefaultEmitter = function () {
var cmdmap = {};
// Emit data to all listeners tied to a given cmdname
// //
// Args: // Args:
// opts (obj): // cmdname (str): Name of command, used to find
// emitter - custom emitter. If not given, // all listeners to this call; each will be
// will use a default emitter. Must have // called as function(kwargs).
// an "emit" function. // kwargs (obj): Argument to the listener.
// connection - This defaults to a WebsocketConnection,
// but could also be the CometConnection or another
// custom protocol. Must have a 'send' method and
// make use of Evennia.emit to return data to Client.
// //
init: function (kwargs) { var emit = function (cmdname, kwargs) {
kwargs = kwargs || {}; log('emit', cmdname, kwargs);
this.emitter = kwargs.emitter || new DefaultEmitter();
this.connection = kwargs.connection || new WebsocketConnection(); if (this.cmdmap[cmdname]) {
} this.cmdmap[cmdname].apply(this, kwargs);
};
};
// Bind listener to event
//
// Args:
// cmdname (str): Name of event to handle.
// listener (function): Function taking one argument,
// to listen to cmdname events.
//
var on = function (cmdname, listener) {
if typeof(listener === 'function') {
this.cmdmap[cmdname] = listener;
};
};
// remove handling of this cmdname
//
// Args:
// cmdname (str): Name of event to handle
//
var off = function (cmdname) {
delete this.cmdmap[cmdname]
};
return {emit:emit, on:on, off:off}
}; };
// Websocket Connector // Websocket Connector
@ -145,70 +199,72 @@ messages sent to the client is one of two modes:
data = JSON.parse(data); data = JSON.parse(data);
Evennia.emit(data[0], data[1]]); Evennia.emit(data[0], data[1]]);
}; };
this.websocket.msg = function(data) {
this.websocket.send(JSON.stringify(data));
};
return websocket; return websocket;
} }
// AJAX/COMET Connector // AJAX/COMET Connector
// //
CometConnection = function() { CometConnection = function() {
var client_hash = '0';
}; var ajaxcomet = {
// Send Client -> Evennia. Called by Evennia.send.
// Basic emitter to distribute data being sent to the client from var msg = function(data) {
// the Server. An alternative can be overridden in Evennia.init. $.ajax({type: "POST", url: "/webclientdata",
// async: true, cache: false, timeout: 30000,
var DefaultEmitter = function () { dataType: "json",
var cmdmap = {}; data: {mode:'input', msg: data, 'suid': client_hash},
success: function(data): {},
// Emit data to all listeners tied to a given cmdname error: function(req, stat, err): {
// log("COMET: Server returned error. " + err)
// Args:
// cmdname (str): Name of command, used to find
// all listeners to this call; each will be
// called as function(kwargs).
// kwargs (obj): Argument to the listener.
//
var emit = function (cmdname, kwargs) {
log('emit', cmdname, kwargs);
if (this.cmdmap[cmdname]) {
this.cmdmap[cmdname].apply(this, kwargs);
};
} }
});
}; };
// Bind listener to event // Receive Evennia -> Client. This will start an asynchronous
// // Long-polling request. It will either timeout or receive data
// Args: // from the 'webclientdata' url. Either way a new polling request
// cmdname (str): Name of event to handle. // will immediately be started.
// listener (function): Function taking one argument, var poll = function() {
// to listen to cmdname events. $.ajax({type: "POST", url: "/webclientdata",
// async: true, cache: false, timeout: 30000,
var on = function (cmdname, listener) { dataType: "json",
if typeof(listener === 'function') { data = {mode: 'receive', 'suid': client_hash},
this.cmdmap[cmdname] = listener; success: function(data) {
Evennia.emit(data[0], data[1])
},
error: function() {
this.poll() // timeout; immediately re-poll
} }
});
}; };
// remove handling of this cmdname // Initialization will happen when this Connection is created.
// // We need to store the client id so Evennia knows to separate
// Args: // the clients.
// cmdname (str): Name of event to handle $.ajax({type: "POST", url: "/webclientdata",
// async: true, cache: false, timeout: 50000,
var off = function (cmdname) { datatype: "json",
delete this.cmdmap[cmdname] success: function(data) {
this.client_hash = data.suid;
this.poll();
},
error: function(req, stat, err) {
log("Connection error: " + err);
} }
});
}; };
return { return ajaxcomet;
emit: emit,
on: on,
off: off
};
}; };
window.Evennia = Evennia; window.Evennia = evennia;
})();
})(); // end of auto-calling Evennia object defintion
// helper logging function // helper logging function
// Args: // Args:
@ -222,13 +278,13 @@ function log(msg) {
// Called when page has finished loading (kicks the client into gear) // Called when page has finished loading (kicks the client into gear)
$(document).ready(function(){ $(document).ready(function(){
// remove the "no javascript" warning, since we obviously have javascript
$('#noscript').remove();
// a small timeout to stop 'loading' indicator in Chrome // a small timeout to stop 'loading' indicator in Chrome
setTimeout(function () { setTimeout(function () {
log('Evennia initialized...') log('Evennia initialized...')
Evennia.init(); Evennia.init()
}, 500); }, 500);
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes) // set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() { setInterval(function() {