Updated to a working websocket implementation of webclient.

This commit is contained in:
Griatch 2014-06-26 23:37:03 +02:00
parent ca1e36da5f
commit d59500f574
6 changed files with 133 additions and 121 deletions

View file

@ -2,30 +2,39 @@
Evennia websocket webclient (javascript component)
The client is composed of several parts:
templates/webclient.html - the main page
webclient/views.py - the django view serving the template (based on urls.py pattern)
src/server/portal/websockets.py - the server component talking to the client
The client is composed of two parts:
src/server/portal/websocket_client.py - the portal-side component
this file - the javascript component handling dynamic content
This implements an mud client for use with Evennia, using jQuery
for simplicity.
messages sent to the client is one of three modes:
OOB(func,(args), func,(args), ...) - OOB command executions
text - any other text is considered a normal text to echo
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.
*/
// jQuery must be imported by the calling html page before this script
// There are plenty of help on using the jQuery library on http://jquery.com/
// If on, allows client user to send OOB messages to server by
// prepending with ##OOB{}, for example ##OOB{"echo":[1,2,3,4]}
var OOB_debug = true
// Server communications
// Set this to the value matching settings.WEBSOCKET_PORTS
var wsurl = "ws://localhost:8001";
// Custom OOB functions
// functions defined here can be called by name by the server. For
// example the OOB{"echo":arguments} will trigger a function named
// echo(arguments).
function echo(message) {
// example echo function.
doShow("out", "ECHO return: " + message) }
// Webclient code
function webclient_init(){
// initializing the client once the html page has loaded
// called when client is just initializing
websocket = new WebSocket(wsurl);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
@ -34,91 +43,100 @@ function webclient_init(){
}
function onOpen(evt) {
// client is just connecting
// called when client is first connecting
$("#connecting").remove(); // remove the "connecting ..." message
msg_display("sys", "Using websockets - connected to " + wsurl + ".")
doShow("sys", "Using websockets - connected to " + wsurl + ".")
setTimeout(function () {
$("#playercount").fadeOut('slow', webclient_set_sizes);
$("#playercount").fadeOut('slow', doSetSizes);
}, 10000);
}
function onClose(evt) {
// client is closing
// called when client is closing
CLIENT_HASH = 0;
alert("Mud client connection was closed cleanly.");
}
function onMessage(evt) {
// outgoing message from server
// called when the Evennia is sending data to client
var inmsg = evt.data
if (inmsg.length > 3 && inmsg.substr(0, 3) == "OOB") {
// dynamically call oob methods, if available
try {var oobarray = JSON.parse(inmsg.slice(3));} // everything after OOB }
catch(err) {
// not JSON packed - a normal text
msg_display('out', err + " " + inmsg);
doShow('out', err + " " + inmsg);
return;
}
for (var ind in oobarray) {
try { window[oobarray[ind][0]](oobarray[ind][1]) }
catch(err) { msg_display("err", "Could not execute OOB function " + oobtuple[0] + "(" + oobtuple[1] + ")!") }
catch(err) { doShow("err", "Could not execute OOB function " + oobtuple[0] + "(" + oobtuple[1] + ")!") }
}
}
else {
// normal message
msg_display('out', inmsg); }
doShow('out', inmsg); }
}
function onError(evt) {
// client error message
msg_display('err', "Error: Server returned an error. Try reloading the page.");
// called on a server error
doShow('err', "Error: Server returned an error. Try reloading the page.");
}
function doSend(){
// sending data from client to server
// relays data from client to Evennia.
// If OOB_debug is set, allows OOB test data on the
// form ##OOB{func:args}
outmsg = $("#inputfield").val();
history_add(outmsg);
HISTORY_POS = 0;
$('#inputform')[0].reset(); // clear input field
if (outmsg.length > 4 && outmsg.substr(0, 5) == "##OOB") {
if (OOB_debug && outmsg.length > 4 && outmsg.substr(0, 5) == "##OOB") {
// test OOB messaging
doOOB(JSON.parse(outmsg.slice(5))); }
else {
// normal output
websocket.send(outmsg); }
}
function doOOB(oobdict){
// Handle OOB communication from client side
// Takes a dict on form {funcname:[args], funcname: [args], ... ]
msg_display("out", "into doOOB: " + oobdict)
msg_display("out", "stringify: " + JSON.stringify(oobdict))
// Send OOB data from client to Evennia.
// Takes input on form {funcname:[args], funcname: [args], ... }
var oobmsg = JSON.stringify(oobdict);
websocket.send("OOB" + oobmsg);
}
//
// OOB functions
//
function echo(message) {
msg_display("out", "ECHO return: " + message) }
//
// Display messages
function msg_display(type, msg){
// Add a div to the message window.
function doShow(type, msg){
// Add msg to the main output window.
// type gives the class of div to use.
// The default types are
// "out" (normal output) or "err" (red error message)
$("#messagewindow").append(
"<div class='msg "+ type +"'>"+ msg +"</div>");
// scroll message window to bottom
$('#messagewindow').animate({scrollTop: $('#messagewindow')[0].scrollHeight});
}
// Input history mechanism
function doSetSizes() {
// Sets the size of the message window
var win_h = $(document).height();
//var win_w = $('#wrapper').width();
var inp_h = $('#inputform').outerHeight(true);
//var inp_w = $('#inputsend').outerWidth(true);
$("#messagewindow").css({'height': win_h - inp_h - 1});
//$("#inputfield").css({'width': win_w - inp_w - 20});
}
//
// Input code
//
// Input history
var HISTORY_MAX_LENGTH = 21
var HISTORY = new Array();
@ -223,6 +241,8 @@ $.fn.appendCaret = function() {
});
};
// Input jQuery callbacks
$(document).keydown( function(event) {
// Get the pressed key (normalized by jQuery)
var code = event.which,
@ -233,7 +253,7 @@ $(document).keydown( function(event) {
// Special keys recognized by client
//msg_display("out", "key code pressed: " + code); // debug
//doShow("out", "key code pressed: " + code); // debug
if (code == 13) { // Enter Key
doSend();
@ -252,36 +272,24 @@ $(document).keydown( function(event) {
// handler to avoid double-clicks until the ajax request finishes
//$("#inputsend").one("click", webclient_input)
function webclient_set_sizes() {
// Sets the size of the message window
var win_h = $(document).height();
//var win_w = $('#wrapper').width();
var inp_h = $('#inputform').outerHeight(true);
//var inp_w = $('#inputsend').outerWidth(true);
// Callback function - called when the browser window resizes
$(window).resize(doSetSizes);
$("#messagewindow").css({'height': win_h - inp_h - 1});
//$("#inputfield").css({'width': win_w - inp_w - 20});
}
// Callback function - called when page has finished loading (gets things going)
// Callback function - called when page is closed or moved away from.
//$(window).bind("beforeunload", webclient_close);
//
// 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();
// set sizes of elements and reposition them
webclient_set_sizes();
doSetSizes();
// a small timeout to stop 'loading' indicator in Chrome
setTimeout(function () {
webclient_init();
}, 500);
// set an idle timer to avoid proxy servers to time out on us (every 3 minutes)
setInterval(function() {
webclient_input("idle", true);
websocket.send("idle");
}, 60000*3);
});
// Callback function - called when the browser window resizes
$(window).resize(webclient_set_sizes);
// Callback function - called when page is closed or moved away from.
//$(window).bind("beforeunload", webclient_close);

View file

@ -19,9 +19,10 @@
<script language="javascript" type="text/javascript">
if ("WebSocket" in window) {
<!-- Importing the Evennia websocket webclient component (requires jQuery) -->
var wsurl = "{{websocket_url}}";
document.write("\<script src=\"/media/javascript/evennia_websocket_webclient.js\" type=\"text/javascript\" charset=\"utf-8\"\>\</script\>")}
else {
<!-- Importing the Evennia ajax webclient component (requires jQuery) -->
<!-- No websocket support in browser. Importing the Evennia ajax webclient component (requires jQuery) -->
document.write("\<script src=\"/media/javascript/evennia_ajax_webclient.js\" type=\"text/javascript\" charset=\"utf-8\"\>\</script\>")}
</script>
{% else %}

View file

@ -6,7 +6,6 @@
# tuple.
#
from django.db import models
from django.conf import settings
from src.utils.utils import get_evennia_version
@ -30,6 +29,9 @@ WEBSITE = ['Flatpages', 'News', 'Sites']
# The main context processor function
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
WEBSOCKET_CLIENT_ENABLED = settings.WEBSOCKET_CLIENT_ENABLED
WSURL = "%s:%s" % (settings.WEBSOCKET_CLIENT_URL, settings.WEBSOCKET_CLIENT_PORT)
def general_context(request):
"""
@ -44,6 +46,7 @@ def general_context(request):
'evennia_setupapps': GAME_SETUP,
'evennia_connectapps': CONNECTIONS,
'evennia_websiteapps':WEBSITE,
"webclient_enabled" : settings.WEBCLIENT_ENABLED,
"websocket_enabled" : settings.WEBSOCKET_ENABLED
"webclient_enabled" : WEBCLIENT_ENABLED,
"websocket_enabled" : WEBSOCKET_CLIENT_ENABLED,
"websocket_url" : WSURL
}