mirror of
https://github.com/evennia/evennia.git
synced 2026-03-29 03:57:17 +02:00
Updated parts of server/ dir to google docstrings as per #709.
This commit is contained in:
parent
abff559a61
commit
b2ddd34efd
7 changed files with 382 additions and 85 deletions
|
|
@ -75,15 +75,27 @@ class AmpServerFactory(protocol.ServerFactory):
|
|||
"""
|
||||
def __init__(self, server):
|
||||
"""
|
||||
server: The Evennia server service instance
|
||||
protocol: The protocol the factory creates instances of.
|
||||
Initialize the factory.
|
||||
|
||||
Args:
|
||||
server (Server): The Evennia server service instance.
|
||||
protocol (Protocol): The protocol the factory creates
|
||||
instances of.
|
||||
|
||||
"""
|
||||
self.server = server
|
||||
self.protocol = AMPProtocol
|
||||
|
||||
def buildProtocol(self, addr):
|
||||
"""
|
||||
Start a new connection, and store it on the service object
|
||||
Start a new connection, and store it on the service object.
|
||||
|
||||
Args:
|
||||
addr (str): Connection address. Not used.
|
||||
|
||||
Returns:
|
||||
protocol (Protocol): The created protocol.
|
||||
|
||||
"""
|
||||
#print "Evennia Server connected to Portal at %s." % addr
|
||||
self.server.amp_protocol = AMPProtocol()
|
||||
|
|
@ -95,6 +107,7 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
"""
|
||||
This factory creates an instance of the Portal, an AMPProtocol
|
||||
instances to use to connect
|
||||
|
||||
"""
|
||||
# Initial reconnect delay in seconds.
|
||||
initialDelay = 1
|
||||
|
|
@ -102,12 +115,24 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
maxDelay = 1
|
||||
|
||||
def __init__(self, portal):
|
||||
"""
|
||||
Initializes the client factory.
|
||||
|
||||
Args:
|
||||
portal (Portal): Portal instance.
|
||||
|
||||
"""
|
||||
self.portal = portal
|
||||
self.protocol = AMPProtocol
|
||||
|
||||
def startedConnecting(self, connector):
|
||||
"""
|
||||
Called when starting to try to connect to the MUD server.
|
||||
|
||||
Args:
|
||||
connector (Connector): Twisted Connector instance representing
|
||||
this connection.
|
||||
|
||||
"""
|
||||
pass
|
||||
#print 'AMP started to connect:', connector
|
||||
|
|
@ -115,6 +140,10 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
def buildProtocol(self, addr):
|
||||
"""
|
||||
Creates an AMPProtocol instance when connecting to the server.
|
||||
|
||||
Args:
|
||||
addr (str): Connection address. Not used.
|
||||
|
||||
"""
|
||||
#print "Portal connected to Evennia server at %s." % addr
|
||||
self.resetDelay()
|
||||
|
|
@ -125,6 +154,12 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
def clientConnectionLost(self, connector, reason):
|
||||
"""
|
||||
Called when the AMP connection to the MUD server is lost.
|
||||
|
||||
Args:
|
||||
connector (Connector): Twisted Connector instance representing
|
||||
this connection.
|
||||
reason (str): Eventual text describing why connection was lost.
|
||||
|
||||
"""
|
||||
if hasattr(self, "server_restart_mode"):
|
||||
self.maxDelay = 1
|
||||
|
|
@ -137,6 +172,12 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
def clientConnectionFailed(self, connector, reason):
|
||||
"""
|
||||
Called when an AMP connection attempt to the MUD server fails.
|
||||
|
||||
Args:
|
||||
connector (Connector): Twisted Connector instance representing
|
||||
this connection.
|
||||
reason (str): Eventual text describing why connection failed.
|
||||
|
||||
"""
|
||||
if hasattr(self, "server_restart_mode"):
|
||||
self.maxDelay = 1
|
||||
|
|
@ -150,7 +191,8 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
|
||||
class MsgPortal2Server(amp.Command):
|
||||
"""
|
||||
Message portal -> server
|
||||
Message Portal -> Server
|
||||
|
||||
"""
|
||||
key = "MsgPortal2Server"
|
||||
arguments = [('hashid', amp.String()),
|
||||
|
|
@ -163,7 +205,8 @@ class MsgPortal2Server(amp.Command):
|
|||
|
||||
class MsgServer2Portal(amp.Command):
|
||||
"""
|
||||
Message server -> portal
|
||||
Message Server -> Portal
|
||||
|
||||
"""
|
||||
key = "MsgServer2Portal"
|
||||
arguments = [('hashid', amp.String()),
|
||||
|
|
@ -176,11 +219,11 @@ class MsgServer2Portal(amp.Command):
|
|||
|
||||
class ServerAdmin(amp.Command):
|
||||
"""
|
||||
Portal -> Server
|
||||
Administration Portal -> Server
|
||||
|
||||
Sent when the portal needs to perform admin operations on the
|
||||
server, such as when a new session connects or resyncs
|
||||
|
||||
Sent when the portal needs to perform admin
|
||||
operations on the server, such as when a new
|
||||
session connects or resyncs
|
||||
"""
|
||||
key = "ServerAdmin"
|
||||
arguments = [('hashid', amp.String()),
|
||||
|
|
@ -193,10 +236,11 @@ class ServerAdmin(amp.Command):
|
|||
|
||||
class PortalAdmin(amp.Command):
|
||||
"""
|
||||
Server -> Portal
|
||||
Administration Server -> Portal
|
||||
|
||||
Sent when the server needs to perform admin operations on the
|
||||
portal.
|
||||
|
||||
Sent when the server needs to perform admin
|
||||
operations on the portal.
|
||||
"""
|
||||
key = "PortalAdmin"
|
||||
arguments = [('hashid', amp.String()),
|
||||
|
|
@ -209,11 +253,11 @@ class PortalAdmin(amp.Command):
|
|||
|
||||
class FunctionCall(amp.Command):
|
||||
"""
|
||||
Bidirectional
|
||||
Bidirectional Server <-> Portal
|
||||
|
||||
Sent when either process needs to call an arbitrary function in
|
||||
the other. This does not use the batch-send functionality.
|
||||
|
||||
Sent when either process needs to call an
|
||||
arbitrary function in the other. This does
|
||||
not use the batch-send functionality.
|
||||
"""
|
||||
key = "FunctionCall"
|
||||
arguments = [('module', amp.String()),
|
||||
|
|
@ -224,7 +268,7 @@ class FunctionCall(amp.Command):
|
|||
response = [('result', amp.String())]
|
||||
|
||||
|
||||
# Helper functions
|
||||
# Helper functions for pickling.
|
||||
|
||||
dumps = lambda data: to_str(pickle.dumps(to_str(data), pickle.HIGHEST_PROTOCOL))
|
||||
loads = lambda data: pickle.loads(to_str(data))
|
||||
|
|
@ -237,19 +281,22 @@ loads = lambda data: pickle.loads(to_str(data))
|
|||
class AMPProtocol(amp.AMP):
|
||||
"""
|
||||
This is the protocol that the MUD server and the proxy server
|
||||
communicate to each other with. AMP is a bi-directional protocol, so
|
||||
both the proxy and the MUD use the same commands and protocol.
|
||||
communicate to each other with. AMP is a bi-directional protocol,
|
||||
so both the proxy and the MUD use the same commands and protocol.
|
||||
|
||||
AMP specifies responder methods here and connect them to
|
||||
amp.Command subclasses that specify the datatypes of the
|
||||
input/output of these methods.
|
||||
|
||||
AMP specifies responder methods here and connect them to amp.Command
|
||||
subclasses that specify the datatypes of the input/output of these methods.
|
||||
"""
|
||||
|
||||
# helper methods
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Initialize protocol with some things that need to be
|
||||
in place already before connecting both on portal and server.
|
||||
Initialize protocol with some things that need to be in place
|
||||
already before connecting both on portal and server.
|
||||
|
||||
"""
|
||||
self.min_batch_step = 1.0 / BATCH_RATE
|
||||
self.lastsend = time()
|
||||
|
|
@ -259,13 +306,13 @@ class AMPProtocol(amp.AMP):
|
|||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
This is called when a connection is established
|
||||
between server and portal. AMP calls it on both sides,
|
||||
so we need to make sure to only trigger resync from the
|
||||
portal side.
|
||||
This is called when a connection is established between server
|
||||
and portal. AMP calls it on both sides, so we need to make
|
||||
sure to only trigger resync from the portal side.
|
||||
|
||||
"""
|
||||
self.transport.setTcpNoDelay(True) # this makes for a factor x10 faster sends!
|
||||
# this makes for a factor x10 faster sends!
|
||||
self.transport.setTcpNoDelay(True)
|
||||
if hasattr(self.factory, "portal"):
|
||||
# only the portal has the 'portal' property, so we know we are
|
||||
# on the portal side and can initialize the connection.
|
||||
|
|
@ -280,7 +327,15 @@ class AMPProtocol(amp.AMP):
|
|||
# Error handling
|
||||
|
||||
def errback(self, e, info):
|
||||
"error handler, to avoid dropping connections on server tracebacks."
|
||||
"""
|
||||
Error callback.
|
||||
Handles errors to avoid dropping connections on server tracebacks.
|
||||
|
||||
Args:
|
||||
e (Failure): Deferred error instance.
|
||||
info (str): Error string.
|
||||
|
||||
"""
|
||||
e.trap(Exception)
|
||||
print "AMP Error for %(info)s: %(e)s" % {'info': info,
|
||||
'e': e.getErrorMessage()}
|
||||
|
|
@ -289,8 +344,17 @@ class AMPProtocol(amp.AMP):
|
|||
"""
|
||||
This will batch data together to send fewer, large batches.
|
||||
|
||||
Args:
|
||||
command (AMP Command): A protocol send command.
|
||||
sessid (int): A unique Session id.
|
||||
|
||||
Kwargs:
|
||||
force_direct: send direct
|
||||
force_direct (bool): Send direct, without batching data.
|
||||
|
||||
Returns:
|
||||
deferreds (list or None): A list of deferreds firing with
|
||||
as batch parts get sent (or fails).
|
||||
|
||||
"""
|
||||
#print "batch_send 1:", command, sessid
|
||||
global _SENDBATCH
|
||||
|
|
@ -343,6 +407,17 @@ class AMPProtocol(amp.AMP):
|
|||
This will receive and unpack data sent as a batch. This both
|
||||
handles too-long data as well as batch-sending very fast-
|
||||
arriving commands.
|
||||
|
||||
Args:
|
||||
hashid (str): Unique hash id representing this batch in
|
||||
the cache buffer.
|
||||
data (str): Data coming over the wire.
|
||||
ipart (int): Index of this part of the batch (ipart/nparts)
|
||||
nparts (int): Total number of parts in this batch.
|
||||
|
||||
Returns:
|
||||
data (str or list): The received data.
|
||||
|
||||
"""
|
||||
global _MSGBUFFER
|
||||
if nparts == 1:
|
||||
|
|
@ -364,11 +439,20 @@ class AMPProtocol(amp.AMP):
|
|||
|
||||
def amp_msg_portal2server(self, hashid, data, ipart, nparts):
|
||||
"""
|
||||
Relays message to server. This method is executed on the Server.
|
||||
Relays message to server. This method is executed on the
|
||||
Server.
|
||||
|
||||
Since AMP has a limit of 65355 bytes per message, it's
|
||||
possible the data comes in multiple chunks; if so (nparts>1)
|
||||
we buffer the data and wait for the remaining parts to arrive
|
||||
before continuing.
|
||||
|
||||
Args:
|
||||
hashid (str): Unique hash identifying this data batch.
|
||||
data (str): Data to send (often a part of a batch)
|
||||
ipart (int): Index of this part of the batch.
|
||||
nparts (int): Total number of batches.
|
||||
|
||||
Since AMP has a limit of 65355 bytes per message, it's possible the
|
||||
data comes in multiple chunks; if so (nparts>1) we buffer the data
|
||||
and wait for the remaining parts to arrive before continuing.
|
||||
"""
|
||||
batch = self.batch_recv(hashid, data, ipart, nparts)
|
||||
for (sessid, kwargs) in batch:
|
||||
|
|
@ -382,6 +466,15 @@ class AMPProtocol(amp.AMP):
|
|||
def call_remote_MsgPortal2Server(self, sessid, msg, data=""):
|
||||
"""
|
||||
Access method called by the Portal and executed on the Portal.
|
||||
|
||||
Args:
|
||||
sessid (int): Unique Session id.
|
||||
msg (str): Message to send over the wire.
|
||||
data (str, optional): Optional data.
|
||||
|
||||
Returns:
|
||||
deferred (Deferred): Asynchronous return.
|
||||
|
||||
"""
|
||||
#print "msg portal->server (portal side):", sessid, msg, data
|
||||
return self.batch_send(MsgPortal2Server, sessid,
|
||||
|
|
@ -393,6 +486,18 @@ class AMPProtocol(amp.AMP):
|
|||
def amp_msg_server2portal(self, hashid, data, ipart, nparts):
|
||||
"""
|
||||
Relays message to Portal. This method is executed on the Portal.
|
||||
|
||||
Since AMP has a limit of 65355 bytes per message, it's
|
||||
possible the data comes in multiple chunks; if so (nparts>1)
|
||||
we buffer the data and wait for the remaining parts to arrive
|
||||
before continuing.
|
||||
|
||||
Args:
|
||||
hashid (str): Unique hash identifying this data batch.
|
||||
data (str): Data to send (often a part of a batch)
|
||||
ipart (int): Index of this part of the batch.
|
||||
nparts (int): Total number of batches.
|
||||
|
||||
"""
|
||||
batch = self.batch_recv(hashid, data, ipart, nparts)
|
||||
for (sessid, kwargs) in batch:
|
||||
|
|
@ -406,6 +511,18 @@ class AMPProtocol(amp.AMP):
|
|||
def amp_batch_server2portal(self, hashid, data, ipart, nparts):
|
||||
"""
|
||||
Relays batch data to Portal. This method is executed on the Portal.
|
||||
|
||||
Since AMP has a limit of 65355 bytes per message, it's
|
||||
possible the data comes in multiple chunks; if so (nparts>1)
|
||||
we buffer the data and wait for the remaining parts to arrive
|
||||
before continuing.
|
||||
|
||||
Args:
|
||||
hashid (str): Unique hash identifying this data batch.
|
||||
data (str): Data to send (often a part of a batch)
|
||||
ipart (int): Index of this part of the batch.
|
||||
nparts (int): Total number of batches.
|
||||
|
||||
"""
|
||||
batch = self.batch_recv(hashid, data, ipart, nparts)
|
||||
if batch is not None:
|
||||
|
|
@ -418,7 +535,13 @@ class AMPProtocol(amp.AMP):
|
|||
|
||||
def call_remote_MsgServer2Portal(self, sessid, msg, data=""):
|
||||
"""
|
||||
Access method called by the Server and executed on the Server.
|
||||
Send Message - access method called by the Server and executed on the Server.
|
||||
|
||||
Args:
|
||||
sessid (int): Unique Session id.
|
||||
msg (str): Message to send over the wire.
|
||||
data (str, optional): Extra data.
|
||||
|
||||
"""
|
||||
#print "msg server->portal (server side):", sessid, msg, data
|
||||
return self.batch_send(MsgServer2Portal, sessid, msg=msg, data=data)
|
||||
|
|
@ -429,6 +552,17 @@ class AMPProtocol(amp.AMP):
|
|||
This allows the portal to perform admin
|
||||
operations on the server. This is executed on the Server.
|
||||
|
||||
Since AMP has a limit of 65355 bytes per message, it's
|
||||
possible the data comes in multiple chunks; if so (nparts>1)
|
||||
we buffer the data and wait for the remaining parts to arrive
|
||||
before continuing.
|
||||
|
||||
Args:
|
||||
hashid (str): Unique hash identifying this data batch.
|
||||
data (str): Data to send (often a part of a batch)
|
||||
ipart (int): Index of this part of the batch.
|
||||
nparts (int): Total number of batches.
|
||||
|
||||
"""
|
||||
#print "serveradmin (server side):", hashid, ipart, nparts
|
||||
batch = self.batch_recv(hashid, data, ipart, nparts)
|
||||
|
|
@ -465,7 +599,15 @@ class AMPProtocol(amp.AMP):
|
|||
|
||||
def call_remote_ServerAdmin(self, sessid, operation="", data=""):
|
||||
"""
|
||||
Access method called by the Portal and Executed on the Portal.
|
||||
Administrative access method called by the Portal and Executed
|
||||
on the Portal.
|
||||
|
||||
Args:
|
||||
sessid (int): Session id.
|
||||
operation (char, optional): Identifier for the server operation, as defined by the
|
||||
global variables in `evennia/server/amp.py`.
|
||||
data (str, optional): Data going into the adminstrative operation.
|
||||
|
||||
"""
|
||||
#print "serveradmin (portal side):", sessid, ord(operation), data
|
||||
if hasattr(self.factory, "server_restart_mode"):
|
||||
|
|
@ -478,6 +620,18 @@ class AMPProtocol(amp.AMP):
|
|||
"""
|
||||
This allows the server to perform admin
|
||||
operations on the portal. This is executed on the Portal.
|
||||
|
||||
Since AMP has a limit of 65355 bytes per message, it's
|
||||
possible the data comes in multiple chunks; if so (nparts>1)
|
||||
we buffer the data and wait for the remaining parts to arrive
|
||||
before continuing.
|
||||
|
||||
Args:
|
||||
hashid (str): Unique hash identifying this data batch.
|
||||
data (str): Data to send (often a part of a batch)
|
||||
ipart (int): Index of this part of the batch.
|
||||
nparts (int): Total number of batches.
|
||||
|
||||
"""
|
||||
#print "portaladmin (portal side):", sessid, ord(operation), data
|
||||
batch = self.batch_recv(hashid, data, ipart, nparts)
|
||||
|
|
@ -519,7 +673,17 @@ class AMPProtocol(amp.AMP):
|
|||
|
||||
def call_remote_PortalAdmin(self, sessid, operation="", data=""):
|
||||
"""
|
||||
Access method called by the server side.
|
||||
Administrative access method called by the Server side and executed
|
||||
onthe Portal.
|
||||
|
||||
Args:
|
||||
sessid (int): Session id.
|
||||
operation (char, optional): Identifier for the server
|
||||
operation, as defined by the global variables in
|
||||
`evennia/server/amp.py`.
|
||||
data (str, optional): Data going into the adminstrative
|
||||
operation.
|
||||
|
||||
"""
|
||||
if operation == SSYNC:
|
||||
return self.batch_send(PortalAdmin, sessid, force_direct=True, operation=operation, data=data)
|
||||
|
|
@ -529,8 +693,18 @@ class AMPProtocol(amp.AMP):
|
|||
|
||||
def amp_function_call(self, module, function, args, **kwargs):
|
||||
"""
|
||||
This allows Portal- and Server-process to call an arbitrary function
|
||||
in the other process. It is intended for use by plugin modules.
|
||||
This allows Portal- and Server-process to call an arbitrary
|
||||
function in the other process. It is intended for use by
|
||||
plugin modules.
|
||||
|
||||
Args:
|
||||
module (str or module): The module containing the
|
||||
`function` to call.
|
||||
function (str): The name of the function to call in
|
||||
`module`.
|
||||
args, kwargs (any): These will be used as args/kwargs to
|
||||
`function`.
|
||||
|
||||
"""
|
||||
args = loads(args)
|
||||
kwargs = loads(kwargs)
|
||||
|
|
@ -561,6 +735,7 @@ class AMPProtocol(amp.AMP):
|
|||
Returns:
|
||||
A deferred that fires with the return value of the remote
|
||||
function call
|
||||
|
||||
"""
|
||||
return self.callRemote(FunctionCall,
|
||||
module=modulepath,
|
||||
|
|
|
|||
|
|
@ -315,6 +315,7 @@ ERROR_NODJANGO = \
|
|||
def evennia_version():
|
||||
"""
|
||||
Get the Evennia version info from the main package.
|
||||
|
||||
"""
|
||||
version = "Unknown"
|
||||
try:
|
||||
|
|
@ -338,6 +339,7 @@ def check_main_evennia_dependencies():
|
|||
|
||||
Returns:
|
||||
not_error (bool): True if no dependency error was found.
|
||||
|
||||
"""
|
||||
error = False
|
||||
|
||||
|
|
@ -381,6 +383,7 @@ def set_gamedir(path):
|
|||
"""
|
||||
Set GAMEDIR based on path, by figuring out where the setting file
|
||||
is inside the directory tree.
|
||||
|
||||
"""
|
||||
|
||||
global GAMEDIR
|
||||
|
|
@ -405,6 +408,7 @@ def set_gamedir(path):
|
|||
def create_secret_key():
|
||||
"""
|
||||
Randomly create the secret key for the settings file
|
||||
|
||||
"""
|
||||
import random
|
||||
import string
|
||||
|
|
@ -419,6 +423,7 @@ def create_settings_file():
|
|||
"""
|
||||
Uses the template settings file to build a working
|
||||
settings file.
|
||||
|
||||
"""
|
||||
settings_path = os.path.join(GAMEDIR, "server", "conf", "settings.py")
|
||||
with open(settings_path, 'r') as f:
|
||||
|
|
@ -441,6 +446,10 @@ def create_game_directory(dirname):
|
|||
Initialize a new game directory named dirname
|
||||
at the current path. This means copying the
|
||||
template directory from evennia's root.
|
||||
|
||||
Args:
|
||||
dirname (str): The directory name to create.
|
||||
|
||||
"""
|
||||
global GAMEDIR
|
||||
GAMEDIR = os.path.abspath(os.path.join(CURRENT_DIR, dirname))
|
||||
|
|
@ -454,14 +463,20 @@ def create_game_directory(dirname):
|
|||
|
||||
|
||||
def create_superuser():
|
||||
"Create the superuser player"
|
||||
"""
|
||||
Create the superuser player
|
||||
|
||||
"""
|
||||
print "\nCreate a superuser below. The superuser is Player #1, the 'owner' account of the server.\n"
|
||||
django.core.management.call_command("createsuperuser", interactive=True)
|
||||
|
||||
|
||||
def check_database():
|
||||
"""
|
||||
Check database exists
|
||||
Check so the database exists.
|
||||
|
||||
Returns:
|
||||
exists (bool): `True` if the database exists, otherwise `False`.
|
||||
"""
|
||||
# Check so a database exists and is accessible
|
||||
from django.db import connection
|
||||
|
|
@ -517,7 +532,11 @@ def check_database():
|
|||
|
||||
def getenv():
|
||||
"""
|
||||
Get current environment and add PYTHONPATH
|
||||
Get current environment and add PYTHONPATH.
|
||||
|
||||
Returns:
|
||||
env (dict): Environment global dict.
|
||||
|
||||
"""
|
||||
sep = ";" if os.name == 'nt' else ":"
|
||||
env = os.environ.copy()
|
||||
|
|
@ -527,8 +546,14 @@ def getenv():
|
|||
|
||||
def get_pid(pidfile):
|
||||
"""
|
||||
Get the PID (Process ID) by trying to access
|
||||
an PID file.
|
||||
Get the PID (Process ID) by trying to access an PID file.
|
||||
|
||||
Args:
|
||||
pidfile (str): The path of the pid file.
|
||||
|
||||
Returns:
|
||||
pid (str): The process id.
|
||||
|
||||
"""
|
||||
pid = None
|
||||
if os.path.exists(pidfile):
|
||||
|
|
@ -542,6 +567,10 @@ def del_pid(pidfile):
|
|||
The pidfile should normally be removed after a process has
|
||||
finished, but when sending certain signals they remain, so we need
|
||||
to clean them manually.
|
||||
|
||||
Args:
|
||||
pidfile (str): The path of the pid file.
|
||||
|
||||
"""
|
||||
if os.path.exists(pidfile):
|
||||
os.remove(pidfile)
|
||||
|
|
@ -552,6 +581,15 @@ def kill(pidfile, signal=SIG, succmsg="", errmsg="", restart_file=SERVER_RESTART
|
|||
Send a kill signal to a process based on PID. A customized
|
||||
success/error message will be returned. If clean=True, the system
|
||||
will attempt to manually remove the pid file.
|
||||
|
||||
Args:
|
||||
pidfile (str): The path of the pidfile to get the PID from.
|
||||
signal (int, optional): Signal identifier.
|
||||
succmsg (str, optional): Message to log on success.
|
||||
errmsg (str, optional): Message to log on failure.
|
||||
restart_file (str, optional): Restart file location.
|
||||
restart (bool, optional): Are we in restart mode or not.
|
||||
|
||||
"""
|
||||
pid = get_pid(pidfile)
|
||||
if pid:
|
||||
|
|
@ -579,7 +617,14 @@ def kill(pidfile, signal=SIG, succmsg="", errmsg="", restart_file=SERVER_RESTART
|
|||
|
||||
def show_version_info(about=False):
|
||||
"""
|
||||
Display version info
|
||||
Display version info.
|
||||
|
||||
Args:
|
||||
about (bool): Include ABOUT info as well as version numbers.
|
||||
|
||||
Returns:
|
||||
version_info (str): A complete version info string.
|
||||
|
||||
"""
|
||||
import os, sys
|
||||
import twisted
|
||||
|
|
@ -595,10 +640,15 @@ def show_version_info(about=False):
|
|||
def error_check_python_modules():
|
||||
"""
|
||||
Import settings modules in settings. This will raise exceptions on
|
||||
pure python-syntax issues which are hard to catch gracefully
|
||||
with exceptions in the engine (since they are formatting errors in
|
||||
the python source files themselves). Best they fail already here
|
||||
pure python-syntax issues which are hard to catch gracefully with
|
||||
exceptions in the engine (since they are formatting errors in the
|
||||
python source files themselves). Best they fail already here
|
||||
before we get any further.
|
||||
|
||||
Raises:
|
||||
DeprecationWarning: For trying to access various modules
|
||||
(usually in `settings.py`) which are no longer supported.
|
||||
|
||||
"""
|
||||
from django.conf import settings
|
||||
def imp(path, split=True):
|
||||
|
|
@ -661,8 +711,13 @@ def error_check_python_modules():
|
|||
def init_game_directory(path, check_db=True):
|
||||
"""
|
||||
Try to analyze the given path to find settings.py - this defines
|
||||
the game directory and also sets PYTHONPATH as well as the
|
||||
django path.
|
||||
the game directory and also sets PYTHONPATH as well as the django
|
||||
path.
|
||||
|
||||
Args:
|
||||
path (str): Path to new game directory, including its name.
|
||||
check_db (bool, optional): Check if the databae exists.
|
||||
|
||||
"""
|
||||
# set the GAMEDIR path
|
||||
set_gamedir(path)
|
||||
|
|
@ -758,8 +813,14 @@ def run_dummyrunner(number_of_dummies):
|
|||
"""
|
||||
Start an instance of the dummyrunner
|
||||
|
||||
The dummy players' behavior can be customized by adding a
|
||||
dummyrunner_settings.py config file in the game's conf directory.
|
||||
Args:
|
||||
number_of_dummies (int): The number of dummy players to start.
|
||||
|
||||
Notes:
|
||||
The dummy players' behavior can be customized by adding a
|
||||
´dummyrunner_settings.py´ config file in the game's conf/
|
||||
directory.
|
||||
|
||||
"""
|
||||
number_of_dummies = str(int(number_of_dummies)) if number_of_dummies else 1
|
||||
cmdstr = [sys.executable, EVENNIA_DUMMYRUNNER, "-N", number_of_dummies]
|
||||
|
|
@ -773,8 +834,12 @@ def run_dummyrunner(number_of_dummies):
|
|||
|
||||
def list_settings(keys):
|
||||
"""
|
||||
Display the server settings. We only display
|
||||
the Evennia specific settings here.
|
||||
Display the server settings. We only display the Evennia specific
|
||||
settings here. The result will be printed to the terminal.
|
||||
|
||||
Args:
|
||||
keys (str or list): Setting key or keys to inspect.
|
||||
|
||||
"""
|
||||
from importlib import import_module
|
||||
from evennia.utils import evtable
|
||||
|
|
@ -800,6 +865,7 @@ def list_settings(keys):
|
|||
def run_menu():
|
||||
"""
|
||||
This launches an interactive menu.
|
||||
|
||||
"""
|
||||
while True:
|
||||
# menu loop
|
||||
|
|
@ -864,10 +930,12 @@ def server_operation(mode, service, interactive, profiler):
|
|||
"""
|
||||
Handle argument options given on the command line.
|
||||
|
||||
mode - str; start/stop etc
|
||||
service - str; server, portal or all
|
||||
interactive - bool; use interactive mode or daemon
|
||||
profiler - run the service under the profiler
|
||||
Args:
|
||||
mode (str): Start/stop/restart and so on.
|
||||
service (str): "server", "portal" or "all".
|
||||
interactive (bool). Use interactive mode or daemon.
|
||||
profiler (bool): Run the service under the profiler.
|
||||
|
||||
"""
|
||||
|
||||
cmdstr = [sys.executable, EVENNIA_RUNNER]
|
||||
|
|
@ -936,7 +1004,8 @@ def server_operation(mode, service, interactive, profiler):
|
|||
|
||||
def main():
|
||||
"""
|
||||
Run the evennia main program.
|
||||
Run the evennia launcher main program.
|
||||
|
||||
"""
|
||||
|
||||
# set up argument parser
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ WARNING_POSTGRESQL_FIX = \
|
|||
def create_config_values():
|
||||
"""
|
||||
Creates the initial config values.
|
||||
|
||||
"""
|
||||
ServerConfig.objects.conf("site_name", settings.SERVERNAME)
|
||||
ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT)
|
||||
|
|
@ -53,6 +54,7 @@ def create_config_values():
|
|||
def get_god_player():
|
||||
"""
|
||||
Creates the god user and don't take no for an answer.
|
||||
|
||||
"""
|
||||
try:
|
||||
god_player = PlayerDB.objects.get(id=1)
|
||||
|
|
@ -64,6 +66,7 @@ def get_god_player():
|
|||
def create_objects():
|
||||
"""
|
||||
Creates the #1 player and Limbo room.
|
||||
|
||||
"""
|
||||
|
||||
print " Creating objects (Player #1 and Limbo room) ..."
|
||||
|
|
@ -122,6 +125,7 @@ def create_objects():
|
|||
def create_channels():
|
||||
"""
|
||||
Creates some sensible default channels.
|
||||
|
||||
"""
|
||||
print " Creating default channels ..."
|
||||
|
||||
|
|
@ -137,6 +141,7 @@ def at_initial_setup():
|
|||
setup. Called very last in the sequence. It tries to import and
|
||||
srun a module settings.AT_INITIAL_SETUP_HOOK_MODULE and will fail
|
||||
silently if this does not exist or fails to load.
|
||||
|
||||
"""
|
||||
modname = settings.AT_INITIAL_SETUP_HOOK_MODULE
|
||||
if not modname:
|
||||
|
|
@ -152,10 +157,11 @@ def at_initial_setup():
|
|||
|
||||
def reset_server():
|
||||
"""
|
||||
We end the initialization by resetting the server. This
|
||||
makes sure the first login is the same as all the following
|
||||
ones, particularly it cleans all caches for the special objects.
|
||||
It also checks so the warm-reset mechanism works as it should.
|
||||
We end the initialization by resetting the server. This makes sure
|
||||
the first login is the same as all the following ones,
|
||||
particularly it cleans all caches for the special objects. It
|
||||
also checks so the warm-reset mechanism works as it should.
|
||||
|
||||
"""
|
||||
from evennia.server.sessionhandler import SESSIONS
|
||||
print " Initial setup complete. Restarting Server once."
|
||||
|
|
@ -164,9 +170,14 @@ def reset_server():
|
|||
|
||||
def handle_setup(last_step):
|
||||
"""
|
||||
Main logic for the module. It allows for restarting
|
||||
the initialization at any point if one of the modules
|
||||
should crash.
|
||||
Main logic for the module. It allows for restarting the
|
||||
initialization at any point if one of the modules should crash.
|
||||
|
||||
Args:
|
||||
last_step (int): The last stored successful step, for starting
|
||||
over on errors. If `< 0`, initialization has finished and no
|
||||
steps need to be redone.
|
||||
|
||||
"""
|
||||
|
||||
if last_step < 0:
|
||||
|
|
|
|||
|
|
@ -6,22 +6,31 @@ from django.db import models
|
|||
|
||||
class ServerConfigManager(models.Manager):
|
||||
"""
|
||||
This ServerConfigManager implements methods for searching
|
||||
and manipulating ServerConfigs directly from the database.
|
||||
This ServerConfigManager implements methods for searching and
|
||||
manipulating ServerConfigs directly from the database.
|
||||
|
||||
These methods will all return database objects
|
||||
(or QuerySets) directly.
|
||||
These methods will all return database objects (or QuerySets)
|
||||
directly.
|
||||
|
||||
ServerConfigs are used to store certain persistent settings for the
|
||||
server at run-time.
|
||||
|
||||
Evennia-specific:
|
||||
conf
|
||||
ServerConfigs are used to store certain persistent settings for
|
||||
the server at run-time.
|
||||
|
||||
"""
|
||||
def conf(self, key=None, value=None, delete=False, default=None):
|
||||
"""
|
||||
Access and manipulate config values
|
||||
Add, retrieve and manipulate config values.
|
||||
|
||||
Args:
|
||||
key (str, optional): Name of config.
|
||||
value (str, optional): Data to store in this config value.
|
||||
delete (bool, optional): If `True`, delete config with `key`.
|
||||
default (str, optional): Use when retrieving a config value
|
||||
by a key that does not exist.
|
||||
Returns:
|
||||
all (list): If `key` was not given - all stored config values.
|
||||
value (str): If `key` was given, this is the stored value, or
|
||||
`default` if no matching `key` was found.
|
||||
|
||||
"""
|
||||
if not key:
|
||||
return self.all()
|
||||
|
|
@ -43,8 +52,13 @@ class ServerConfigManager(models.Manager):
|
|||
|
||||
def get_mysql_db_version(self):
|
||||
"""
|
||||
This is a helper method for getting the version string
|
||||
of a mysql database.
|
||||
This is a helper method for specifically getting the version
|
||||
string of a MySQL database.
|
||||
|
||||
Returns:
|
||||
mysql_version (str): The currently used mysql database
|
||||
version.
|
||||
|
||||
"""
|
||||
from django.db import connection
|
||||
conn = connection.cursor()
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ class ServerConfig(WeakSharedMemoryModel):
|
|||
On-the fly storage of global settings.
|
||||
|
||||
Properties defined on ServerConfig:
|
||||
key - main identifier
|
||||
value - value stored in key. This is a pickled storage.
|
||||
|
||||
- key: Main identifier
|
||||
- value: Value stored in key. This is a pickled storage.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -112,7 +113,12 @@ class ServerConfig(WeakSharedMemoryModel):
|
|||
|
||||
def store(self, key, value):
|
||||
"""
|
||||
Wrap the storage (handles pickling)
|
||||
Wrap the storage.
|
||||
|
||||
Args:
|
||||
key (str): The name of this store.
|
||||
value (str): The data to store with this `key`.
|
||||
|
||||
"""
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ def oob_report(session, *args, **kwargs):
|
|||
Notes:
|
||||
When the property updates, the monitor will send a MSDP_ARRAY
|
||||
to the session of the form `(SEND, fieldname, new_value)`
|
||||
|
||||
Examples:
|
||||
("REPORT", "CHARACTER_NAME")
|
||||
("MSDP_TABLE", "CHARACTER_NAME", "Amanda")
|
||||
|
|
@ -268,6 +269,11 @@ def oob_return_field_report(session, fieldname, obj, *args, **kwargs):
|
|||
changes. It is not part of the official MSDP specification but is
|
||||
a callback used by the monitor to format the result before sending
|
||||
it on.
|
||||
|
||||
Args:
|
||||
session (Session): The Session object controlling this oob function.
|
||||
fieldname (str): The name of the Field to report on.
|
||||
|
||||
"""
|
||||
session.msg(oob=("MSDP_TABLE", (),
|
||||
{fieldname: to_str(getattr(obj, fieldname), force_string=True)}))
|
||||
|
|
@ -283,6 +289,11 @@ def oob_return_attribute_report(session, fieldname, obj, *args, **kwargs):
|
|||
This command is not part of the official MSDP specification but is
|
||||
a callback used by the monitor to format the result before sending
|
||||
it on.
|
||||
|
||||
Args:
|
||||
session (Session): The Session object controlling this oob function.
|
||||
fieldname (str): The name of the Attribute to report on.
|
||||
|
||||
"""
|
||||
session.msg(oob=("MSDP_TABLE", (),
|
||||
{obj.db_key: to_str(getattr(obj, fieldname), force_string=True)}))
|
||||
|
|
@ -292,6 +303,10 @@ def oob_return_attribute_report(session, fieldname, obj, *args, **kwargs):
|
|||
def oob_unreport(session, *args, **kwargs):
|
||||
"""
|
||||
This removes tracking for the given data.
|
||||
|
||||
Args:
|
||||
session (Session): Session controling this command.
|
||||
|
||||
"""
|
||||
obj = session.get_puppet_or_player()
|
||||
if obj:
|
||||
|
|
@ -330,6 +345,7 @@ def oob_list(session, mode, *args, **kwargs):
|
|||
Examples:
|
||||
oob in: LIST COMMANDS
|
||||
oob out: (COMMANDS, (SEND, REPORT, LIST, ...)
|
||||
|
||||
"""
|
||||
mode = mode.upper()
|
||||
if mode == "COMMANDS":
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class OOBFieldMonitor(object):
|
|||
the update() method w ill be called by the
|
||||
save mechanism, which in turn will call the
|
||||
user-customizable func()
|
||||
|
||||
"""
|
||||
def __init__(self, obj):
|
||||
"""
|
||||
|
|
@ -50,14 +51,19 @@ class OOBFieldMonitor(object):
|
|||
|
||||
Args:
|
||||
obj (Object): object handler is defined on.
|
||||
|
||||
"""
|
||||
self.obj = obj
|
||||
self.subscribers = defaultdict(list)
|
||||
|
||||
def __call__(self, fieldname):
|
||||
"""
|
||||
Called by the save() mechanism when the given
|
||||
field has updated.
|
||||
Called by the save() mechanism when the given field has
|
||||
updated.
|
||||
|
||||
Args:
|
||||
fieldname (str): The field to monitor
|
||||
|
||||
"""
|
||||
for sessid, oobtuples in self.subscribers.items():
|
||||
# oobtuples is a list [(oobfuncname, args, kwargs), ...],
|
||||
|
|
@ -73,12 +79,13 @@ class OOBFieldMonitor(object):
|
|||
Args:
|
||||
sessid (int): Session id
|
||||
oobfuncname (str): oob command to call when field updates
|
||||
args,kwargs: arguments to pass to oob commjand
|
||||
args,kwargs (any): arguments to pass to oob commjand
|
||||
|
||||
Notes:
|
||||
Each sessid may have a list of (oobfuncname, args, kwargs)
|
||||
tuples, all of which will be executed when the
|
||||
field updates.
|
||||
|
||||
"""
|
||||
self.subscribers[sessid].append((oobfuncname, args, kwargs))
|
||||
|
||||
|
|
@ -88,7 +95,6 @@ class OOBFieldMonitor(object):
|
|||
|
||||
Args:
|
||||
sessid(int): Session id
|
||||
Keyword Args:
|
||||
oobfuncname (str, optional): Only delete this cmdname.
|
||||
If not given, delete all.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue