Fixed bugs, made server start. Still cannot reload.
This commit is contained in:
parent
6441859e61
commit
ab052b8301
9 changed files with 394 additions and 327 deletions
377
bin/evennia
377
bin/evennia
|
|
@ -291,6 +291,22 @@ ERROR_NODJANGO = \
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
def evennia_version():
|
||||||
|
"""
|
||||||
|
Get the Evennia version info from the main package.
|
||||||
|
"""
|
||||||
|
version = "Unknown"
|
||||||
|
with open(os.path.join(EVENNIA_ROOT, "VERSION.txt"), 'r') as f:
|
||||||
|
version = f.read().strip()
|
||||||
|
try:
|
||||||
|
version = "%s (rev %s)" % (version, check_output("git rev-parse --short HEAD", shell=True, cwd=EVENNIA_ROOT).strip())
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
return version
|
||||||
|
|
||||||
|
EVENNIA_VERSION = evennia_version()
|
||||||
|
|
||||||
|
|
||||||
def check_main_evennia_dependencies():
|
def check_main_evennia_dependencies():
|
||||||
"""
|
"""
|
||||||
Checks and imports the Evennia dependencies. This must be done
|
Checks and imports the Evennia dependencies. This must be done
|
||||||
|
|
@ -354,22 +370,6 @@ def set_gamedir(path):
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
def evennia_version():
|
|
||||||
"""
|
|
||||||
Get the Evennia version info from the main package.
|
|
||||||
"""
|
|
||||||
version = "Unknown"
|
|
||||||
with open(os.path.join(EVENNIA_ROOT, "VERSION.txt"), 'r') as f:
|
|
||||||
version = f.read().strip()
|
|
||||||
try:
|
|
||||||
version = "%s (rev %s)" % (version, check_output("git rev-parse --short HEAD", shell=True, cwd=EVENNIA_ROOT).strip())
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
return version
|
|
||||||
|
|
||||||
EVENNIA_VERSION = evennia_version()
|
|
||||||
|
|
||||||
|
|
||||||
def create_secret_key():
|
def create_secret_key():
|
||||||
"""
|
"""
|
||||||
Randomly create the secret key for the settings file
|
Randomly create the secret key for the settings file
|
||||||
|
|
@ -422,6 +422,166 @@ def create_game_directory(dirname):
|
||||||
create_settings_file()
|
create_settings_file()
|
||||||
|
|
||||||
|
|
||||||
|
def create_superuser():
|
||||||
|
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(exit_on_error=False):
|
||||||
|
"""
|
||||||
|
Check database exists and has a superuser
|
||||||
|
"""
|
||||||
|
# Check so a database exists and is accessible
|
||||||
|
from django.db import connection
|
||||||
|
tables = connection.introspection.get_table_list(connection.cursor())
|
||||||
|
if tables and u'players_playerdb' in tables:
|
||||||
|
# database exists and seems set up. Initialize evennia.
|
||||||
|
import evennia
|
||||||
|
evennia.init()
|
||||||
|
else:
|
||||||
|
if exit_on_error:
|
||||||
|
print ERROR_DATABASE.format(traceback=e)
|
||||||
|
sys.exit()
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Try to get Player#1
|
||||||
|
from evennia.players.models import PlayerDB
|
||||||
|
try:
|
||||||
|
PlayerDB.objects.get(id=1)
|
||||||
|
except PlayerDB.DoesNotExist:
|
||||||
|
# no superuser yet. We need to create it.
|
||||||
|
create_superuser()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def getenv():
|
||||||
|
"""
|
||||||
|
Get current environment and add PYTHONPATH
|
||||||
|
"""
|
||||||
|
sep = ";" if os.name == 'nt' else ":"
|
||||||
|
env = os.environ.copy()
|
||||||
|
env['PYTHONPATH'] = sep.join(sys.path)
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def get_pid(pidfile):
|
||||||
|
"""
|
||||||
|
Get the PID (Process ID) by trying to access
|
||||||
|
an PID file.
|
||||||
|
"""
|
||||||
|
pid = None
|
||||||
|
if os.path.exists(pidfile):
|
||||||
|
f = open(pidfile, 'r')
|
||||||
|
pid = f.read()
|
||||||
|
return pid
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
if os.path.exists(pidfile):
|
||||||
|
os.remove(pidfile)
|
||||||
|
|
||||||
|
|
||||||
|
def kill(pidfile, signal=SIG, succmsg="", errmsg="", restart_file=SERVER_RESTART, restart="reload"):
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
pid = get_pid(pidfile)
|
||||||
|
if pid:
|
||||||
|
if os.name == 'nt':
|
||||||
|
if sys.version < "2.7":
|
||||||
|
print "Windows requires Python 2.7 or higher for this operation."
|
||||||
|
return
|
||||||
|
os.remove(pidfile)
|
||||||
|
# set restart/norestart flag
|
||||||
|
if restart == 'reload':
|
||||||
|
django.core.management.call_command('collectstatic', interactive=False, verbosity=0)
|
||||||
|
with open(restart_file, 'w') as f:
|
||||||
|
f.write(str(restart))
|
||||||
|
try:
|
||||||
|
os.kill(int(pid), signal)
|
||||||
|
except OSError:
|
||||||
|
print "Process %(pid)s could not be signalled. The PID file '%(pidfile)s' seems stale. Try removing it." % {'pid': pid, 'pidfile': pidfile}
|
||||||
|
return
|
||||||
|
print "Evennia:", succmsg
|
||||||
|
return
|
||||||
|
print "Evennia:", errmsg
|
||||||
|
|
||||||
|
|
||||||
|
def show_version_info(about=False):
|
||||||
|
"""
|
||||||
|
Display version info
|
||||||
|
"""
|
||||||
|
import os, sys
|
||||||
|
import twisted
|
||||||
|
import django
|
||||||
|
|
||||||
|
return VERSION_INFO.format(version=EVENNIA_VERSION,
|
||||||
|
about=ABOUT_INFO if about else "",
|
||||||
|
os=os.name, python=sys.version.split()[0],
|
||||||
|
twisted=twisted.version.short(),
|
||||||
|
django=django.get_version())
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
before we get any further.
|
||||||
|
"""
|
||||||
|
from django.conf import settings
|
||||||
|
def imp(path, split=True):
|
||||||
|
mod, fromlist = path, "None"
|
||||||
|
if split:
|
||||||
|
mod, fromlist = path.rsplit('.', 1)
|
||||||
|
__import__(mod, fromlist=[fromlist])
|
||||||
|
|
||||||
|
# core modules
|
||||||
|
imp(settings.COMMAND_PARSER)
|
||||||
|
imp(settings.SEARCH_AT_RESULT)
|
||||||
|
imp(settings.SEARCH_AT_MULTIMATCH_INPUT)
|
||||||
|
imp(settings.CONNECTION_SCREEN_MODULE)
|
||||||
|
#imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
|
||||||
|
for path in settings.LOCK_FUNC_MODULES:
|
||||||
|
imp(path, split=False)
|
||||||
|
# cmdsets
|
||||||
|
|
||||||
|
deprstring = "settings.%s should be renamed to %s. If defaults are used, " \
|
||||||
|
"their path/classname must be updated (see evennia/settings_default.py)."
|
||||||
|
if hasattr(settings, "CMDSET_DEFAULT"):
|
||||||
|
raise DeprecationWarning(deprstring % ("CMDSET_DEFAULT", "CMDSET_CHARACTER"))
|
||||||
|
if hasattr(settings, "CMDSET_OOC"):
|
||||||
|
raise DeprecationWarning(deprstring % ("CMDSET_OOC", "CMDSET_PLAYER"))
|
||||||
|
if settings.WEBSERVER_ENABLED and not isinstance(settings.WEBSERVER_PORTS[0], tuple):
|
||||||
|
raise DeprecationWarning("settings.WEBSERVER_PORTS must be on the form [(proxyport, serverport), ...]")
|
||||||
|
if hasattr(settings, "BASE_COMM_TYPECLASS"):
|
||||||
|
raise DeprecationWarning(deprstring % ("BASE_COMM_TYPECLASS", "BASE_CHANNEL_TYPECLASS"))
|
||||||
|
if hasattr(settings, "COMM_TYPECLASS_PATHS"):
|
||||||
|
raise DeprecationWarning(deprstring % ("COMM_TYPECLASS_PATHS", "CHANNEL_TYPECLASS_PATHS"))
|
||||||
|
if hasattr(settings, "CHARACTER_DEFAULT_HOME"):
|
||||||
|
raise DeprecationWarning("settings.CHARACTER_DEFAULT_HOME should be renamed to DEFAULT_HOME. " \
|
||||||
|
"See also settings.START_LOCATION (see evennia/settings_default.py).")
|
||||||
|
|
||||||
|
from evennia.commands import cmdsethandler
|
||||||
|
if not cmdsethandler.import_cmdset(settings.CMDSET_UNLOGGEDIN, None): print "Warning: CMDSET_UNLOGGED failed to load!"
|
||||||
|
if not cmdsethandler.import_cmdset(settings.CMDSET_CHARACTER, None): print "Warning: CMDSET_CHARACTER failed to load"
|
||||||
|
if not cmdsethandler.import_cmdset(settings.CMDSET_PLAYER, None): print "Warning: CMDSET_PLAYER failed to load"
|
||||||
|
# typeclasses
|
||||||
|
imp(settings.BASE_PLAYER_TYPECLASS)
|
||||||
|
imp(settings.BASE_OBJECT_TYPECLASS)
|
||||||
|
imp(settings.BASE_CHARACTER_TYPECLASS)
|
||||||
|
imp(settings.BASE_ROOM_TYPECLASS)
|
||||||
|
imp(settings.BASE_EXIT_TYPECLASS)
|
||||||
|
imp(settings.BASE_SCRIPT_TYPECLASS)
|
||||||
|
|
||||||
|
|
||||||
def init_game_directory(path):
|
def init_game_directory(path):
|
||||||
"""
|
"""
|
||||||
Try to analyze the given path to find settings.py - this defines
|
Try to analyze the given path to find settings.py - this defines
|
||||||
|
|
@ -450,12 +610,8 @@ def init_game_directory(path):
|
||||||
print ERROR_SETTINGS
|
print ERROR_SETTINGS
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
# testing the main library import. If there are errors in importing
|
# this will both check the database and initialize the evennia dir.
|
||||||
# the main library, it should show here.
|
check_database()
|
||||||
evennia = importlib.import_module("evennia")
|
|
||||||
|
|
||||||
if check_database():
|
|
||||||
evennia.init()
|
|
||||||
|
|
||||||
# set up the Evennia executables and log file locations
|
# set up the Evennia executables and log file locations
|
||||||
global SERVER_PY_FILE, PORTAL_PY_FILE
|
global SERVER_PY_FILE, PORTAL_PY_FILE
|
||||||
|
|
@ -517,107 +673,6 @@ def init_game_directory(path):
|
||||||
print INFO_WINDOWS_BATFILE.format(twistd_path=twistd_path)
|
print INFO_WINDOWS_BATFILE.format(twistd_path=twistd_path)
|
||||||
|
|
||||||
|
|
||||||
def getenv():
|
|
||||||
"""
|
|
||||||
Get current environment and add PYTHONPATH
|
|
||||||
"""
|
|
||||||
sep = ";" if os.name == 'nt' else ":"
|
|
||||||
env = os.environ.copy()
|
|
||||||
env['PYTHONPATH'] = sep.join(sys.path)
|
|
||||||
return env
|
|
||||||
|
|
||||||
|
|
||||||
def create_database():
|
|
||||||
print "\nCreating a database ...\n"
|
|
||||||
django.core.management.call_command("migrate", interactive=False)
|
|
||||||
print "\n ... database initialized.\n"
|
|
||||||
|
|
||||||
|
|
||||||
def create_superuser():
|
|
||||||
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(exit_on_error=False):
|
|
||||||
# Check so a database exists and is accessible
|
|
||||||
from django.db import DatabaseError
|
|
||||||
from evennia.players.models import PlayerDB
|
|
||||||
try:
|
|
||||||
PlayerDB.objects.get(id=1)
|
|
||||||
except DatabaseError, e:
|
|
||||||
if exit_on_error:
|
|
||||||
print ERROR_DATABASE.format(traceback=e)
|
|
||||||
sys.exit()
|
|
||||||
return False
|
|
||||||
except PlayerDB.DoesNotExist:
|
|
||||||
# no superuser yet. We need to create it.
|
|
||||||
create_superuser()
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def get_pid(pidfile):
|
|
||||||
"""
|
|
||||||
Get the PID (Process ID) by trying to access
|
|
||||||
an PID file.
|
|
||||||
"""
|
|
||||||
pid = None
|
|
||||||
if os.path.exists(pidfile):
|
|
||||||
f = open(pidfile, 'r')
|
|
||||||
pid = f.read()
|
|
||||||
return pid
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
if os.path.exists(pidfile):
|
|
||||||
os.remove(pidfile)
|
|
||||||
|
|
||||||
|
|
||||||
def kill(pidfile, signal=SIG, succmsg="", errmsg="", restart_file=SERVER_RESTART, restart="reload"):
|
|
||||||
"""
|
|
||||||
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.
|
|
||||||
"""
|
|
||||||
pid = get_pid(pidfile)
|
|
||||||
if pid:
|
|
||||||
if os.name == 'nt':
|
|
||||||
if sys.version < "2.7":
|
|
||||||
print "Windows requires Python 2.7 or higher for this operation."
|
|
||||||
return
|
|
||||||
os.remove(pidfile)
|
|
||||||
# set restart/norestart flag
|
|
||||||
if restart == 'reload':
|
|
||||||
django.core.management.call_command('collectstatic', interactive=False, verbosity=0)
|
|
||||||
f = open(restart_file, 'w')
|
|
||||||
f.write(str(restart))
|
|
||||||
f.close()
|
|
||||||
try:
|
|
||||||
os.kill(int(pid), signal)
|
|
||||||
except OSError:
|
|
||||||
print "Process %(pid)s could not be signalled. The PID file '%(pidfile)s' seems stale. Try removing it." % {'pid': pid, 'pidfile': pidfile}
|
|
||||||
return
|
|
||||||
print "Evennia:", succmsg
|
|
||||||
return
|
|
||||||
print "Evennia:", errmsg
|
|
||||||
|
|
||||||
def show_version_info(about=False):
|
|
||||||
"""
|
|
||||||
Display version info
|
|
||||||
"""
|
|
||||||
import os, sys
|
|
||||||
import twisted
|
|
||||||
import django
|
|
||||||
|
|
||||||
return VERSION_INFO.format(version=EVENNIA_VERSION,
|
|
||||||
about=ABOUT_INFO if about else "",
|
|
||||||
os=os.name, python=sys.version.split()[0],
|
|
||||||
twisted=twisted.version.short(),
|
|
||||||
django=django.get_version())
|
|
||||||
|
|
||||||
def run_menu():
|
def run_menu():
|
||||||
"""
|
"""
|
||||||
This launches an interactive menu.
|
This launches an interactive menu.
|
||||||
|
|
@ -668,19 +723,19 @@ def run_menu():
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
print "This operation is not supported under Windows. Log into the game to restart/reload the server."
|
print "This operation is not supported under Windows. Log into the game to restart/reload the server."
|
||||||
return
|
return
|
||||||
kill(SERVER_PIDFILE, SIG, "Server reloaded.", errmsg % "Server", restart="reload")
|
kill(SERVER_PIDFILE, SIG, "Server reloaded.", errmsg % "Server", SERVER_RESTART, restart="reload")
|
||||||
elif inp == 6:
|
elif inp == 6:
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
print "This operation is not supported under Windows."
|
print "This operation is not supported under Windows."
|
||||||
return
|
return
|
||||||
kill(PORTAL_PIDFILE, SIG, "Portal reloaded (or stopped if in daemon mode).", errmsg % "Portal", restart=True)
|
kill(PORTAL_PIDFILE, SIG, "Portal reloaded (or stopped if in daemon mode).", errmsg % "Portal", PORTAL_RESTART, restart=True)
|
||||||
elif inp == 7:
|
elif inp == 7:
|
||||||
kill(SERVER_PIDFILE, SIG, "Stopped Portal.", errmsg % "Portal", PORTAL_RESTART, restart=False)
|
kill(PORTAL_PIDFILE, SIG, "Stopped Portal.", errmsg % "Portal", PORTAL_RESTART, restart=False)
|
||||||
kill(PORTAL_PIDFILE, SIG, "Stopped Server.", errmsg % "Server", restart="shutdown")
|
kill(SERVER_PIDFILE, SIG, "Stopped Server.", errmsg % "Server", SERVER_RESTART, restart="shutdown")
|
||||||
elif inp == 8:
|
elif inp == 8:
|
||||||
kill(PORTAL_PIDFILE, SIG, "Stopped Server.", errmsg % "Server", restart="shutdown")
|
kill(SERVER_PIDFILE, SIG, "Stopped Server.", errmsg % "Server", SERVER_RESTART, restart="shutdown")
|
||||||
elif inp == 9:
|
elif inp == 9:
|
||||||
kill(SERVER_PIDFILE, SIG, "Stopped Portal.", errmsg % "Portal", PORTAL_RESTART, restart=False)
|
kill(PORTAL_PIDFILE, SIG, "Stopped Portal.", errmsg % "Portal", PORTAL_RESTART, restart=False)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
print "Not a valid option."
|
print "Not a valid option."
|
||||||
|
|
@ -736,81 +791,27 @@ def server_operation(mode, service, interactive, profiler):
|
||||||
print "Restarting from command line is not supported under Windows. Log into the game to restart."
|
print "Restarting from command line is not supported under Windows. Log into the game to restart."
|
||||||
return
|
return
|
||||||
if service == 'server':
|
if service == 'server':
|
||||||
kill(SERVER_PIDFILE, SIG, "Server reloaded.", errmsg % 'Server', restart="reload")
|
kill(SERVER_PIDFILE, SIG, "Server reloaded.", errmsg % 'Server', SERVER_RESTART, restart="reload")
|
||||||
elif service == 'portal':
|
elif service == 'portal':
|
||||||
print """
|
print """
|
||||||
Note: Portal usually don't need to be reloaded unless you are debugging in interactive mode.
|
Note: Portal usually don't need to be reloaded unless you are debugging in interactive mode.
|
||||||
If Portal was running in default Daemon mode, it cannot be restarted. In that case you have
|
If Portal was running in default Daemon mode, it cannot be restarted. In that case you have
|
||||||
to restart it manually with 'evennia.py start portal'
|
to restart it manually with 'evennia.py start portal'
|
||||||
"""
|
"""
|
||||||
kill(PORTAL_PIDFILE, SIG, "Portal reloaded (or stopped, if it was in daemon mode).", errmsg % 'Portal', PORTAL_RESTART)
|
kill(PORTAL_PIDFILE, SIG, "Portal reloaded (or stopped, if it was in daemon mode).", errmsg % 'Portal', PORTAL_RESTART, restart="reload")
|
||||||
else: # all
|
else: # all
|
||||||
# default mode, only restart server
|
# default mode, only restart server
|
||||||
kill(SERVER_PIDFILE, SIG, "Server reload.", errmsg % 'Server', restart="reload")
|
kill(SERVER_PIDFILE, SIG, "Server reload.", errmsg % 'Server', SERVER_RESTART, restart="reload")
|
||||||
|
|
||||||
elif mode == 'stop':
|
elif mode == 'stop':
|
||||||
# stop processes, avoiding reload
|
# stop processes, avoiding reload
|
||||||
if service == 'server':
|
if service == 'server':
|
||||||
kill(SERVER_PIDFILE, SIG, "Server stopped.", errmsg % 'Server', restart="shutdown")
|
kill(SERVER_PIDFILE, SIG, "Server stopped.", errmsg % 'Server', SERVER_RESTART, restart="shutdown")
|
||||||
elif service == 'portal':
|
elif service == 'portal':
|
||||||
kill(PORTAL_PIDFILE, SIG, "Portal stopped.", errmsg % 'Portal', PORTAL_RESTART, restart=False)
|
kill(PORTAL_PIDFILE, SIG, "Portal stopped.", errmsg % 'Portal', PORTAL_RESTART, restart=False)
|
||||||
else:
|
else:
|
||||||
kill(PORTAL_PIDFILE, SIG, "Portal stopped.", errmsg % 'Portal', PORTAL_RESTART, restart=False)
|
kill(PORTAL_PIDFILE, SIG, "Portal stopped.", errmsg % 'Portal', PORTAL_RESTART, restart=False)
|
||||||
kill(SERVER_PIDFILE, SIG, "Server stopped.", errmsg % 'Server', restart="shutdown")
|
kill(SERVER_PIDFILE, SIG, "Server stopped.", errmsg % 'Server', SERVER_RESTART, restart="shutdown")
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
before we get any further.
|
|
||||||
"""
|
|
||||||
from django.conf import settings
|
|
||||||
def imp(path, split=True):
|
|
||||||
mod, fromlist = path, "None"
|
|
||||||
if split:
|
|
||||||
mod, fromlist = path.rsplit('.', 1)
|
|
||||||
__import__(mod, fromlist=[fromlist])
|
|
||||||
|
|
||||||
# core modules
|
|
||||||
imp(settings.COMMAND_PARSER)
|
|
||||||
imp(settings.SEARCH_AT_RESULT)
|
|
||||||
imp(settings.SEARCH_AT_MULTIMATCH_INPUT)
|
|
||||||
imp(settings.CONNECTION_SCREEN_MODULE)
|
|
||||||
#imp(settings.AT_INITIAL_SETUP_HOOK_MODULE, split=False)
|
|
||||||
for path in settings.LOCK_FUNC_MODULES:
|
|
||||||
imp(path, split=False)
|
|
||||||
# cmdsets
|
|
||||||
|
|
||||||
deprstring = "settings.%s should be renamed to %s. If defaults are used, " \
|
|
||||||
"their path/classname must be updated (see evennia/settings_default.py)."
|
|
||||||
if hasattr(settings, "CMDSET_DEFAULT"):
|
|
||||||
raise DeprecationWarning(deprstring % ("CMDSET_DEFAULT", "CMDSET_CHARACTER"))
|
|
||||||
if hasattr(settings, "CMDSET_OOC"):
|
|
||||||
raise DeprecationWarning(deprstring % ("CMDSET_OOC", "CMDSET_PLAYER"))
|
|
||||||
if settings.WEBSERVER_ENABLED and not isinstance(settings.WEBSERVER_PORTS[0], tuple):
|
|
||||||
raise DeprecationWarning("settings.WEBSERVER_PORTS must be on the form [(proxyport, serverport), ...]")
|
|
||||||
if hasattr(settings, "BASE_COMM_TYPECLASS"):
|
|
||||||
raise DeprecationWarning(deprstring % ("BASE_COMM_TYPECLASS", "BASE_CHANNEL_TYPECLASS"))
|
|
||||||
if hasattr(settings, "COMM_TYPECLASS_PATHS"):
|
|
||||||
raise DeprecationWarning(deprstring % ("COMM_TYPECLASS_PATHS", "CHANNEL_TYPECLASS_PATHS"))
|
|
||||||
if hasattr(settings, "CHARACTER_DEFAULT_HOME"):
|
|
||||||
raise DeprecationWarning("settings.CHARACTER_DEFAULT_HOME should be renamed to DEFAULT_HOME. " \
|
|
||||||
"See also settings.START_LOCATION (see evennia/settings_default.py).")
|
|
||||||
|
|
||||||
from evennia.commands import cmdsethandler
|
|
||||||
if not cmdsethandler.import_cmdset(settings.CMDSET_UNLOGGEDIN, None): print "Warning: CMDSET_UNLOGGED failed to load!"
|
|
||||||
if not cmdsethandler.import_cmdset(settings.CMDSET_CHARACTER, None): print "Warning: CMDSET_CHARACTER failed to load"
|
|
||||||
if not cmdsethandler.import_cmdset(settings.CMDSET_PLAYER, None): print "Warning: CMDSET_PLAYER failed to load"
|
|
||||||
# typeclasses
|
|
||||||
imp(settings.BASE_PLAYER_TYPECLASS)
|
|
||||||
imp(settings.BASE_OBJECT_TYPECLASS)
|
|
||||||
imp(settings.BASE_CHARACTER_TYPECLASS)
|
|
||||||
imp(settings.BASE_ROOM_TYPECLASS)
|
|
||||||
imp(settings.BASE_EXIT_TYPECLASS)
|
|
||||||
imp(settings.BASE_SCRIPT_TYPECLASS)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
"""
|
"""
|
||||||
|
|
||||||
This runner is controlled by evennia.py and should normally not be
|
This runner is controlled by the evennia launcher and should normally
|
||||||
launched directly. It manages the two main Evennia processes (Server
|
not be launched directly. It manages the two main Evennia processes
|
||||||
and Portal) and most importanly runs a passive, threaded loop that
|
(Server and Portal) and most importanly runs a passive, threaded loop
|
||||||
makes sure to restart Server whenever it shuts down.
|
that makes sure to restart Server whenever it shuts down.
|
||||||
|
|
||||||
Since twistd does not allow for returning an optional exit code we
|
Since twistd does not allow for returning an optional exit code we
|
||||||
need to handle the current reload state for server and portal with
|
need to handle the current reload state for server and portal with
|
||||||
|
|
@ -183,14 +183,14 @@ def start_services(server_argv, portal_argv):
|
||||||
message, rc = processes.get()
|
message, rc = processes.get()
|
||||||
|
|
||||||
# restart only if process stopped cleanly
|
# restart only if process stopped cleanly
|
||||||
if (message == "server_stopped" and int(rc) == 0 and
|
if (message == "server_stopped" and not rc.returncode and
|
||||||
get_restart_mode(SERVER_RESTART) in ("True", "reload", "reset")):
|
get_restart_mode(SERVER_RESTART) in ("True", "reload", "reset")):
|
||||||
print PROCESS_RESTART.format(component="Server")
|
print PROCESS_RESTART.format(component="Server")
|
||||||
SERVER = thread.start_new_thread(server_waiter, (processes, ))
|
SERVER = thread.start_new_thread(server_waiter, (processes, ))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# normally the portal is not reloaded since it's run as a daemon.
|
# normally the portal is not reloaded since it's run as a daemon.
|
||||||
if (message == "portal_stopped" and int(rc) == 0 and
|
if (message == "portal_stopped" and not rc.returncode and
|
||||||
get_restart_mode(PORTAL_RESTART) == "True"):
|
get_restart_mode(PORTAL_RESTART) == "True"):
|
||||||
print PROCESS_RESTART.format(component="Portal")
|
print PROCESS_RESTART.format(component="Portal")
|
||||||
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
|
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ DefaultObject = None
|
||||||
DefaultCharacter = None
|
DefaultCharacter = None
|
||||||
DefaultRoom = None
|
DefaultRoom = None
|
||||||
DefaultExit = None
|
DefaultExit = None
|
||||||
Channel = None
|
DefaultChannel = None
|
||||||
Script = None
|
Script = None
|
||||||
|
|
||||||
# Database models
|
# Database models
|
||||||
|
|
@ -80,7 +80,8 @@ def init():
|
||||||
mod, fromlist = path.rsplit('.', 1)
|
mod, fromlist = path.rsplit('.', 1)
|
||||||
return __import__(mod, fromlist=[fromlist])
|
return __import__(mod, fromlist=[fromlist])
|
||||||
|
|
||||||
global DefaultPlayer, DefaultObject, DefaultGuest, DefaultCharacter, DefaultRoom, DefaultExit, Channel, Script
|
global DefaultPlayer, DefaultObject, DefaultGuest, DefaultCharacter, \
|
||||||
|
DefaultRoom, DefaultExit, DefaultChannel, Script
|
||||||
global ObjectDB, PlayerDB, ScriptDB, ChannelDB, Msg
|
global ObjectDB, PlayerDB, ScriptDB, ChannelDB, Msg
|
||||||
global Command, default_cmds, syscmdkeys
|
global Command, default_cmds, syscmdkeys
|
||||||
global search_object, search_script, search_player, search_channel, search_help
|
global search_object, search_script, search_player, search_channel, search_help
|
||||||
|
|
@ -93,7 +94,7 @@ def init():
|
||||||
from objects.objects import DefaultCharacter
|
from objects.objects import DefaultCharacter
|
||||||
from objects.objects import DefaultRoom
|
from objects.objects import DefaultRoom
|
||||||
from objects.objects import DefaultExit
|
from objects.objects import DefaultExit
|
||||||
from comms.comms import Channel
|
from comms.comms import DefaultChannel
|
||||||
from scripts.scripts import Script
|
from scripts.scripts import Script
|
||||||
|
|
||||||
# Database models
|
# Database models
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ from evennia.utils import logger
|
||||||
from evennia.utils.utils import make_iter
|
from evennia.utils.utils import make_iter
|
||||||
|
|
||||||
|
|
||||||
class Channel(ChannelDB):
|
class DefaultChannel(ChannelDB):
|
||||||
"""
|
"""
|
||||||
This is the base class for all Comms. Inherit from this to create different
|
This is the base class for all Comms. Inherit from this to create different
|
||||||
types of communication channels.
|
types of communication channels.
|
||||||
|
|
@ -113,78 +113,6 @@ class Channel(ChannelDB):
|
||||||
from evennia.comms.channelhandler import CHANNELHANDLER
|
from evennia.comms.channelhandler import CHANNELHANDLER
|
||||||
CHANNELHANDLER.update()
|
CHANNELHANDLER.update()
|
||||||
|
|
||||||
def channel_prefix(self, msg=None, emit=False):
|
|
||||||
"""
|
|
||||||
How the channel should prefix itself for users. Return a string.
|
|
||||||
"""
|
|
||||||
return '[%s] ' % self.key
|
|
||||||
|
|
||||||
def format_senders(self, senders=None):
|
|
||||||
"""
|
|
||||||
Function used to format a list of sender names.
|
|
||||||
|
|
||||||
This function exists separately so that external sources can use
|
|
||||||
it to format source names in the same manner as normal object/player
|
|
||||||
names.
|
|
||||||
"""
|
|
||||||
if not senders:
|
|
||||||
return ''
|
|
||||||
return ', '.join(senders)
|
|
||||||
|
|
||||||
def pose_transform(self, msg, sender_string):
|
|
||||||
"""
|
|
||||||
Detects if the sender is posing, and modifies the message accordingly.
|
|
||||||
"""
|
|
||||||
pose = False
|
|
||||||
message = msg.message
|
|
||||||
message_start = message.lstrip()
|
|
||||||
if message_start.startswith((':', ';')):
|
|
||||||
pose = True
|
|
||||||
message = message[1:]
|
|
||||||
if not message.startswith((':', "'", ',')):
|
|
||||||
if not message.startswith(' '):
|
|
||||||
message = ' ' + message
|
|
||||||
if pose:
|
|
||||||
return '%s%s' % (sender_string, message)
|
|
||||||
else:
|
|
||||||
return '%s: %s' % (sender_string, message)
|
|
||||||
|
|
||||||
def format_external(self, msg, senders, emit=False):
|
|
||||||
"""
|
|
||||||
Used for formatting external messages. This is needed as a separate
|
|
||||||
operation because the senders of external messages may not be in-game
|
|
||||||
objects/players, and so cannot have things like custom user
|
|
||||||
preferences.
|
|
||||||
|
|
||||||
senders should be a list of strings, each containing a sender.
|
|
||||||
msg should contain the body of the message to be sent.
|
|
||||||
"""
|
|
||||||
if not senders:
|
|
||||||
emit = True
|
|
||||||
if emit:
|
|
||||||
return msg.message
|
|
||||||
senders = ', '.join(senders)
|
|
||||||
return self.pose_transform(msg, senders)
|
|
||||||
|
|
||||||
def format_message(self, msg, emit=False):
|
|
||||||
"""
|
|
||||||
Formats a message body for display.
|
|
||||||
|
|
||||||
If emit is True, it means the message is intended to be posted detached
|
|
||||||
from an identity.
|
|
||||||
"""
|
|
||||||
# We don't want to count things like external sources as senders for
|
|
||||||
# the purpose of constructing the message string.
|
|
||||||
senders = [sender for sender in msg.senders if hasattr(sender, 'key')]
|
|
||||||
if not senders:
|
|
||||||
emit = True
|
|
||||||
if emit:
|
|
||||||
return msg.message
|
|
||||||
else:
|
|
||||||
senders = [sender.key for sender in msg.senders]
|
|
||||||
senders = ', '.join(senders)
|
|
||||||
return self.pose_transform(msg, senders)
|
|
||||||
|
|
||||||
def message_transform(self, msg, emit=False, prefix=True,
|
def message_transform(self, msg, emit=False, prefix=True,
|
||||||
sender_strings=None, external=False):
|
sender_strings=None, external=False):
|
||||||
"""
|
"""
|
||||||
|
|
@ -199,57 +127,6 @@ class Channel(ChannelDB):
|
||||||
msg.message = body
|
msg.message = body
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def pre_join_channel(self, joiner):
|
|
||||||
"""
|
|
||||||
Run right before a channel is joined. If this returns a false value,
|
|
||||||
channel joining is aborted.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def post_join_channel(self, joiner):
|
|
||||||
"""
|
|
||||||
Run right after an object or player joins a channel.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def pre_leave_channel(self, leaver):
|
|
||||||
"""
|
|
||||||
Run right before a user leaves a channel. If this returns a false
|
|
||||||
value, leaving the channel will be aborted.
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def post_leave_channel(self, leaver):
|
|
||||||
"""
|
|
||||||
Run right after an object or player leaves a channel.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def pre_send_message(self, msg):
|
|
||||||
"""
|
|
||||||
Run before a message is sent to the channel.
|
|
||||||
|
|
||||||
This should return the message object, after any transformations.
|
|
||||||
If the message is to be discarded, return a false value.
|
|
||||||
"""
|
|
||||||
return msg
|
|
||||||
|
|
||||||
def post_send_message(self, msg):
|
|
||||||
"""
|
|
||||||
Run after a message is sent to the channel.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def at_init(self):
|
|
||||||
"""
|
|
||||||
This is always called whenever this channel is initiated --
|
|
||||||
that is, whenever it its typeclass is cached from memory. This
|
|
||||||
happens on-demand first time the channel is used or activated
|
|
||||||
in some way after being created but also after each server
|
|
||||||
restart or reload.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def distribute_message(self, msg, online=False):
|
def distribute_message(self, msg, online=False):
|
||||||
"""
|
"""
|
||||||
Method for grabbing all listeners that a message should be sent to on
|
Method for grabbing all listeners that a message should be sent to on
|
||||||
|
|
@ -328,3 +205,131 @@ class Channel(ChannelDB):
|
||||||
"""
|
"""
|
||||||
self.msg(message, senders=senders, header=header, persistent=False)
|
self.msg(message, senders=senders, header=header, persistent=False)
|
||||||
|
|
||||||
|
|
||||||
|
# hooks
|
||||||
|
|
||||||
|
def channel_prefix(self, msg=None, emit=False):
|
||||||
|
|
||||||
|
"""
|
||||||
|
How the channel should prefix itself for users. Return a string.
|
||||||
|
"""
|
||||||
|
return '[%s] ' % self.key
|
||||||
|
|
||||||
|
def format_senders(self, senders=None):
|
||||||
|
"""
|
||||||
|
Function used to format a list of sender names.
|
||||||
|
|
||||||
|
This function exists separately so that external sources can use
|
||||||
|
it to format source names in the same manner as normal object/player
|
||||||
|
names.
|
||||||
|
"""
|
||||||
|
if not senders:
|
||||||
|
return ''
|
||||||
|
return ', '.join(senders)
|
||||||
|
|
||||||
|
def pose_transform(self, msg, sender_string):
|
||||||
|
"""
|
||||||
|
Detects if the sender is posing, and modifies the message accordingly.
|
||||||
|
"""
|
||||||
|
pose = False
|
||||||
|
message = msg.message
|
||||||
|
message_start = message.lstrip()
|
||||||
|
if message_start.startswith((':', ';')):
|
||||||
|
pose = True
|
||||||
|
message = message[1:]
|
||||||
|
if not message.startswith((':', "'", ',')):
|
||||||
|
if not message.startswith(' '):
|
||||||
|
message = ' ' + message
|
||||||
|
if pose:
|
||||||
|
return '%s%s' % (sender_string, message)
|
||||||
|
else:
|
||||||
|
return '%s: %s' % (sender_string, message)
|
||||||
|
|
||||||
|
def format_external(self, msg, senders, emit=False):
|
||||||
|
"""
|
||||||
|
Used for formatting external messages. This is needed as a separate
|
||||||
|
operation because the senders of external messages may not be in-game
|
||||||
|
objects/players, and so cannot have things like custom user
|
||||||
|
preferences.
|
||||||
|
|
||||||
|
senders should be a list of strings, each containing a sender.
|
||||||
|
msg should contain the body of the message to be sent.
|
||||||
|
"""
|
||||||
|
if not senders:
|
||||||
|
emit = True
|
||||||
|
if emit:
|
||||||
|
return msg.message
|
||||||
|
senders = ', '.join(senders)
|
||||||
|
return self.pose_transform(msg, senders)
|
||||||
|
|
||||||
|
def format_message(self, msg, emit=False):
|
||||||
|
"""
|
||||||
|
Formats a message body for display.
|
||||||
|
|
||||||
|
If emit is True, it means the message is intended to be posted detached
|
||||||
|
from an identity.
|
||||||
|
"""
|
||||||
|
# We don't want to count things like external sources as senders for
|
||||||
|
# the purpose of constructing the message string.
|
||||||
|
senders = [sender for sender in msg.senders if hasattr(sender, 'key')]
|
||||||
|
if not senders:
|
||||||
|
emit = True
|
||||||
|
if emit:
|
||||||
|
return msg.message
|
||||||
|
else:
|
||||||
|
senders = [sender.key for sender in msg.senders]
|
||||||
|
senders = ', '.join(senders)
|
||||||
|
return self.pose_transform(msg, senders)
|
||||||
|
|
||||||
|
def pre_join_channel(self, joiner):
|
||||||
|
"""
|
||||||
|
Run right before a channel is joined. If this returns a false value,
|
||||||
|
channel joining is aborted.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def post_join_channel(self, joiner):
|
||||||
|
"""
|
||||||
|
Run right after an object or player joins a channel.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def pre_leave_channel(self, leaver):
|
||||||
|
"""
|
||||||
|
Run right before a user leaves a channel. If this returns a false
|
||||||
|
value, leaving the channel will be aborted.
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def post_leave_channel(self, leaver):
|
||||||
|
"""
|
||||||
|
Run right after an object or player leaves a channel.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pre_send_message(self, msg):
|
||||||
|
"""
|
||||||
|
Run before a message is sent to the channel.
|
||||||
|
|
||||||
|
This should return the message object, after any transformations.
|
||||||
|
If the message is to be discarded, return a false value.
|
||||||
|
"""
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def post_send_message(self, msg):
|
||||||
|
"""
|
||||||
|
Run after a message is sent to the channel.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def at_init(self):
|
||||||
|
"""
|
||||||
|
This is always called whenever this channel is initiated --
|
||||||
|
that is, whenever it its typeclass is cached from memory. This
|
||||||
|
happens on-demand first time the channel is used or activated
|
||||||
|
in some way after being created but also after each server
|
||||||
|
restart or reload.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ PORTAL_SERVICES_PLUGIN_MODULES = [mod_import(module) for module in make_iter(set
|
||||||
|
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
# For Windows we need to handle pid files manually.
|
# For Windows we need to handle pid files manually.
|
||||||
PORTAL_PIDFILE = os.path.join(settings.GAME_DIR, 'portal.pid')
|
PORTAL_PIDFILE = os.path.join(settings.GAME_DIR, "server", 'portal.pid')
|
||||||
|
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
# Evennia Portal settings
|
# Evennia Portal settings
|
||||||
|
|
@ -44,7 +44,7 @@ VERSION = get_evennia_version()
|
||||||
|
|
||||||
SERVERNAME = settings.SERVERNAME
|
SERVERNAME = settings.SERVERNAME
|
||||||
|
|
||||||
PORTAL_RESTART = os.path.join(settings.GAME_DIR, 'portal.restart')
|
PORTAL_RESTART = os.path.join(settings.GAME_DIR, "server", 'portal.restart')
|
||||||
|
|
||||||
TELNET_PORTS = settings.TELNET_PORTS
|
TELNET_PORTS = settings.TELNET_PORTS
|
||||||
SSL_PORTS = settings.SSL_PORTS
|
SSL_PORTS = settings.SSL_PORTS
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,10 @@ _SA = object.__setattr__
|
||||||
|
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
# For Windows we need to handle pid files manually.
|
# For Windows we need to handle pid files manually.
|
||||||
SERVER_PIDFILE = os.path.join(settings.GAME_DIR, 'server.pid')
|
SERVER_PIDFILE = os.path.join(settings.GAME_DIR, "server", 'server.pid')
|
||||||
|
|
||||||
# a file with a flag telling the server to restart after shutdown or not.
|
# a file with a flag telling the server to restart after shutdown or not.
|
||||||
SERVER_RESTART = os.path.join(settings.GAME_DIR, 'server.restart')
|
SERVER_RESTART = os.path.join(settings.GAME_DIR, "server", 'server.restart')
|
||||||
|
|
||||||
# module containing hook methods called during start_stop
|
# module containing hook methods called during start_stop
|
||||||
SERVER_STARTSTOP_MODULE = mod_import(settings.AT_SERVER_STARTSTOP_MODULE)
|
SERVER_STARTSTOP_MODULE = mod_import(settings.AT_SERVER_STARTSTOP_MODULE)
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ LOCK_FUNC_MODULES = ("evennia.locks.lockfuncs", "server.conf.lockfuncs",)
|
||||||
# Module holding OOB (Out of Band) hook objects. This allows for customization
|
# Module holding OOB (Out of Band) hook objects. This allows for customization
|
||||||
# and expansion of which hooks OOB protocols are allowed to call on the server
|
# and expansion of which hooks OOB protocols are allowed to call on the server
|
||||||
# protocols for attaching tracker hooks for when various object field change
|
# protocols for attaching tracker hooks for when various object field change
|
||||||
OOB_PLUGIN_MODULES = ["evennia.server.oob_cmds", "server.conf.oob_cmds"]
|
OOB_PLUGIN_MODULES = ["evennia.server.oob_cmds", "server.conf.oobfuncs"]
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Default command sets
|
# Default command sets
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,5 @@ a global function oob_error will be used as optional error management.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# import the contents of the default msdp module
|
# import the contents of the default msdp module
|
||||||
from src.server.oob_cmds import *
|
from evennia.server.oob_cmds import *
|
||||||
|
|
||||||
|
|
|
||||||
60
game_template/typeclasses/channels.py
Normal file
60
game_template/typeclasses/channels.py
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
"""
|
||||||
|
Channel
|
||||||
|
|
||||||
|
The channel class represents the out-of-character chat-room usable by
|
||||||
|
Players in-game. It is mostly overloaded to change its appearance, but
|
||||||
|
channels can be used to implement many different forms of message
|
||||||
|
distribution systems.
|
||||||
|
|
||||||
|
Note that sending data to channels are handled via the CMD_CHANNEL
|
||||||
|
syscommand (see evennia.syscmds). The sending should normally not need
|
||||||
|
to be modified.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from evennia import DefaultChannel
|
||||||
|
|
||||||
|
class Channel(DefaultChannel):
|
||||||
|
"""
|
||||||
|
Working methods:
|
||||||
|
at_channel_creation() - called once, when the channel is created
|
||||||
|
has_connection(player) - check if the given player listens to this channel
|
||||||
|
connect(player) - connect player to this channel
|
||||||
|
disconnect(player) - disconnect player from channel
|
||||||
|
access(access_obj, access_type='listen', default=False) - check the
|
||||||
|
access on this channel (default access_type is listen)
|
||||||
|
delete() - delete this channel
|
||||||
|
message_transform(msg, emit=False, prefix=True,
|
||||||
|
sender_strings=None, external=False) - called by
|
||||||
|
the comm system and triggers the hooks below
|
||||||
|
msg(msgobj, header=None, senders=None, sender_strings=None,
|
||||||
|
persistent=None, online=False, emit=False, external=False) - main
|
||||||
|
send method, builds and sends a new message to channel.
|
||||||
|
tempmsg(msg, header=None, senders=None) - wrapper for sending non-persistent
|
||||||
|
messages.
|
||||||
|
distribute_message(msg, online=False) - send a message to all
|
||||||
|
connected players on channel, optionally sending only
|
||||||
|
to players that are currently online (optimized for very large sends)
|
||||||
|
|
||||||
|
Useful hooks:
|
||||||
|
channel_prefix(msg, emit=False) - how the channel should be
|
||||||
|
prefixed when returning to user. Returns a string
|
||||||
|
format_senders(senders) - should return how to display multiple
|
||||||
|
senders to a channel
|
||||||
|
pose_transform(msg, sender_string) - should detect if the
|
||||||
|
sender is posing, and if so, modify the string
|
||||||
|
format_external(msg, senders, emit=False) - format messages sent
|
||||||
|
from outside the game, like from IRC
|
||||||
|
format_message(msg, emit=False) - format the message body before
|
||||||
|
displaying it to the user. 'emit' generally means that the
|
||||||
|
message should not be displayed with the sender's name.
|
||||||
|
|
||||||
|
pre_join_channel(joiner) - if returning False, abort join
|
||||||
|
post_join_channel(joiner) - called right after successful join
|
||||||
|
pre_leave_channel(leaver) - if returning False, abort leave
|
||||||
|
post_leave_channel(leaver) - called right after successful leave
|
||||||
|
pre_send_message(msg) - runs just before a message is sent to channel
|
||||||
|
post_send_message(msg) - called just after message was sent to channel
|
||||||
|
|
||||||
|
"""
|
||||||
|
pass
|
||||||
Loading…
Add table
Add a link
Reference in a new issue