Cleaned up the webclient and changed how it handles sessions and identifies with the server. Fixed some reported bugs caused by the changed layout of sessionhandler.
This commit is contained in:
parent
b1682f78c9
commit
0eb5d29560
16 changed files with 191 additions and 107 deletions
|
|
@ -7,7 +7,7 @@ Admin commands
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from src.players.models import PlayerDB
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.permissions.permissions import has_perm, has_perm_string
|
||||
from src.permissions.models import PermissionGroup
|
||||
from src.utils import utils
|
||||
|
|
@ -48,7 +48,7 @@ class CmdBoot(MuxCommand):
|
|||
|
||||
if 'port' in self.switches:
|
||||
# Boot a particular port.
|
||||
sessions = sessionhandler.get_session_list(True)
|
||||
sessions = SESSIONS.get_session_list(True)
|
||||
for sess in sessions:
|
||||
# Find the session with the matching port number.
|
||||
if sess.getClientAddress()[1] == int(args):
|
||||
|
|
@ -66,7 +66,7 @@ class CmdBoot(MuxCommand):
|
|||
pobj.msg(string)
|
||||
return
|
||||
# we have a bootable object with a connected user
|
||||
matches = sessionhandler.sessions_from_object(pobj)
|
||||
matches = SESSIONS.sessions_from_object(pobj)
|
||||
for match in matches:
|
||||
boot_list.append(match)
|
||||
else:
|
||||
|
|
@ -90,7 +90,7 @@ class CmdBoot(MuxCommand):
|
|||
if feedback:
|
||||
session.msg(feedback)
|
||||
session.disconnectClient()
|
||||
sessionhandler.remove_session(session)
|
||||
SESSIONS.remove_session(session)
|
||||
caller.msg("You booted %s." % name)
|
||||
|
||||
|
||||
|
|
@ -479,4 +479,4 @@ class CmdWall(MuxCommand):
|
|||
self.caller.msg("Usage: @wall <message>")
|
||||
return
|
||||
message = "%s shouts \"%s\"" % (self.caller.name, self.args)
|
||||
sessionhandler.announce_all(message)
|
||||
SESSIONS.announce_all(message)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ now.
|
|||
"""
|
||||
import time
|
||||
from django.conf import settings
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.permissions.models import PermissionGroup
|
||||
from src.permissions.permissions import has_perm, has_perm_string
|
||||
from src.objects.models import HANDLE_SEARCH_ERRORS
|
||||
|
|
@ -342,7 +342,7 @@ class CmdWho(MuxCommand):
|
|||
"""
|
||||
|
||||
caller = self.caller
|
||||
session_list = sessionhandler.get_sessions()
|
||||
session_list = SESSIONS.get_sessions()
|
||||
|
||||
if self.cmdstring == "doing":
|
||||
show_session_data = False
|
||||
|
|
@ -350,44 +350,44 @@ class CmdWho(MuxCommand):
|
|||
show_session_data = has_perm_string(caller, "Immortals,Wizards")
|
||||
|
||||
if show_session_data:
|
||||
retval = "Player Name On For Idle Room Cmds Host\n\r"
|
||||
table = [["Player Name"], ["On for"], ["Idle"], ["Room"], ["Cmds"], ["Host"]]
|
||||
else:
|
||||
retval = "Player Name On For Idle\n\r"
|
||||
|
||||
table = [["Player Name"], ["On for"], ["Idle"]]
|
||||
|
||||
for session in session_list:
|
||||
if not session.logged_in:
|
||||
continue
|
||||
delta_cmd = time.time() - session.cmd_last_visible
|
||||
delta_conn = time.time() - session.conn_time
|
||||
plr_pobject = session.get_character()
|
||||
|
||||
if show_session_data:
|
||||
retval += '%-31s%9s %4s%-3s#%-6d%5d%3s%-25s\r\n' % \
|
||||
(plr_pobject.name[:25], \
|
||||
# On-time
|
||||
utils.time_format(delta_conn,0), \
|
||||
# Idle time
|
||||
utils.time_format(delta_cmd,1), \
|
||||
# Flags
|
||||
'', \
|
||||
# Location
|
||||
plr_pobject.location.id, \
|
||||
session.cmd_total, \
|
||||
# More flags?
|
||||
'', \
|
||||
session.address[0])
|
||||
table[0].append(plr_pobject.name[:25])
|
||||
table[1].append(utils.time_format(delta_conn,0))
|
||||
table[2].append(utils.time_format(delta_cmd,1))
|
||||
table[3].append(plr_pobject.location.id)
|
||||
table[4].append(session.cmd_total)
|
||||
table[5].append(session.address[0])
|
||||
else:
|
||||
retval += '%-31s%9s %4s%-3s\r\n' % \
|
||||
(plr_pobject.name[:25], \
|
||||
# On-time
|
||||
utils.time_format(delta_conn,0), \
|
||||
# Idle time
|
||||
utils.time_format(delta_cmd,1), \
|
||||
# Flags
|
||||
'')
|
||||
retval += '%d Players logged in.' % (len(session_list),)
|
||||
table[0].append(plr_pobject.name[:25])
|
||||
table[1].append(utils.time_format(delta_conn,0))
|
||||
table[2].append(utils.time_format(delta_cmd,1))
|
||||
stable = []
|
||||
for row in table: # prettify values
|
||||
stable.append([str(val).strip() for val in row])
|
||||
ftable = utils.format_table(stable, 5)
|
||||
string = ""
|
||||
for ir, row in enumerate(ftable):
|
||||
if ir == 0:
|
||||
string += "\n" + "{w%s{n" % ("".join(row))
|
||||
else:
|
||||
string += "\n" + "".join(row)
|
||||
nplayers = (SESSIONS.player_count())
|
||||
if nplayers == 1:
|
||||
string += '\nOne player logged in.'
|
||||
else:
|
||||
string += '\n%d players logged in.' % nplayers
|
||||
|
||||
caller.msg(retval)
|
||||
caller.msg(string)
|
||||
|
||||
class CmdSay(MuxCommand):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -9,13 +9,15 @@ import os, datetime
|
|||
import django, twisted
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from src.server import sessionhandler
|
||||
from src.server.server import EVENNIA
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.scripts.models import ScriptDB
|
||||
from src.objects.models import ObjectDB
|
||||
from src.config.models import ConfigValue
|
||||
from src.utils import reloads, create, logger, utils, gametime
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
|
||||
class CmdReload(MuxCommand):
|
||||
"""
|
||||
Reload the system
|
||||
|
|
@ -429,13 +431,9 @@ class CmdShutdown(MuxCommand):
|
|||
announcement = "\nServer is being SHUT DOWN!\n"
|
||||
if self.args:
|
||||
announcement += "%s\n" % self.args
|
||||
|
||||
sessionhandler.announce_all(announcement)
|
||||
logger.log_infomsg('Server shutdown by %s.' % self.caller.name)
|
||||
|
||||
# access server through session so we don't call server directly
|
||||
# (importing it directly would restart it...)
|
||||
session.server.shutdown()
|
||||
SESSIONS.announce_all(announcement)
|
||||
EVENNIA.shutdown()
|
||||
|
||||
class CmdVersion(MuxCommand):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ be able to delete connections on the fly).
|
|||
from django.db import models
|
||||
from src.utils.idmapper.models import SharedMemoryModel
|
||||
from src.players.models import PlayerDB
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.comms import managers
|
||||
from src.permissions.permissions import has_perm
|
||||
from src.utils.utils import is_iter
|
||||
|
|
@ -509,7 +509,7 @@ class Channel(SharedMemoryModel):
|
|||
# send message to all connected players
|
||||
for conn in conns:
|
||||
for session in \
|
||||
sessionhandler.SESSIONS.sessions_from_player(conn.player):
|
||||
SESSIONS.sessions_from_player(conn.player):
|
||||
session.msg(msg)
|
||||
return True
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ from django.conf import settings
|
|||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.encoding import smart_str
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.players import manager
|
||||
from src.typeclasses.models import Attribute, TypedObject
|
||||
from src.permissions import permissions
|
||||
|
|
@ -220,7 +220,7 @@ class PlayerDB(TypedObject):
|
|||
#@property
|
||||
def sessions_get(self):
|
||||
"Getter. Retrieve sessions related to this player/user"
|
||||
return sessionhandler.SESSIONS.sessions_from_player(self)
|
||||
return SESSIONS.sessions_from_player(self)
|
||||
#@sessions.setter
|
||||
def sessions_set(self, value):
|
||||
"Setter. Protects the sessions property from adding things"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ It also defines a few common scripts.
|
|||
|
||||
from time import time
|
||||
from twisted.internet import task
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.typeclasses.typeclass import TypeClass
|
||||
from src.scripts.models import ScriptDB
|
||||
from src.comms import channelhandler
|
||||
|
|
@ -234,7 +234,7 @@ class CheckSessions(Script):
|
|||
"called every 60 seconds"
|
||||
#print "session check!"
|
||||
#print "ValidateSessions run"
|
||||
sessionhandler.validate_sessions()
|
||||
SESSIONS.validate_sessions()
|
||||
|
||||
class ValidateScripts(Script):
|
||||
"Check script validation regularly"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ from django.db import connection
|
|||
from django.conf import settings
|
||||
from src.utils import reloads
|
||||
from src.config.models import ConfigValue
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.server import initial_setup
|
||||
|
||||
from src.utils.utils import get_evennia_version
|
||||
|
|
@ -77,7 +77,7 @@ class Evennia(object):
|
|||
self.run_initial_setup()
|
||||
|
||||
# we have to null this here.
|
||||
sessionhandler.SESSIONS.session_count(0)
|
||||
SESSIONS.session_count(0)
|
||||
|
||||
self.start_time = time.time()
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ class Evennia(object):
|
|||
"""
|
||||
if not message:
|
||||
message = 'The server has been shutdown. Please check back soon.'
|
||||
sessionhandler.SESSIONS.disconnect_all_sessions(reason=message)
|
||||
SESSIONS.disconnect_all_sessions(reason=message)
|
||||
reactor.callLater(0, reactor.stop)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from django.conf import settings
|
|||
from src.comms.models import Channel
|
||||
from src.utils import logger, reloads
|
||||
from src.commands import cmdhandler
|
||||
from src.server import sessionhandler
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
|
||||
IDLE_TIMEOUT = settings.IDLE_TIMEOUT
|
||||
IDLE_COMMAND = settings.IDLE_COMMAND
|
||||
|
|
@ -75,7 +75,7 @@ class SessionBase(object):
|
|||
# Total number of commands issued.
|
||||
self.cmd_total = 0
|
||||
#self.channels_subscribed = {}
|
||||
sessionhandler.SESSIONS.add_unloggedin_session(self)
|
||||
SESSIONS.add_unloggedin_session(self)
|
||||
# call hook method
|
||||
self.at_connect()
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ class SessionBase(object):
|
|||
reloads.reload_scripts(obj=self.player.character, init_mode=True)
|
||||
|
||||
#add session to connected list
|
||||
sessionhandler.SESSIONS.add_loggedin_session(self)
|
||||
SESSIONS.add_loggedin_session(self)
|
||||
|
||||
#call hook
|
||||
self.at_login()
|
||||
|
|
@ -123,7 +123,7 @@ class SessionBase(object):
|
|||
uaccount.last_login = datetime.now()
|
||||
uaccount.save()
|
||||
self.logged_in = False
|
||||
sessionhandler.SESSIONS.remove_session(self)
|
||||
SESSIONS.remove_session(self)
|
||||
|
||||
def session_validate(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -151,6 +151,14 @@ class SessionHandler(object):
|
|||
num = max(0, num + add)
|
||||
ConfigValue.objects.conf('nr_sessions', str(num))
|
||||
|
||||
def player_count(self):
|
||||
"""
|
||||
Get the number of connected players (not sessions since a player
|
||||
may have more than one session connected if ALLOW_MULTISESSION is True)
|
||||
Only logged-in players are counted here.
|
||||
"""
|
||||
return len(set(sess.uid for sess in self.get_sessions()))
|
||||
|
||||
def sessions_from_player(self, player):
|
||||
"""
|
||||
Given a player, return any matching sessions.
|
||||
|
|
@ -179,6 +187,13 @@ class SessionHandler(object):
|
|||
"""
|
||||
return [sess for sess in self.get_sessions(include_unloggedin=True) if sess.suid and sess.suid == suid]
|
||||
|
||||
def announce_all(self, message):
|
||||
"""
|
||||
Send message to all connected sessions
|
||||
"""
|
||||
for sess in self.get_sessions(include_unloggedin=True):
|
||||
sess.msg(message)
|
||||
|
||||
SESSIONS = SessionHandler()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ found on http://localhost:8020/webclient.)
|
|||
handle these requests and act as a gateway
|
||||
to sessions connected over the webclient.
|
||||
"""
|
||||
import time
|
||||
from hashlib import md5
|
||||
|
||||
from twisted.web import server, resource
|
||||
from twisted.internet import defer
|
||||
|
|
@ -27,7 +29,8 @@ from django.conf import settings
|
|||
from src.utils import utils
|
||||
from src.utils.text2html import parse_html
|
||||
from src.config.models import ConnectScreen
|
||||
from src.server import session, sessionhandler
|
||||
from src.server import session
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
|
||||
SERVERNAME = settings.SERVERNAME
|
||||
ENCODINGS = settings.ENCODINGS
|
||||
|
|
@ -94,8 +97,8 @@ class WebClient(resource.Resource):
|
|||
self.databuffer[suid] = dataentries
|
||||
|
||||
def disconnect(self, suid):
|
||||
"Disconnect session"
|
||||
sess = sessionhandler.SESSIONS.session_from_suid(suid)
|
||||
"Disconnect session with given suid."
|
||||
sess = SESSIONS.session_from_suid(suid)
|
||||
if sess:
|
||||
sess[0].session_disconnect()
|
||||
if self.requests.has_key(suid):
|
||||
|
|
@ -110,32 +113,35 @@ class WebClient(resource.Resource):
|
|||
This is called by render_POST when the client
|
||||
requests an init mode operation (at startup)
|
||||
"""
|
||||
csess = request.getSession() # obs, this is a cookie, not an evennia session!
|
||||
#csess = request.getSession() # obs, this is a cookie, not an evennia session!
|
||||
#csees.expireCallbacks.append(lambda : )
|
||||
suid = csess.uid
|
||||
suid = request.args.get('suid', ['0'])[0]
|
||||
|
||||
remote_addr = request.getClientIP()
|
||||
host_string = "%s (%s:%s)" % (SERVERNAME, request.getHost().host, request.getHost().port)
|
||||
self.requests[suid] = []
|
||||
self.databuffer[suid] = []
|
||||
if suid == '0':
|
||||
# creating a unique id hash string
|
||||
suid = md5(str(time.time())).hexdigest()
|
||||
self.requests[suid] = []
|
||||
self.databuffer[suid] = []
|
||||
|
||||
sess = sessionhandler.SESSIONS.session_from_suid(suid)
|
||||
if not sess:
|
||||
sess = WebClientSession()
|
||||
sess.client = self
|
||||
sess.session_connect(remote_addr, suid)
|
||||
sessionhandler.SESSIONS.add_unloggedin_session(sess)
|
||||
return jsonify({'msg':host_string})
|
||||
sess.client = self
|
||||
sess.session_connect(remote_addr, suid)
|
||||
return jsonify({'msg':host_string, 'suid':suid})
|
||||
|
||||
def mode_input(self, request):
|
||||
"""
|
||||
This is called by render_POST when the client
|
||||
is sending data to the server.
|
||||
"""
|
||||
string = request.args.get('msg', [''])[0]
|
||||
data = request.args.get('data', [None])[0]
|
||||
suid = request.getSession().uid
|
||||
sess = sessionhandler.SESSIONS.session_from_suid(suid)
|
||||
suid = request.args.get('suid', ['0'])[0]
|
||||
if suid == '0':
|
||||
return ''
|
||||
sess = SESSIONS.session_from_suid(suid)
|
||||
if sess:
|
||||
string = request.args.get('msg', [''])[0]
|
||||
data = request.args.get('data', [None])[0]
|
||||
sess[0].at_data_in(string, data)
|
||||
return ''
|
||||
|
||||
|
|
@ -147,16 +153,29 @@ class WebClient(resource.Resource):
|
|||
mechanism: the server will wait to reply until data is
|
||||
available.
|
||||
"""
|
||||
suid = request.getSession().uid
|
||||
suid = request.args.get('suid', ['0'])[0]
|
||||
if suid == '0':
|
||||
return ''
|
||||
|
||||
dataentries = self.databuffer.get(suid, [])
|
||||
if dataentries:
|
||||
return dataentries.pop(0)
|
||||
return dataentries.pop(0)
|
||||
reqlist = self.requests.get(suid, [])
|
||||
request.notifyFinish().addErrback(self._responseFailed, suid, request)
|
||||
reqlist.append(request)
|
||||
self.requests[suid] = reqlist
|
||||
return server.NOT_DONE_YET
|
||||
|
||||
def mode_close(self, request):
|
||||
"""
|
||||
This is called by render_POST when the client is signalling
|
||||
that it is about to be closed.
|
||||
"""
|
||||
suid = request.args.get('suid', ['0'])[0]
|
||||
if suid == '0':
|
||||
self.disconnect(suid)
|
||||
return ''
|
||||
|
||||
def render_POST(self, request):
|
||||
"""
|
||||
This function is what Twisted calls with POST requests coming
|
||||
|
|
@ -176,6 +195,9 @@ class WebClient(resource.Resource):
|
|||
elif dmode == 'receive':
|
||||
# the client is waiting to receive data.
|
||||
return self.mode_receive(request)
|
||||
elif dmode == 'close':
|
||||
# the client is closing
|
||||
return self.mode_close(request)
|
||||
else:
|
||||
# this should not happen if client sends valid data.
|
||||
return ''
|
||||
|
|
@ -234,8 +256,7 @@ class WebClientSession(session.Session):
|
|||
# string handling is similar to telnet
|
||||
if self.encoding:
|
||||
try:
|
||||
string = utils.to_str(string, encoding=self.encoding)
|
||||
#self.client.lineSend(self.suid, ansi.parse_ansi(string, strip_ansi=True))
|
||||
string = utils.to_str(string, encoding=self.encoding)
|
||||
self.client.lineSend(self.suid, parse_html(string))
|
||||
return
|
||||
except Exception:
|
||||
|
|
@ -256,7 +277,7 @@ class WebClientSession(session.Session):
|
|||
self.client.lineSend(self.suid, parse_html(string))
|
||||
def at_data_in(self, string, data=None):
|
||||
"""
|
||||
Input from Player -> Evennia (called by client).
|
||||
Input from Player -> Evennia (called by client protocol).
|
||||
Use of 'data' is up to the client - server implementation.
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ TELNET_PORTS = [4000]
|
|||
# in the section 'Config for Django web features')
|
||||
WEBSERVER_ENABLED = True
|
||||
# A list of ports the Evennia webserver listens on
|
||||
WEBSERVER_PORTS = [8020]
|
||||
WEBSERVER_PORTS = [8000]
|
||||
# Start the evennia ajax client on /webclient
|
||||
# (the webserver must also be running)
|
||||
WEBCLIENT_ENABLED = True
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@ def reload_modules():
|
|||
# We protect e.g. src/ from reload since reloading it in a running
|
||||
# server can create unexpected results (and besides, non-evennia devs
|
||||
# should never need to do that anyway). Updating src requires a server
|
||||
# reboot.
|
||||
# reboot. Modules in except_dirs are considered ok to reload despite being
|
||||
# inside src/
|
||||
protected_dirs = ('src.',)
|
||||
except_dirs = ('src.commands.default.')
|
||||
|
||||
# flag 'dangerous' typeclasses (those which retain a memory
|
||||
# reference, notably Scripts with a timer component) for
|
||||
|
|
@ -43,8 +45,8 @@ def reload_modules():
|
|||
unsafe_modules = list(set(unsafe_modules))
|
||||
|
||||
def safe_dir_to_reload(modpath):
|
||||
"Check so modpath is not a subdir of a protected dir"
|
||||
return not any(modpath.startswith(pdir) for pdir in protected_dirs)
|
||||
"Check so modpath is not a subdir of a protected dir, and not an ok exception"
|
||||
return not any(modpath.startswith(pdir) and not any(modpath.startswith(pdir) for pdir in except_dirs) for pdir in protected_dirs)
|
||||
def safe_mod_to_reload(modpath):
|
||||
"Check so modpath is not in an unsafe module"
|
||||
return not any(mpath.startswith(modpath) for mpath in unsafe_modules)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class TextToHTMLparser(object):
|
|||
normalcode = '\033[0m'
|
||||
tabstop = 4
|
||||
|
||||
re_string = re.compile(r'(?P<htmlchars>[<&>])|(?P<space>^[ \t]+)|(?P<lineend>\r\n|\r|\n)|(?P<protocal>(^|\s)((http|ftp)://.*?))(\s|$)',
|
||||
re_string = re.compile(r'(?P<htmlchars>[<&>])|(?P<space>^[ \t]+)|(?P<lineend>\r\n|\r|\n)|(?P<protocol>(^|\s)((http|ftp)://.*?))(\s|$)',
|
||||
re.S|re.M|re.I)
|
||||
|
||||
def re_color(self, text):
|
||||
|
|
@ -95,7 +95,7 @@ class TextToHTMLparser(object):
|
|||
elif c['space'] == '\t':
|
||||
return ' '*self.tabstop
|
||||
else:
|
||||
url = m.group('protocal')
|
||||
url = m.group('protocol')
|
||||
if url.startswith(' '):
|
||||
prefix = ' '
|
||||
url = url[1:]
|
||||
|
|
|
|||
|
|
@ -320,12 +320,21 @@ def format_table(table, extra_space=1):
|
|||
collumns must have the same number of rows (some positions may be
|
||||
empty though).
|
||||
|
||||
The function formats the columns to be as wide as the wides member
|
||||
The function formats the columns to be as wide as the widest member
|
||||
of each column.
|
||||
|
||||
extra_space defines how much extra padding should minimum be left between
|
||||
collumns.
|
||||
first_row_ansi defines an evential colour string for the first row.
|
||||
|
||||
print the resulting list e.g. with
|
||||
|
||||
for ir, row in enumarate(ftable):
|
||||
if ir == 0:
|
||||
# make first row white
|
||||
string += "\n{w" + ""join(row) + "{n"
|
||||
else:
|
||||
string += "\n" + "".join(row)
|
||||
print string
|
||||
|
||||
"""
|
||||
if not table:
|
||||
|
|
|
|||
|
|
@ -28,15 +28,18 @@ contain the 'mode' of the request to be handled by the protocol:
|
|||
should happen at this point. The server returns a data object
|
||||
with the 'msg' property containing the server address.
|
||||
|
||||
mode 'close' - closes the connection. The server closes the session and does
|
||||
cleanup at this point.
|
||||
*/
|
||||
|
||||
|
||||
// jQuery must be imported by the calling html page before this script
|
||||
// (it comes with Evennia, in media/javascript/jquery-<version>.js)
|
||||
// There are plenty of help on using the jQuery library on http://jquery.com/
|
||||
|
||||
// Server communications
|
||||
|
||||
var CLIENT_HASH = '0'; // variable holding the client id
|
||||
|
||||
function webclient_receive(){
|
||||
// This starts an asynchronous long-polling request. It will either timeout
|
||||
// or receive data from the 'receivedata' url. In both cases a new request will
|
||||
|
|
@ -49,7 +52,7 @@ function webclient_receive(){
|
|||
cache: false, // Forces browser reload independent of cache
|
||||
timeout:30000, // Timeout in ms. After this time a new long-poll will be started.
|
||||
dataType:"json",
|
||||
data: {mode:'receive'},
|
||||
data: {mode:'receive', 'suid':CLIENT_HASH},
|
||||
|
||||
// callback methods
|
||||
|
||||
|
|
@ -66,7 +69,7 @@ function webclient_receive(){
|
|||
function webclient_input(){
|
||||
// Send an input from the player to the server
|
||||
|
||||
var outmsg = $("#inputfield").val() // get data from form
|
||||
var outmsg = $("#inputfield").val(); // get data from form
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
|
|
@ -74,7 +77,7 @@ function webclient_input(){
|
|||
async: true,
|
||||
cache: false,
|
||||
timeout: 30000,
|
||||
data: {mode:'input', msg:outmsg, data:'NoData'},
|
||||
data: {mode:'input', msg:outmsg, data:'NoData', 'suid':CLIENT_HASH},
|
||||
|
||||
//callback methods
|
||||
|
||||
|
|
@ -82,7 +85,7 @@ function webclient_input(){
|
|||
//if (outmsg.length > 0 ) msg_display("inp", outmsg) // echo input on command line
|
||||
history_add(outmsg);
|
||||
HISTORY_POS = 0;
|
||||
$('#inputform')[0].reset() // clear input field
|
||||
$('#inputform')[0].reset(); // clear input field
|
||||
},
|
||||
error: function(XMLHttpRequest, textStatus, errorThrown){
|
||||
msg_display("err", "Error: Server returned an error or timed out. Try resending.");
|
||||
|
|
@ -100,19 +103,20 @@ function webclient_init(){
|
|||
cache: false,
|
||||
timeout: 50000,
|
||||
dataType:"json",
|
||||
data: {mode:'init'},
|
||||
data: {mode:'init', 'suid':CLIENT_HASH},
|
||||
|
||||
// callback methods
|
||||
|
||||
success: function(data){ // called when request to initdata completes
|
||||
$("#connecting").remove() // remove the "connecting ..." message.
|
||||
CLIENT_HASH = data.suid // unique id hash given from server
|
||||
|
||||
setTimeout(function () { // a small timeout to stop 'loading' indicator in Chrome
|
||||
$("#playercount").fadeOut('slow');
|
||||
}, 10000);
|
||||
|
||||
// Report success
|
||||
msg_display('sys',"Connected to " + data.msg + ".")
|
||||
msg_display('sys',"Connected to " + data.msg + ".");
|
||||
|
||||
// Wait for input
|
||||
webclient_receive();
|
||||
|
|
@ -124,6 +128,29 @@ function webclient_init(){
|
|||
});
|
||||
}
|
||||
|
||||
function webclient_close(){
|
||||
// Kill the connection and do house cleaning on the server.
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/webclientdata",
|
||||
async: false,
|
||||
cache: false,
|
||||
timeout: 50000,
|
||||
dataType: "json",
|
||||
data: {mode: 'close', 'suid': CLIENT_HASH},
|
||||
|
||||
success: function(data){
|
||||
CLIENT_HASH = '0';
|
||||
alert("Mud client connection was closed cleanly.");
|
||||
},
|
||||
error: function(XMLHttpRequest, textStatus, errorThrown){
|
||||
CLIENT_HASH = '0';
|
||||
alert("There was an error disconnecting from the mud server.");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// Display messages
|
||||
|
||||
function msg_display(type, msg){
|
||||
|
|
@ -156,17 +183,17 @@ function history_add(input) {
|
|||
// add an entry to history
|
||||
if (input != HISTORY[HISTORY.length-1]) {
|
||||
if (HISTORY.length >= HISTORY_MAX_LENGTH) {
|
||||
HISTORY.shift() // kill oldest history entry
|
||||
HISTORY.shift(); // kill oldest history entry
|
||||
}
|
||||
HISTORY[HISTORY.length-1] = input
|
||||
HISTORY[HISTORY.length] = ''
|
||||
HISTORY[HISTORY.length-1] = input;
|
||||
HISTORY[HISTORY.length] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// Catching keyboard shortcuts
|
||||
|
||||
$(document).keypress( function(event) {
|
||||
var code = event.keyCode ? event.keyCode : event.which
|
||||
var code = event.keyCode ? event.keyCode : event.which;
|
||||
|
||||
// always focus input field
|
||||
$("#inputfield")[0].focus();
|
||||
|
|
@ -192,21 +219,34 @@ $(document).keypress( function(event) {
|
|||
// handler to avoid double-clicks until the ajax request finishes
|
||||
$("#inputsend").one("click", webclient_input)
|
||||
|
||||
// Callback function - called when page has finished loading (gets things going)
|
||||
$(document).ready(function(){
|
||||
|
||||
// remove the "no javascript" warning, since we obviously have javascript
|
||||
$('#noscript').remove()
|
||||
|
||||
// set sizes of elements and reposition them
|
||||
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').height();
|
||||
var inp_w = $('#inputsend').width()
|
||||
$("#messagewindow").css({'height':win_h-inp_h - 20});
|
||||
$("#inputfield").css({'width':win_w-inp_w - 20});
|
||||
}
|
||||
|
||||
setTimeout(function () { // a small timeout to stop 'loading' indicator in Chrome
|
||||
// Callback function - called when page has finished loading (gets things going)
|
||||
$(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();
|
||||
// a small timeout to stop 'loading' indicator in Chrome
|
||||
setTimeout(function () {
|
||||
webclient_init();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// Callback function - called when the browser window resizes
|
||||
$(window).resize(function() {
|
||||
webclient_set_sizes();
|
||||
});
|
||||
|
||||
// Callback function - called when page is closed or moved away from.
|
||||
$(window).unload(function() {
|
||||
webclient_close();
|
||||
});
|
||||
|
|
@ -8,8 +8,7 @@ page and serve it eventual static content.
|
|||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.conf import settings
|
||||
from src.server import sessionhandler
|
||||
from src.config.models import ConfigValue
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
|
||||
def webclient(request):
|
||||
"""
|
||||
|
|
@ -17,7 +16,7 @@ def webclient(request):
|
|||
"""
|
||||
|
||||
# as an example we send the number of connected players to the template
|
||||
pagevars = {'num_players_connected': ConfigValue.objects.conf('nr_sessions')}
|
||||
pagevars = {'num_players_connected': SESSIONS.player_count()}
|
||||
|
||||
context_instance = RequestContext(request)
|
||||
return render_to_response('webclient.html', pagevars, context_instance)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue