Merge remote-tracking branch 'upstream/master'

This commit is contained in:
luyijun 2014-10-22 00:37:49 +08:00
commit 73e57422c7
13 changed files with 66 additions and 34 deletions

View file

@ -62,8 +62,6 @@ def _init_command(mcs, **kwargs):
if hasattr(mcs, 'arg_regex') and isinstance(mcs.arg_regex, basestring):
mcs.arg_regex = re.compile(r"%s" % mcs.arg_regex, re.I)
else:
mcs.arg_regex = None
if not hasattr(mcs, "auto_help"):
mcs.auto_help = True
if not hasattr(mcs, 'is_exit'):
@ -140,14 +138,16 @@ class Command(object):
locks = ""
# used by the help system to group commands in lists.
help_category = "general"
# This allows to turn off auto-help entry creation for individual commands.
auto_help = True
# optimization for quickly separating exit-commands from normal commands
is_exit = False
# define the command not only by key but by the regex form of its arguments
arg_regex = None
# auto-set (by Evennia on command instantiation) are:
# obj - which object this command is defined on
# sessid - which session-id (if any) is responsible for
# triggering this command
#
# sessid - which session-id (if any) is responsible for triggering this command
def __init__(self, **kwargs):
"""the lockhandler works the same as for objects.

View file

@ -195,7 +195,7 @@ class TickerHandler(object):
self.save_name = save_name
self.ticker_pool = self.ticker_pool_class()
def _store_key(self, obj, interval):
def _store_key(self, obj, interval, idstring=""):
"""
Tries to create a store_key for the object.
Returns a tuple (isdb, store_key) where isdb
@ -224,7 +224,7 @@ class TickerHandler(object):
objkey = id(obj)
isdb = False
# return sidb and store_key
return isdb, (objkey, interval)
return isdb, (objkey, interval, idstring)
def save(self):
"""
@ -237,9 +237,11 @@ class TickerHandler(object):
start_delays = dict((interval, ticker.task.next_call_time())
for interval, ticker in self.ticker_pool.tickers.items())
# update the timers for the tickers
for (obj, interval), (args, kwargs) in self.ticker_storage.items():
#for (obj, interval, idstring), (args, kwargs) in self.ticker_storage.items():
for store_key, (args, kwargs) in self.ticker_storage.items():
interval = store_key[1]
# this is a mutable, so it's updated in-place in ticker_storage
kwargs["_start_delay"] = start_delays.get(interval, None)
ServerConfig.objects.conf(key=self.save_name,
value=dbserialize(self.ticker_storage))
else:
@ -254,30 +256,34 @@ class TickerHandler(object):
if ticker_storage:
self.ticker_storage = dbunserialize(ticker_storage)
#print "restore:", self.ticker_storage
for (obj, interval), (args, kwargs) in self.ticker_storage.items():
for store_key, (args, kwargs) in self.ticker_storage.items():
if len(store_key) == 2:
# old form of store_key - update it
store_key = (store_key[0], store_key[1], "")
obj, interval, idstring = store_key
obj = unpack_dbobj(obj)
_, store_key = self._store_key(obj, interval)
_, store_key = self._store_key(obj, interval, idstring)
self.ticker_pool.add(store_key, obj, interval, *args, **kwargs)
def add(self, obj, interval, *args, **kwargs):
def add(self, obj, interval, idstring="", *args, **kwargs):
"""
Add object to tickerhandler. The object must have an at_tick
method. This will be called every interval seconds until the
object is unsubscribed from the ticker.
"""
isdb, store_key = self._store_key(obj, interval)
isdb, store_key = self._store_key(obj, interval, idstring)
if isdb:
self.ticker_storage[store_key] = (args, kwargs)
self.save()
self.ticker_pool.add(store_key, obj, interval, *args, **kwargs)
def remove(self, obj, interval=None):
def remove(self, obj, interval=None, idstring=""):
"""
Remove object from ticker, or only this object ticking
at a given interval.
"""
if interval:
isdb, store_key = self._store_key(obj, interval)
isdb, store_key = self._store_key(obj, interval, idstring)
if isdb:
self.ticker_storage.pop(store_key, None)
self.save()
@ -287,7 +293,7 @@ class TickerHandler(object):
intervals = self.ticker_pool.tickers.keys()
should_save = False
for interval in intervals:
isdb, store_key = self._store_key(obj, interval)
isdb, store_key = self._store_key(obj, interval, idstring)
if isdb:
self.ticker_storage.pop(store_key, None)
should_save = True

View file

@ -28,6 +28,10 @@ def mxp_parse(text):
"""
Replaces links to the correct format for MXP.
"""
text = text.replace("&", "&") \
.replace("<", "&lt;") \
.replace(">", "&gt;")
text = LINKS_SUB.sub(MXP_SEND, text)
return text
@ -47,6 +51,7 @@ class Mxp(object):
Client does not support MXP.
"""
self.protocol.protocol_flags["MXP"] = False
self.protocol.handshake_done()
def do_mxp(self, option):
"""

View file

@ -64,6 +64,15 @@ class PortalSessionHandler(SessionHandler):
# only use if session already has sessid (i.e. has already connected)
sessdata = session.get_sync_data()
if self.portal.amp_protocol:
# we only send sessdata that should not have changed
# at the server level at this point
sessdata = dict((key, val) for key, val in sessdata.items() if key in ("protocol_key",
"address",
"sessid",
"suid",
"conn_time",
"protocol_flags",
"server_data",))
self.portal.amp_protocol.call_remote_ServerAdmin(session.sessid,
operation=PCONNSYNC,
data=sessdata)

View file

@ -50,6 +50,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
self.msdp = msdp.Msdp(self)
# mxp support
self.mxp = Mxp(self)
# keepalive watches for dead links
self.transport.setTcpKeepAlive(1)
# add this new connection to sessionhandler so
# the Server becomes aware of it.
self.sessionhandler.connect(self)
@ -258,6 +260,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
if prompt:
# Send prompt separately
prompt = ansi.parse_ansi(_RE_N.sub("", prompt) + "{n", strip_ansi=nomarkup, xterm256=xterm256)
if mxp:
prompt = mxp_parse(prompt)
prompt = prompt.replace(IAC, IAC + IAC).replace('\n', '\r\n')
prompt += IAC + GA
self.transport.write(mccp_compress(self, prompt))

View file

@ -46,6 +46,8 @@ class WebSocketClient(Protocol, Session):
"""
client_address = self.transport.client
self.init_session("websocket", client_address, self.factory.sessionhandler)
# watch for dead links
self.transport.setTcpKeepAlive(1)
self.sessionhandler.connect(self)
def disconnect(self, reason=None):
@ -122,10 +124,10 @@ class WebSocketClient(Protocol, Session):
oobstruct = self.sessionhandler.oobstruct_parser(kwargs.pop("oob"))
#print "oob data_out:", "OOB" + json.dumps(oobstruct)
self.sendLine("OOB" + json.dumps(oobstruct))
if "prompt" in kwargs:
self.sendLine("PROMPT" + kwargs["prompt"])
raw = kwargs.get("raw", False)
nomarkup = kwargs.get("nomarkup", False)
if "prompt" in kwargs:
self.sendLine("PROMPT" + parse_html(kwargs["prompt"], strip_ansi=nomarkup))
if raw:
self.sendLine(text)
else:

View file

@ -234,12 +234,6 @@ class ServerSession(Session):
Send Evennia -> User
"""
text = text if text else ""
#if text is None:
# text = ""
#else:
# text = to_unicode(text)
# text = to_str(text, self.encoding)
self.sessionhandler.data_out(self, text=text, **kwargs)
def __eq__(self, other):

View file

@ -95,7 +95,7 @@ class Session(object):
and loads it into the correct properties of the session.
"""
for propname, value in sessdata.items():
self.__dict__[propname] = value
setattr(self, propname, value)
def at_sync(self):
"""

View file

@ -220,6 +220,11 @@ class ServerSessionHandler(SessionHandler):
sessid = portalsessiondata.get("sessid")
session = self.sessions.get(sessid)
if session:
# since some of the session properties may have had
# a chance to change already before the portal gets here
# the portal doesn't send all sessiondata here, but only
# ones which should only be changed from portal (like
# protocol_flags etc)
session.load_sync_data(portalsessiondata)
def portal_disconnect(self, sessid):
@ -339,7 +344,7 @@ class ServerSessionHandler(SessionHandler):
session.logged_in = True
# sync the portal to the session
sessdata = session.get_sync_data()
sessdata = {"logged_in": True}
if not testmode:
self.server.amp_protocol.call_remote_PortalAdmin(session.sessid,
operation=SLOGIN,
@ -407,7 +412,7 @@ class ServerSessionHandler(SessionHandler):
def validate_sessions(self):
"""
Check all currently connected sessions (logged in and not)
and see if any are dead.
and see if any are dead or idle
"""
tcurr = time.time()
reason = _("Idle timeout exceeded, disconnecting.")

View file

@ -305,11 +305,15 @@ def create_script(typeclass, key=None, obj=None, player=None, locks=None,
if persistent is not None:
new_script.persistent = persistent
# must do this before starting the script since some
# scripts may otherwise run for a very short time and
# try to delete itself before we have a time to save it.
new_db_script.save()
# a new created script should usually be started.
if autostart:
new_script.start()
new_db_script.save()
return new_script
#alias
script = create_script

View file

@ -782,7 +782,8 @@ def mod_import(module):
def all_from_module(module):
"""
Return all global-level variables from a module as a dict
Return all global-level variables from a module as a dict.
Ignores modules and variable names starting with an underscore.
"""
mod = mod_import(module)
if not mod: