mirror of
https://github.com/evennia/evennia.git
synced 2026-04-01 21:47:17 +02:00
Changed how the Typeclass system returns errors. Instead of echoing typeclass erros to the MUD-info channel (which is not only not only very spammy for everyone but also very hard to make clean so as to avoid recursion at a stage of typeclass failing), the system instead stores a property on itself called 'typeclass_last_errmsg' that holds eventual errors. This means that the task of reporting errors does not fall on the typeclass system itself but on the calling methods, as it should be. So src.utils.create.create_* functions now takes a new optional keyword "report_to" that holds an object to receive errors. If this keyword is given, the function msg():es that object with the error and returns None as before. If report_to is not set however, the create_* methods now return an Exception containing the error text. All default commands have been changed to accomodate for this behaviour, which allows for much more control over errors.
Also, the default ADMIN_MEDIA static files changed location in Django 1.4. The initial_setup function now accounts for this.
This commit is contained in:
parent
63329f5420
commit
8c3b49e704
15 changed files with 838 additions and 785 deletions
|
|
@ -16,13 +16,13 @@ from src.commands.default.muxcommand import MuxCommand
|
|||
PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
|
||||
|
||||
# limit members for API inclusion
|
||||
__all__ = ("CmdBoot", "CmdBan", "CmdUnban", "CmdDelPlayer", "CmdEmit", "CmdNewPassword",
|
||||
__all__ = ("CmdBoot", "CmdBan", "CmdUnban", "CmdDelPlayer", "CmdEmit", "CmdNewPassword",
|
||||
"CmdPerm", "CmdWall")
|
||||
|
||||
|
||||
class CmdBoot(MuxCommand):
|
||||
"""
|
||||
@boot
|
||||
@boot
|
||||
|
||||
Usage
|
||||
@boot[/switches] <player obj> [: reason]
|
||||
|
|
@ -30,11 +30,11 @@ class CmdBoot(MuxCommand):
|
|||
Switches:
|
||||
quiet - Silently boot without informing player
|
||||
port - boot by port number instead of name or dbref
|
||||
|
||||
|
||||
Boot a player object from the server. If a reason is
|
||||
supplied it will be echoed to the user unless /quiet is set.
|
||||
supplied it will be echoed to the user unless /quiet is set.
|
||||
"""
|
||||
|
||||
|
||||
key = "@boot"
|
||||
locks = "cmd:perm(boot) or perm(Wizards)"
|
||||
help_category = "Admin"
|
||||
|
|
@ -43,7 +43,7 @@ class CmdBoot(MuxCommand):
|
|||
"Implementing the function"
|
||||
caller = self.caller
|
||||
args = self.args
|
||||
|
||||
|
||||
if not args:
|
||||
caller.msg("Usage: @boot[/switches] <player> [:reason]")
|
||||
return
|
||||
|
|
@ -67,12 +67,12 @@ class CmdBoot(MuxCommand):
|
|||
# Boot by player object
|
||||
pobj = caller.search("*%s" % args, global_search=True, player=True)
|
||||
if not pobj:
|
||||
return
|
||||
return
|
||||
if pobj.character.has_player:
|
||||
if not pobj.access(caller, 'boot'):
|
||||
string = "You don't have the permission to boot %s."
|
||||
pobj.msg(string)
|
||||
return
|
||||
return
|
||||
# we have a bootable object with a connected user
|
||||
matches = SESSIONS.sessions_from_player(pobj)
|
||||
for match in matches:
|
||||
|
|
@ -87,7 +87,7 @@ class CmdBoot(MuxCommand):
|
|||
|
||||
# Carry out the booting of the sessions in the boot list.
|
||||
|
||||
feedback = None
|
||||
feedback = None
|
||||
if not 'quiet' in self.switches:
|
||||
feedback = "You have been disconnected by %s.\n" % caller.name
|
||||
if reason:
|
||||
|
|
@ -108,16 +108,16 @@ def list_bans(banlist):
|
|||
Helper function to display a list of active bans. Input argument
|
||||
is the banlist read into the two commands @ban and @undban below.
|
||||
"""
|
||||
if not banlist:
|
||||
if not banlist:
|
||||
return "No active bans were found."
|
||||
|
||||
table = [["id"], ["name/ip"], ["date"], ["reason"]]
|
||||
table[0].extend([str(i+1) for i in range(len(banlist))])
|
||||
for ban in banlist:
|
||||
if ban[0]:
|
||||
for ban in banlist:
|
||||
if ban[0]:
|
||||
table[1].append(ban[0])
|
||||
else:
|
||||
table[1].append(ban[1])
|
||||
else:
|
||||
table[1].append(ban[1])
|
||||
table[2].extend([ban[3] for ban in banlist])
|
||||
table[3].extend([ban[4] for ban in banlist])
|
||||
ftable = utils.format_table(table, 4)
|
||||
|
|
@ -128,8 +128,8 @@ def list_bans(banlist):
|
|||
srow = "{w%s{n" % srow.rstrip()
|
||||
else:
|
||||
srow = "\n" + "{w%s{n" % row[0] + "".join(row[1:])
|
||||
string += srow.rstrip()
|
||||
return string
|
||||
string += srow.rstrip()
|
||||
return string
|
||||
|
||||
class CmdBan(MuxCommand):
|
||||
"""
|
||||
|
|
@ -137,34 +137,34 @@ class CmdBan(MuxCommand):
|
|||
|
||||
Usage:
|
||||
@ban [<name or ip> [: reason]]
|
||||
|
||||
Without any arguments, shows numbered list of active bans.
|
||||
|
||||
|
||||
Without any arguments, shows numbered list of active bans.
|
||||
|
||||
This command bans a user from accessing the game. Supply an
|
||||
optional reason to be able to later remember why the ban was put in
|
||||
place
|
||||
|
||||
|
||||
It is often to
|
||||
prefer over deleting a player with @delplayer. If banned by name,
|
||||
that player account can no longer be logged into.
|
||||
|
||||
IP (Internet Protocol) address banning allows to block all access
|
||||
from a specific address or subnet. Use the asterisk (*) as a
|
||||
wildcard.
|
||||
wildcard.
|
||||
|
||||
Examples:
|
||||
Examples:
|
||||
@ban thomas - ban account 'thomas'
|
||||
@ban/ip 134.233.2.111 - ban specific ip address
|
||||
@ban/ip 134.233.2.* - ban all in a subnet
|
||||
@ban/ip 134.233.*.* - even wider ban
|
||||
|
||||
@ban/ip 134.233.2.* - ban all in a subnet
|
||||
@ban/ip 134.233.*.* - even wider ban
|
||||
|
||||
A single IP filter is easy to circumvent by changing the computer
|
||||
(also, some ISPs assign only temporary IPs to their users in the
|
||||
first placer. Widening the IP block filter with wildcards might be
|
||||
tempting, but remember that blocking too much may accidentally
|
||||
also block innocent users connecting from the same country and
|
||||
region.
|
||||
|
||||
|
||||
"""
|
||||
key = "@ban"
|
||||
aliases = ["@bans"]
|
||||
|
|
@ -173,25 +173,25 @@ class CmdBan(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"""
|
||||
Bans are stored in a serverconf db object as a list of
|
||||
dictionaries:
|
||||
Bans are stored in a serverconf db object as a list of
|
||||
dictionaries:
|
||||
[ (name, ip, ipregex, date, reason),
|
||||
(name, ip, ipregex, date, reason),... ]
|
||||
where name and ip are set by the user and are shown in
|
||||
lists. ipregex is a converted form of ip where the * is
|
||||
replaced by an appropriate regex pattern for fast
|
||||
matching. date is the time stamp the ban was instigated and
|
||||
'reason' is any optional info given to the command. Unset
|
||||
'reason' is any optional info given to the command. Unset
|
||||
values in each tuple is set to the empty string.
|
||||
"""
|
||||
"""
|
||||
banlist = ServerConfig.objects.conf('server_bans')
|
||||
if not banlist:
|
||||
banlist = []
|
||||
|
||||
if not self.args or (self.switches
|
||||
and not any(switch in ('ip', 'name') for switch in self.switches)):
|
||||
|
||||
if not self.args or (self.switches
|
||||
and not any(switch in ('ip', 'name') for switch in self.switches)):
|
||||
self.caller.msg(list_bans(banlist))
|
||||
return
|
||||
return
|
||||
|
||||
now = time.ctime()
|
||||
reason = ""
|
||||
|
|
@ -199,13 +199,13 @@ class CmdBan(MuxCommand):
|
|||
ban, reason = self.args.rsplit(':',1)
|
||||
else:
|
||||
ban = self.args
|
||||
ban = ban.lower()
|
||||
ban = ban.lower()
|
||||
ipban = IPREGEX.findall(ban)
|
||||
if not ipban:
|
||||
# store as name
|
||||
# store as name
|
||||
typ = "Name"
|
||||
bantup = (ban, "", "", now, reason)
|
||||
else:
|
||||
bantup = (ban, "", "", now, reason)
|
||||
else:
|
||||
# an ip address.
|
||||
typ = "IP"
|
||||
ban = ipban[0]
|
||||
|
|
@ -215,16 +215,16 @@ class CmdBan(MuxCommand):
|
|||
print "regex:",ipregex
|
||||
ipregex = re.compile(r"%s" % ipregex)
|
||||
bantup = ("", ban, ipregex, now, reason)
|
||||
# save updated banlist
|
||||
# save updated banlist
|
||||
banlist.append(bantup)
|
||||
ServerConfig.objects.conf('server_bans', banlist)
|
||||
ServerConfig.objects.conf('server_bans', banlist)
|
||||
self.caller.msg("%s-Ban {w%s{x was added." % (typ, ban))
|
||||
|
||||
class CmdUnban(MuxCommand):
|
||||
class CmdUnban(MuxCommand):
|
||||
"""
|
||||
remove a ban
|
||||
|
||||
Usage:
|
||||
Usage:
|
||||
@unban <banid>
|
||||
|
||||
This will clear a player name/ip ban previously set with the @ban
|
||||
|
|
@ -236,26 +236,26 @@ class CmdUnban(MuxCommand):
|
|||
key = "@unban"
|
||||
locks = "cmd:perm(unban) or perm(Immortals)"
|
||||
help_category="Admin"
|
||||
|
||||
|
||||
def func(self):
|
||||
"Implement unbanning"
|
||||
|
||||
banlist = ServerConfig.objects.conf('server_bans')
|
||||
|
||||
if not self.args:
|
||||
if not self.args:
|
||||
self.caller.msg(list_bans(banlist))
|
||||
return
|
||||
return
|
||||
|
||||
try:
|
||||
try:
|
||||
num = int(self.args)
|
||||
except Exception:
|
||||
self.caller.msg("You must supply a valid ban id to clear.")
|
||||
return
|
||||
return
|
||||
|
||||
if not banlist:
|
||||
if not banlist:
|
||||
self.caller.msg("There are no bans to clear.")
|
||||
elif not (0 < num < len(banlist) + 1):
|
||||
self.caller.msg("Ban id {w%s{x was not found." % self.args)
|
||||
self.caller.msg("Ban id {w%s{x was not found." % self.args)
|
||||
else:
|
||||
# all is ok, clear ban
|
||||
ban = banlist[num-1]
|
||||
|
|
@ -263,20 +263,20 @@ class CmdUnban(MuxCommand):
|
|||
ServerConfig.objects.conf('server_bans', banlist)
|
||||
self.caller.msg("Cleared ban %s: %s" % (num, " ".join([s for s in ban[:2]])))
|
||||
|
||||
|
||||
|
||||
class CmdDelPlayer(MuxCommand):
|
||||
"""
|
||||
delplayer - delete player from server
|
||||
|
||||
Usage:
|
||||
@delplayer[/switch] <name> [: reason]
|
||||
|
||||
|
||||
Switch:
|
||||
delobj - also delete the player's currently
|
||||
assigned in-game object.
|
||||
assigned in-game object.
|
||||
|
||||
Completely deletes a user from the server database,
|
||||
making their nick and e-mail again available.
|
||||
making their nick and e-mail again available.
|
||||
"""
|
||||
|
||||
key = "@delplayer"
|
||||
|
|
@ -287,10 +287,10 @@ class CmdDelPlayer(MuxCommand):
|
|||
"Implements the command."
|
||||
|
||||
caller = self.caller
|
||||
args = self.args
|
||||
args = self.args
|
||||
|
||||
if hasattr(caller, 'player'):
|
||||
caller = caller.player
|
||||
caller = caller.player
|
||||
|
||||
if not args:
|
||||
caller.msg("Usage: @delplayer[/delobj] <player/user name or #id> [: reason]")
|
||||
|
|
@ -309,26 +309,26 @@ class CmdDelPlayer(MuxCommand):
|
|||
except ValueError:
|
||||
pass
|
||||
|
||||
if not players:
|
||||
if not players:
|
||||
# try to find a user instead of a Player
|
||||
try:
|
||||
user = User.objects.get(id=args)
|
||||
except Exception:
|
||||
except Exception:
|
||||
try:
|
||||
user = User.objects.get(username__iexact=args)
|
||||
user = User.objects.get(username__iexact=args)
|
||||
except Exception:
|
||||
string = "No Player nor User found matching '%s'." % args
|
||||
caller.msg(string)
|
||||
return
|
||||
return
|
||||
try:
|
||||
player = user.get_profile()
|
||||
except Exception:
|
||||
player = None
|
||||
|
||||
player = None
|
||||
|
||||
if player and not player.access(caller, 'delete'):
|
||||
string = "You don't have the permissions to delete this player."
|
||||
caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
string = ""
|
||||
name = user.username
|
||||
|
|
@ -340,13 +340,13 @@ class CmdDelPlayer(MuxCommand):
|
|||
else:
|
||||
string += "The User %s was deleted. It had no Player associated with it." % name
|
||||
caller.msg(string)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
elif utils.is_iter(players):
|
||||
string = "There were multiple matches:"
|
||||
for player in players:
|
||||
string += "\n %s %s" % (player.id, player.key)
|
||||
return
|
||||
string += "\n %s %s" % (player.id, player.key)
|
||||
return
|
||||
else:
|
||||
# one single match
|
||||
|
||||
|
|
@ -357,10 +357,10 @@ class CmdDelPlayer(MuxCommand):
|
|||
if not player.access(caller, 'delete'):
|
||||
string = "You don't have the permissions to delete that player."
|
||||
caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
uname = user.username
|
||||
# boot the player then delete
|
||||
# boot the player then delete
|
||||
if character and character.has_player:
|
||||
caller.msg("Booting and informing player ...")
|
||||
string = "\nYour account '%s' is being *permanently* deleted.\n" % uname
|
||||
|
|
@ -368,30 +368,30 @@ class CmdDelPlayer(MuxCommand):
|
|||
string += " Reason given:\n '%s'" % reason
|
||||
character.msg(string)
|
||||
caller.execute_cmd("@boot %s" % uname)
|
||||
|
||||
|
||||
player.delete()
|
||||
user.delete()
|
||||
user.delete()
|
||||
caller.msg("Player %s was successfully deleted." % uname)
|
||||
|
||||
|
||||
class CmdEmit(MuxCommand):
|
||||
class CmdEmit(MuxCommand):
|
||||
"""
|
||||
@emit
|
||||
|
||||
Usage:
|
||||
@emit[/switches] [<obj>, <obj>, ... =] <message>
|
||||
@remit [<obj>, <obj>, ... =] <message>
|
||||
@pemit [<obj>, <obj>, ... =] <message>
|
||||
@remit [<obj>, <obj>, ... =] <message>
|
||||
@pemit [<obj>, <obj>, ... =] <message>
|
||||
|
||||
Switches:
|
||||
room : limit emits to rooms only (default)
|
||||
players : limit emits to players only
|
||||
players : limit emits to players only
|
||||
contents : send to the contents of matched objects too
|
||||
|
||||
|
||||
Emits a message to the selected objects or to
|
||||
your immediate surroundings. If the object is a room,
|
||||
send to its contents. @remit and @pemit are just
|
||||
limited forms of @emit, for sending to rooms and
|
||||
send to its contents. @remit and @pemit are just
|
||||
limited forms of @emit, for sending to rooms and
|
||||
to players respectively.
|
||||
"""
|
||||
key = "@emit"
|
||||
|
|
@ -401,7 +401,7 @@ class CmdEmit(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"Implement the command"
|
||||
|
||||
|
||||
caller = self.caller
|
||||
args = self.args
|
||||
|
||||
|
|
@ -411,12 +411,12 @@ class CmdEmit(MuxCommand):
|
|||
string += "\n@remit [<obj>, <obj>, ... =] <message>"
|
||||
string += "\n@pemit [<obj>, <obj>, ... =] <message>"
|
||||
caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
rooms_only = 'rooms' in self.switches
|
||||
players_only = 'players' in self.switches
|
||||
send_to_contents = 'contents' in self.switches
|
||||
|
||||
|
||||
# we check which command was used to force the switches
|
||||
if self.cmdstring == '@remit':
|
||||
rooms_only = True
|
||||
|
|
@ -429,12 +429,12 @@ class CmdEmit(MuxCommand):
|
|||
else:
|
||||
message = self.rhs
|
||||
objnames = self.lhslist
|
||||
|
||||
|
||||
# send to all objects
|
||||
for objname in objnames:
|
||||
obj = caller.search(objname, global_search=True)
|
||||
if not obj:
|
||||
return
|
||||
return
|
||||
if rooms_only and not obj.location == None:
|
||||
caller.msg("%s is not a room. Ignored." % objname)
|
||||
continue
|
||||
|
|
@ -463,7 +463,7 @@ class CmdNewPassword(MuxCommand):
|
|||
|
||||
Set a player's password.
|
||||
"""
|
||||
|
||||
|
||||
key = "@userpassword"
|
||||
locks = "cmd:perm(newpassword) or perm(Wizards)"
|
||||
help_category = "Admin"
|
||||
|
|
@ -475,12 +475,12 @@ class CmdNewPassword(MuxCommand):
|
|||
|
||||
if not self.rhs:
|
||||
caller.msg("Usage: @userpassword <user obj> = <new password>")
|
||||
return
|
||||
|
||||
# the player search also matches 'me' etc.
|
||||
player = caller.search("*%s" % self.lhs, global_search=True, player=True)
|
||||
return
|
||||
|
||||
# the player search also matches 'me' etc.
|
||||
player = caller.search("*%s" % self.lhs, global_search=True, player=True)
|
||||
if not player:
|
||||
return
|
||||
return
|
||||
player.user.set_password(self.rhs)
|
||||
player.user.save()
|
||||
caller.msg("%s - new password set to '%s'." % (player.name, self.rhs))
|
||||
|
|
@ -495,12 +495,12 @@ class CmdPerm(MuxCommand):
|
|||
Usage:
|
||||
@perm[/switch] <object> [= <permission>[,<permission>,...]]
|
||||
@perm[/switch] *<player> [= <permission>[,<permission>,...]]
|
||||
|
||||
|
||||
Switches:
|
||||
del : delete the given permission from <object> or <player>.
|
||||
player : set permission on a player (same as adding * to name)
|
||||
|
||||
This command sets/clears individual permission strings on an object
|
||||
This command sets/clears individual permission strings on an object
|
||||
or player. If no permission is given, list all permissions on <object>.
|
||||
"""
|
||||
key = "@perm"
|
||||
|
|
@ -515,19 +515,19 @@ class CmdPerm(MuxCommand):
|
|||
switches = self.switches
|
||||
lhs, rhs = self.lhs, self.rhs
|
||||
|
||||
if not self.args:
|
||||
string = "Usage: @perm[/switch] object [ = permission, permission, ...]"
|
||||
if not self.args:
|
||||
string = "Usage: @perm[/switch] object [ = permission, permission, ...]"
|
||||
caller.msg(string)
|
||||
return
|
||||
|
||||
|
||||
playermode = 'player' in self.switches or lhs.startswith('*')
|
||||
|
||||
# locate the object
|
||||
|
||||
# locate the object
|
||||
obj = caller.search(lhs, global_search=True, player=playermode)
|
||||
if not obj:
|
||||
return
|
||||
|
||||
if not rhs:
|
||||
return
|
||||
|
||||
if not rhs:
|
||||
if not obj.access(caller, 'examine'):
|
||||
caller.msg("You are not allowed to examine this object.")
|
||||
return
|
||||
|
|
@ -539,15 +539,15 @@ class CmdPerm(MuxCommand):
|
|||
string += ", ".join(obj.permissions)
|
||||
if hasattr(obj, 'player') and hasattr(obj.player, 'is_superuser') and obj.player.is_superuser:
|
||||
string += "\n(... but this object is currently controlled by a SUPERUSER! "
|
||||
string += "All access checks are passed automatically.)"
|
||||
string += "All access checks are passed automatically.)"
|
||||
caller.msg(string)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
# we supplied an argument on the form obj = perm
|
||||
|
||||
if not obj.access(caller, 'control'):
|
||||
caller.msg("You are not allowed to edit this object's permissions.")
|
||||
return
|
||||
return
|
||||
|
||||
cstring = ""
|
||||
tstring = ""
|
||||
|
|
@ -561,24 +561,24 @@ class CmdPerm(MuxCommand):
|
|||
continue
|
||||
permissions = obj.permissions
|
||||
del permissions[index]
|
||||
obj.permissions = permissions
|
||||
obj.permissions = permissions
|
||||
cstring += "\nPermission '%s' was removed from %s." % (perm, obj.name)
|
||||
tstring += "\n%s revokes the permission '%s' from you." % (caller.name, perm)
|
||||
else:
|
||||
# add a new permission
|
||||
# add a new permission
|
||||
permissions = obj.permissions
|
||||
|
||||
caller.permissions
|
||||
|
||||
caller.permissions
|
||||
|
||||
|
||||
|
||||
for perm in self.rhslist:
|
||||
|
||||
|
||||
# don't allow to set a permission higher in the hierarchy than the one the
|
||||
# caller has (to prevent self-escalation)
|
||||
if perm.lower() in PERMISSION_HIERARCHY and not obj.locks.check_lockstring(caller, "dummy:perm(%s)" % perm):
|
||||
caller.msg("You cannot assign a permission higher than the one you have yourself.")
|
||||
return
|
||||
return
|
||||
|
||||
if perm in permissions:
|
||||
cstring += "\nPermission '%s' is already defined on %s." % (rhs, obj.name)
|
||||
|
|
@ -586,7 +586,7 @@ class CmdPerm(MuxCommand):
|
|||
permissions.append(perm)
|
||||
obj.permissions = permissions
|
||||
cstring += "\nPermission '%s' given to %s." % (rhs, obj.name)
|
||||
tstring += "\n%s gives you the permission '%s'." % (caller.name, rhs)
|
||||
tstring += "\n%s gives you the permission '%s'." % (caller.name, rhs)
|
||||
caller.msg(cstring.strip())
|
||||
if tstring:
|
||||
obj.msg(tstring.strip())
|
||||
|
|
@ -597,7 +597,7 @@ class CmdWall(MuxCommand):
|
|||
|
||||
Usage:
|
||||
@wall <message>
|
||||
|
||||
|
||||
Announces a message to all connected players.
|
||||
"""
|
||||
key = "@wall"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
"""
|
||||
Batch processors
|
||||
|
||||
These commands implements the 'batch-command' and 'batch-code'
|
||||
processors, using the functionality in src.utils.batchprocessors.
|
||||
They allow for offline world-building.
|
||||
These commands implements the 'batch-command' and 'batch-code'
|
||||
processors, using the functionality in src.utils.batchprocessors.
|
||||
They allow for offline world-building.
|
||||
|
||||
Batch-command is the simpler system. This reads a file (*.ev)
|
||||
containing a list of in-game commands and executes them in sequence as
|
||||
if they had been entered in the game (including permission checks
|
||||
etc).
|
||||
|
||||
Example batch-command file: game/gamesrc/commands/examples/example_batch_cmd.ev
|
||||
Example batch-command file: game/gamesrc/commands/examples/example_batch_cmd.ev
|
||||
|
||||
Batch-code is a full-fledged python code interpreter that reads blocks
|
||||
of python code (*.py) and executes them in sequence. This allows for
|
||||
|
|
@ -18,7 +18,7 @@ much more power than Batch-command, but requires knowing Python and
|
|||
the Evennia API. It is also a severe security risk and should
|
||||
therefore always be limited to superusers only.
|
||||
|
||||
Example batch-code file: game/gamesrc/commands/examples/example_batch_code.py
|
||||
Example batch-code file: game/gamesrc/commands/examples/example_batch_code.py
|
||||
|
||||
"""
|
||||
from traceback import format_exc
|
||||
|
|
@ -42,10 +42,10 @@ UTF8_ERROR = \
|
|||
fine and fully supported! But for Evennia to know how to decode such
|
||||
characters in a universal way, the batchfile must be saved with the
|
||||
international 'UTF-8' encoding. This file is not.
|
||||
|
||||
|
||||
Please re-save the batchfile with the UTF-8 encoding (refer to the
|
||||
documentation of your text editor on how to do this, or switch to a
|
||||
better featured one) and try again.
|
||||
documentation of your text editor on how to do this, or switch to a
|
||||
better featured one) and try again.
|
||||
|
||||
The (first) error was found with a character on line %s in the file.
|
||||
"""
|
||||
|
|
@ -60,16 +60,16 @@ def format_header(caller, entry):
|
|||
Formats a header
|
||||
"""
|
||||
width = HEADER_WIDTH - 10
|
||||
entry = entry.strip()
|
||||
entry = entry.strip()
|
||||
header = utils.crop(entry, width=width)
|
||||
ptr = caller.ndb.batch_stackptr + 1
|
||||
stacklen = len(caller.ndb.batch_stack)
|
||||
ptr = caller.ndb.batch_stackptr + 1
|
||||
stacklen = len(caller.ndb.batch_stack)
|
||||
header = "{w%02i/%02i{G: %s{n" % (ptr, stacklen, header)
|
||||
# add extra space to the side for padding.
|
||||
header = "%s%s" % (header, " "*(width - len(header)))
|
||||
header = header.replace('\n', '\\n')
|
||||
|
||||
return header
|
||||
|
||||
return header
|
||||
|
||||
def format_code(entry):
|
||||
"""
|
||||
|
|
@ -89,7 +89,7 @@ def batch_cmd_exec(caller):
|
|||
command = stack[ptr]
|
||||
caller.msg(format_header(caller, command))
|
||||
try:
|
||||
caller.execute_cmd(command)
|
||||
caller.execute_cmd(command)
|
||||
except Exception:
|
||||
caller.msg(format_code(format_exc()))
|
||||
return False
|
||||
|
|
@ -98,24 +98,24 @@ def batch_cmd_exec(caller):
|
|||
def batch_code_exec(caller):
|
||||
"""
|
||||
Helper function for executing a single batch-code entry
|
||||
"""
|
||||
"""
|
||||
ptr = caller.ndb.batch_stackptr
|
||||
stack = caller.ndb.batch_stack
|
||||
debug = caller.ndb.batch_debug
|
||||
codedict = stack[ptr]
|
||||
|
||||
|
||||
caller.msg(format_header(caller, codedict['code']))
|
||||
err = BATCHCODE.code_exec(codedict,
|
||||
extra_environ={"caller":caller}, debug=debug)
|
||||
err = BATCHCODE.code_exec(codedict,
|
||||
extra_environ={"caller":caller}, debug=debug)
|
||||
if err:
|
||||
caller.msg(format_code(err))
|
||||
return False
|
||||
return True
|
||||
return True
|
||||
|
||||
def step_pointer(caller, step=1):
|
||||
"""
|
||||
Step in stack, returning the item located.
|
||||
|
||||
|
||||
stackptr - current position in stack
|
||||
stack - the stack of units
|
||||
step - how many steps to move from stackptr
|
||||
|
|
@ -139,10 +139,10 @@ def show_curr(caller, showall=False):
|
|||
if stackptr >= len(stack):
|
||||
caller.ndb.batch_stackptr = len(stack) - 1
|
||||
show_curr(caller, showall)
|
||||
return
|
||||
return
|
||||
|
||||
entry = stack[stackptr]
|
||||
|
||||
entry = stack[stackptr]
|
||||
|
||||
if type(entry) == dict:
|
||||
# this is a batch-code entry
|
||||
string = format_header(caller, entry['code'])
|
||||
|
|
@ -160,7 +160,7 @@ def show_curr(caller, showall=False):
|
|||
def purge_processor(caller):
|
||||
"""
|
||||
This purges all effects running
|
||||
on the caller.
|
||||
on the caller.
|
||||
"""
|
||||
try:
|
||||
del caller.ndb.batch_stack
|
||||
|
|
@ -169,17 +169,17 @@ def purge_processor(caller):
|
|||
del caller.ndb.batch_batchmode
|
||||
except:
|
||||
pass
|
||||
# clear everything but the default cmdset.
|
||||
caller.cmdset.delete(BatchSafeCmdSet)
|
||||
caller.cmdset.clear()
|
||||
# clear everything but the default cmdset.
|
||||
caller.cmdset.delete(BatchSafeCmdSet)
|
||||
caller.cmdset.clear()
|
||||
caller.scripts.validate() # this will purge interactive mode
|
||||
|
||||
#------------------------------------------------------------
|
||||
# main access commands
|
||||
# main access commands
|
||||
#------------------------------------------------------------
|
||||
|
||||
class CmdBatchCommands(MuxCommand):
|
||||
"""
|
||||
"""
|
||||
Build from batch-command file
|
||||
|
||||
Usage:
|
||||
|
|
@ -188,9 +188,9 @@ class CmdBatchCommands(MuxCommand):
|
|||
Switch:
|
||||
interactive - this mode will offer more control when
|
||||
executing the batch file, like stepping,
|
||||
skipping, reloading etc.
|
||||
skipping, reloading etc.
|
||||
|
||||
Runs batches of commands from a batch-cmd text file (*.ev).
|
||||
Runs batches of commands from a batch-cmd text file (*.ev).
|
||||
|
||||
"""
|
||||
key = "@batchcommands"
|
||||
|
|
@ -200,23 +200,23 @@ class CmdBatchCommands(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"Starts the processor."
|
||||
|
||||
|
||||
caller = self.caller
|
||||
|
||||
args = self.args
|
||||
if not args:
|
||||
caller.msg("Usage: @batchcommands[/interactive] <path.to.file>")
|
||||
return
|
||||
return
|
||||
python_path = self.args
|
||||
|
||||
#parse indata file
|
||||
#parse indata file
|
||||
|
||||
try:
|
||||
commands = BATCHCMD.parse_file(python_path)
|
||||
except UnicodeDecodeError, err:
|
||||
lnum = err.linenum
|
||||
caller.msg(UTF8_ERROR % (python_path, lnum))
|
||||
return
|
||||
return
|
||||
|
||||
if not commands:
|
||||
string = "'%s' not found.\nYou have to supply the python path "
|
||||
|
|
@ -225,37 +225,37 @@ class CmdBatchCommands(MuxCommand):
|
|||
return
|
||||
switches = self.switches
|
||||
|
||||
# Store work data in cache
|
||||
# Store work data in cache
|
||||
caller.ndb.batch_stack = commands
|
||||
caller.ndb.batch_stackptr = 0
|
||||
caller.ndb.batch_pythonpath = python_path
|
||||
caller.ndb.batch_batchmode = "batch_commands"
|
||||
caller.cmdset.add(BatchSafeCmdSet)
|
||||
caller.cmdset.add(BatchSafeCmdSet)
|
||||
|
||||
if 'inter' in switches or 'interactive' in switches:
|
||||
# Allow more control over how batch file is executed
|
||||
|
||||
# Set interactive state directly
|
||||
# Set interactive state directly
|
||||
caller.cmdset.add(BatchInteractiveCmdSet)
|
||||
|
||||
caller.msg("\nBatch-command processor - Interactive mode for %s ..." % python_path)
|
||||
show_curr(caller)
|
||||
else:
|
||||
caller.msg("Running Batch-command processor - Automatic mode for %s ..." % python_path)
|
||||
|
||||
|
||||
# add the 'safety' cmdset in case the batch processing adds cmdsets to us
|
||||
for inum in range(len(commands)):
|
||||
# loop through the batch file
|
||||
# loop through the batch file
|
||||
if not batch_cmd_exec(caller):
|
||||
return
|
||||
return
|
||||
step_pointer(caller, 1)
|
||||
# clean out the safety cmdset and clean out all other temporary attrs.
|
||||
string = " Batchfile '%s' applied." % python_path
|
||||
# clean out the safety cmdset and clean out all other temporary attrs.
|
||||
string = " Batchfile '%s' applied." % python_path
|
||||
caller.msg("{G%s" % string)
|
||||
purge_processor(caller)
|
||||
|
||||
class CmdBatchCode(MuxCommand):
|
||||
"""
|
||||
"""
|
||||
Build from batch-code file
|
||||
|
||||
Usage:
|
||||
|
|
@ -264,29 +264,29 @@ class CmdBatchCode(MuxCommand):
|
|||
Switch:
|
||||
interactive - this mode will offer more control when
|
||||
executing the batch file, like stepping,
|
||||
skipping, reloading etc.
|
||||
skipping, reloading etc.
|
||||
debug - auto-delete all objects that has been marked as
|
||||
deletable in the script file (see example files for
|
||||
syntax). This is useful so as to to not leave multiple
|
||||
object copies behind when testing out the script.
|
||||
|
||||
Runs batches of commands from a batch-code text file (*.py).
|
||||
Runs batches of commands from a batch-code text file (*.py).
|
||||
|
||||
"""
|
||||
key = "@batchcode"
|
||||
aliases = ["@batchcodes"]
|
||||
locks = "cmd:superuser()"
|
||||
locks = "cmd:superuser()"
|
||||
help_category = "Building"
|
||||
|
||||
def func(self):
|
||||
"Starts the processor."
|
||||
|
||||
|
||||
caller = self.caller
|
||||
|
||||
args = self.args
|
||||
if not args:
|
||||
caller.msg("Usage: @batchcode[/interactive/debug] <path.to.file>")
|
||||
return
|
||||
return
|
||||
python_path = self.args
|
||||
|
||||
#parse indata file
|
||||
|
|
@ -295,7 +295,7 @@ class CmdBatchCode(MuxCommand):
|
|||
except UnicodeDecodeError, err:
|
||||
lnum = err.linenum
|
||||
caller.msg(UTF8_ERROR % (python_path, lnum))
|
||||
return
|
||||
return
|
||||
|
||||
if not codes:
|
||||
string = "'%s' not found.\nYou have to supply the python path "
|
||||
|
|
@ -314,12 +314,12 @@ class CmdBatchCode(MuxCommand):
|
|||
caller.ndb.batch_pythonpath = python_path
|
||||
caller.ndb.batch_batchmode = "batch_code"
|
||||
caller.ndb.batch_debug = debug
|
||||
caller.cmdset.add(BatchSafeCmdSet)
|
||||
caller.cmdset.add(BatchSafeCmdSet)
|
||||
|
||||
if 'inter' in switches or 'interactive'in switches:
|
||||
# Allow more control over how batch file is executed
|
||||
|
||||
# Set interactive state directly
|
||||
# Set interactive state directly
|
||||
caller.cmdset.add(BatchInteractiveCmdSet)
|
||||
|
||||
caller.msg("\nBatch-code processor - Interactive mode for %s ..." % python_path)
|
||||
|
|
@ -328,11 +328,11 @@ class CmdBatchCode(MuxCommand):
|
|||
caller.msg("Running Batch-code processor - Automatic mode for %s ..." % python_path)
|
||||
# add the 'safety' cmdset in case the batch processing adds cmdsets to us
|
||||
for inum in range(len(codes)):
|
||||
# loop through the batch file
|
||||
# loop through the batch file
|
||||
if not batch_code_exec(caller):
|
||||
return
|
||||
return
|
||||
step_pointer(caller, 1)
|
||||
string = " Batchfile '%s' applied." % python_path
|
||||
string = " Batchfile '%s' applied." % python_path
|
||||
caller.msg("{G%s" % string)
|
||||
purge_processor(caller)
|
||||
|
||||
|
|
@ -346,41 +346,41 @@ class CmdStateAbort(MuxCommand):
|
|||
@abort
|
||||
|
||||
This is a safety feature. It force-ejects us out of the processor and to
|
||||
the default cmdset, regardless of what current cmdset the processor might
|
||||
the default cmdset, regardless of what current cmdset the processor might
|
||||
have put us in (e.g. when testing buggy scripts etc).
|
||||
"""
|
||||
key = "@abort"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
"Exit back to default."
|
||||
purge_processor(self.caller)
|
||||
self.caller.msg("Exited processor and reset out active cmdset back to the default one.")
|
||||
|
||||
|
||||
class CmdStateLL(MuxCommand):
|
||||
"""
|
||||
ll
|
||||
|
||||
|
||||
Look at the full source for the current
|
||||
command definition.
|
||||
command definition.
|
||||
"""
|
||||
key = "ll"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
def func(self):
|
||||
show_curr(self.caller, showall=True)
|
||||
|
||||
class CmdStatePP(MuxCommand):
|
||||
"""
|
||||
pp
|
||||
|
||||
|
||||
Process the currently shown command definition.
|
||||
"""
|
||||
key = "pp"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
|
|
@ -392,17 +392,17 @@ class CmdStatePP(MuxCommand):
|
|||
else:
|
||||
batch_cmd_exec(caller)
|
||||
|
||||
|
||||
|
||||
class CmdStateRR(MuxCommand):
|
||||
"""
|
||||
rr
|
||||
|
||||
Reload the batch file, keeping the current
|
||||
position in it.
|
||||
position in it.
|
||||
"""
|
||||
key = "rr"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -410,7 +410,7 @@ class CmdStateRR(MuxCommand):
|
|||
new_data = BATCHCODE.parse_file(caller.ndb.batch_pythonpath)
|
||||
else:
|
||||
new_data = BATCHCMD.parse_file(caller.ndb.batch_pythonpath)
|
||||
caller.ndb.batch_stack = new_data
|
||||
caller.ndb.batch_stack = new_data
|
||||
caller.msg(format_code("File reloaded. Staying on same command."))
|
||||
show_curr(caller)
|
||||
|
||||
|
|
@ -423,7 +423,7 @@ class CmdStateRRR(MuxCommand):
|
|||
"""
|
||||
key = "rrr"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -443,7 +443,7 @@ class CmdStateNN(MuxCommand):
|
|||
"""
|
||||
key = "nn"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -464,7 +464,7 @@ class CmdStateNL(MuxCommand):
|
|||
"""
|
||||
key = "nl"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -485,7 +485,7 @@ class CmdStateBB(MuxCommand):
|
|||
"""
|
||||
key = "bb"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -493,7 +493,7 @@ class CmdStateBB(MuxCommand):
|
|||
if arg and arg.isdigit():
|
||||
step = -int(self.args)
|
||||
else:
|
||||
step = -1
|
||||
step = -1
|
||||
step_pointer(caller, step)
|
||||
show_curr(caller)
|
||||
|
||||
|
|
@ -506,7 +506,7 @@ class CmdStateBL(MuxCommand):
|
|||
"""
|
||||
key = "bl"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -514,9 +514,9 @@ class CmdStateBL(MuxCommand):
|
|||
if arg and arg.isdigit():
|
||||
step = -int(self.args)
|
||||
else:
|
||||
step = -1
|
||||
step = -1
|
||||
step_pointer(caller, step)
|
||||
show_curr(caller, showall=True)
|
||||
show_curr(caller, showall=True)
|
||||
|
||||
class CmdStateSS(MuxCommand):
|
||||
"""
|
||||
|
|
@ -528,7 +528,7 @@ class CmdStateSS(MuxCommand):
|
|||
"""
|
||||
key = "ss"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -536,14 +536,14 @@ class CmdStateSS(MuxCommand):
|
|||
if arg and arg.isdigit():
|
||||
step = int(self.args)
|
||||
else:
|
||||
step = 1
|
||||
step = 1
|
||||
|
||||
for istep in range(step):
|
||||
if caller.ndb.batch_batchmode == "batch_code":
|
||||
batch_code_exec(caller)
|
||||
else:
|
||||
batch_cmd_exec(caller)
|
||||
step_pointer(caller, 1)
|
||||
step_pointer(caller, 1)
|
||||
show_curr(caller)
|
||||
|
||||
class CmdStateSL(MuxCommand):
|
||||
|
|
@ -552,11 +552,11 @@ class CmdStateSL(MuxCommand):
|
|||
|
||||
Process current command, then step to the next
|
||||
one, viewing its full source. If steps is given,
|
||||
process this many commands.
|
||||
process this many commands.
|
||||
"""
|
||||
key = "sl"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -564,7 +564,7 @@ class CmdStateSL(MuxCommand):
|
|||
if arg and arg.isdigit():
|
||||
step = int(self.args)
|
||||
else:
|
||||
step = 1
|
||||
step = 1
|
||||
|
||||
for istep in range(step):
|
||||
if caller.ndb.batch_batchmode == "batch_code":
|
||||
|
|
@ -583,7 +583,7 @@ class CmdStateCC(MuxCommand):
|
|||
"""
|
||||
key = "cc"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -604,7 +604,7 @@ class CmdStateCC(MuxCommand):
|
|||
del caller.ndb.batch_pythonpath
|
||||
del caller.ndb.batch_batchmode
|
||||
caller.msg(format_code("Finished processing batch file."))
|
||||
|
||||
|
||||
class CmdStateJJ(MuxCommand):
|
||||
"""
|
||||
j <command number>
|
||||
|
|
@ -613,7 +613,7 @@ class CmdStateJJ(MuxCommand):
|
|||
"""
|
||||
key = "j"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -622,9 +622,9 @@ class CmdStateJJ(MuxCommand):
|
|||
number = int(self.args)-1
|
||||
else:
|
||||
caller.msg(format_code("You must give a number index."))
|
||||
return
|
||||
return
|
||||
ptr = caller.ndb.batch_stackptr
|
||||
step = number - ptr
|
||||
step = number - ptr
|
||||
step_pointer(caller, step)
|
||||
show_curr(caller)
|
||||
|
||||
|
|
@ -636,7 +636,7 @@ class CmdStateJL(MuxCommand):
|
|||
"""
|
||||
key = "jl"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
caller = self.caller
|
||||
|
|
@ -645,43 +645,43 @@ class CmdStateJL(MuxCommand):
|
|||
number = int(self.args)-1
|
||||
else:
|
||||
caller.msg(format_code("You must give a number index."))
|
||||
return
|
||||
return
|
||||
ptr = caller.ndb.batch_stackptr
|
||||
step = number - ptr
|
||||
step = number - ptr
|
||||
step_pointer(caller, step)
|
||||
show_curr(caller, showall=True)
|
||||
|
||||
class CmdStateQQ(MuxCommand):
|
||||
"""
|
||||
qq
|
||||
qq
|
||||
|
||||
Quit the batchprocessor.
|
||||
"""
|
||||
key = "qq"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
purge_processor(self.caller)
|
||||
self.caller.msg("Aborted interactive batch mode.")
|
||||
|
||||
|
||||
class CmdStateHH(MuxCommand):
|
||||
"Help command"
|
||||
|
||||
key = "hh"
|
||||
help_category = "BatchProcess"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
locks = "cmd:perm(batchcommands)"
|
||||
|
||||
def func(self):
|
||||
string = """
|
||||
Interactive batch processing commands:
|
||||
|
||||
nn [steps] - next command (no processing)
|
||||
nl [steps] - next & look
|
||||
nl [steps] - next & look
|
||||
bb [steps] - back to previous command (no processing)
|
||||
bl [steps] - back & look
|
||||
bl [steps] - back & look
|
||||
jj <N> - jump to command nr N (no processing)
|
||||
jl <N> - jump & look
|
||||
jl <N> - jump & look
|
||||
pp - process currently shown command (no step)
|
||||
ss [steps] - process & step
|
||||
sl [steps] - process & step & look
|
||||
|
|
@ -693,9 +693,9 @@ class CmdStateHH(MuxCommand):
|
|||
cc - continue processing to end, then quit.
|
||||
qq - quit (abort all remaining commands)
|
||||
|
||||
@abort - this is a safety command that always is available
|
||||
@abort - this is a safety command that always is available
|
||||
regardless of what cmdsets gets added to us during
|
||||
batch-command processing. It immediately shuts down
|
||||
batch-command processing. It immediately shuts down
|
||||
the processor and returns us to the default cmdset.
|
||||
"""
|
||||
self.caller.msg(string)
|
||||
|
|
|
|||
|
|
@ -399,9 +399,8 @@ class CmdCreate(ObjManipCommand):
|
|||
# object typeclass will automatically be used)
|
||||
lockstring = "control:id(%s);examine:perm(Builders);delete:id(%s) or perm(Wizards);get:all()" % (caller.id, caller.id)
|
||||
obj = create.create_object(typeclass, name, caller,
|
||||
home=caller, aliases=aliases, locks=lockstring)
|
||||
home=caller, aliases=aliases, locks=lockstring, report_to=caller)
|
||||
if not obj:
|
||||
string = "Error when creating object."
|
||||
continue
|
||||
if aliases:
|
||||
string = "You create a new %s: %s (aliases: %s)."
|
||||
|
|
@ -416,8 +415,8 @@ class CmdCreate(ObjManipCommand):
|
|||
if caller.location:
|
||||
obj.home = caller.location
|
||||
obj.move_to(caller.location, quiet=True)
|
||||
if string:
|
||||
caller.msg(string)
|
||||
if string:
|
||||
caller.msg(string)
|
||||
|
||||
|
||||
class CmdDebug(MuxCommand):
|
||||
|
|
@ -630,7 +629,7 @@ class CmdDig(ObjManipCommand):
|
|||
lockstring = lockstring % (caller.dbref, caller.dbref, caller.dbref)
|
||||
|
||||
new_room = create.create_object(typeclass, room["name"],
|
||||
aliases=room["aliases"])
|
||||
aliases=room["aliases"], report_to=caller)
|
||||
new_room.locks.add(lockstring)
|
||||
alias_string = ""
|
||||
if new_room.aliases:
|
||||
|
|
@ -659,7 +658,7 @@ class CmdDig(ObjManipCommand):
|
|||
|
||||
new_to_exit = create.create_object(typeclass, to_exit["name"], location,
|
||||
aliases=to_exit["aliases"],
|
||||
locks=lockstring, destination=new_room)
|
||||
locks=lockstring, destination=new_room, report_to=caller)
|
||||
alias_string = ""
|
||||
if new_to_exit.aliases:
|
||||
alias_string = " (%s)" % ", ".join(new_to_exit.aliases)
|
||||
|
|
@ -684,7 +683,7 @@ class CmdDig(ObjManipCommand):
|
|||
typeclass = settings.BASE_EXIT_TYPECLASS
|
||||
new_back_exit = create.create_object(typeclass, back_exit["name"],
|
||||
new_room, aliases=back_exit["aliases"],
|
||||
locks=lockstring, destination=location)
|
||||
locks=lockstring, destination=location, report_to=caller)
|
||||
alias_string = ""
|
||||
if new_back_exit.aliases:
|
||||
alias_string = " (%s)" % ", ".join(new_back_exit.aliases)
|
||||
|
|
@ -1083,7 +1082,7 @@ class CmdOpen(ObjManipCommand):
|
|||
typeclass = settings.BASE_EXIT_TYPECLASS
|
||||
exit_obj = create.create_object(typeclass, key=exit_name,
|
||||
location=location,
|
||||
aliases=exit_aliases)
|
||||
aliases=exit_aliases, report_to=caller)
|
||||
if exit_obj:
|
||||
# storing a destination is what makes it an exit!
|
||||
exit_obj.destination = destination
|
||||
|
|
@ -1283,9 +1282,9 @@ class CmdTypeclass(MuxCommand):
|
|||
@typeclass - set object typeclass
|
||||
|
||||
Usage:
|
||||
@typclass[/switch] <object> [= <typeclass path>]
|
||||
@type ''
|
||||
@parent ''
|
||||
@typclass[/switch] <object> [= <typeclass.path>]
|
||||
@type ''
|
||||
@parent ''
|
||||
|
||||
Switch:
|
||||
reset - clean out *all* the attributes on the object -
|
||||
|
|
@ -1295,12 +1294,18 @@ class CmdTypeclass(MuxCommand):
|
|||
Example:
|
||||
@type button = examples.red_button.RedButton
|
||||
|
||||
Sets an object's typeclass. The typeclass must be identified
|
||||
by its location using python dot-notation pointing to the correct
|
||||
module and class. If no typeclass is given (or a wrong typeclass
|
||||
is given), the object will be set to the default typeclass.
|
||||
The location of the typeclass module is searched from
|
||||
the default typeclass directory, as defined in the server settings.
|
||||
View or set an object's typeclass. If setting, the creation hooks
|
||||
of the new typeclass will be run on the object. If you have
|
||||
clashing properties on the old class, use /reset. By default you
|
||||
are protected from changing to a typeclass of the same name as the
|
||||
one you already have, use /force to override this protection.
|
||||
|
||||
The given typeclass must be identified by its location using
|
||||
python dot-notation pointing to the correct module and class. If
|
||||
no typeclass is given (or a wrong typeclass is given). Errors in
|
||||
the path or new typeclass will lead to the old typeclass being
|
||||
kept. The location of the typeclass module is searched from the
|
||||
default typeclass directory, as defined in the server settings.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1327,7 +1332,7 @@ class CmdTypeclass(MuxCommand):
|
|||
# we did not supply a new typeclass, view the
|
||||
# current one instead.
|
||||
if hasattr(obj, "typeclass"):
|
||||
string = "%s's current typeclass is '%s'." % (obj.name, obj.typeclass.typename)
|
||||
string = "%s's current typeclass is '%s' (%s)." % (obj.name, obj.typeclass.typename, obj.typeclass.path)
|
||||
else:
|
||||
string = "%s is not a typed object." % obj.name
|
||||
caller.msg(string)
|
||||
|
|
@ -1344,25 +1349,31 @@ class CmdTypeclass(MuxCommand):
|
|||
caller.msg("This object cannot have a type at all!")
|
||||
return
|
||||
|
||||
if obj.is_typeclass(typeclass) and not 'force' in self.switches:
|
||||
string = "%s already has the typeclass '%s'." % (obj.name, typeclass)
|
||||
is_same = obj.is_typeclass(typeclass)
|
||||
if is_same and not 'force' in self.switches:
|
||||
string = "%s already has the typeclass '%s'. Use /force to override." % (obj.name, typeclass)
|
||||
else:
|
||||
reset = "reset" in self.switches
|
||||
old_typeclass_name = obj.typeclass.typename
|
||||
old_typeclass_path = obj.typeclass.path
|
||||
ok = obj.swap_typeclass(typeclass, clean_attributes=reset)
|
||||
if ok:
|
||||
string = "%s's type is now %s (instead of %s).\n" % (obj.name,
|
||||
obj.typeclass.typename,
|
||||
old_typeclass_name)
|
||||
if reset:
|
||||
string += "All attributes where reset."
|
||||
if is_same:
|
||||
string = "%s updated its existing typeclass (%s).\n" % (obj.name, obj.typeclass.path)
|
||||
else:
|
||||
string += "Note that the new class type could have overwritten "
|
||||
string += "same-named attributes on the existing object."
|
||||
string = "%s's changed typeclass from %s to %s.\n" % (obj.name,
|
||||
old_typeclass_path,
|
||||
obj.typeclass.path)
|
||||
string += "Creation hooks were run."
|
||||
if reset:
|
||||
string += " All old attributes where deleted before the swap."
|
||||
else:
|
||||
string += " Note that the typeclassed object could have ended up with a mixture of old"
|
||||
string += "\nand new attributes. Use /reset to remove old attributes if you don't want this."
|
||||
else:
|
||||
string = "Could not swap '%s' (%s) to typeclass '%s'." % (obj.name,
|
||||
old_typeclass_name,
|
||||
typeclass)
|
||||
string = obj.typeclass_last_errmsg
|
||||
string += "\nCould not swap '%s' (%s) to typeclass '%s'." % (obj.name,
|
||||
old_typeclass_path,
|
||||
typeclass)
|
||||
|
||||
caller.msg(string)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
Comsystem command module.
|
||||
|
||||
Comm commands are OOC commands and intended to be made available to
|
||||
the Player at all times (they go into the PlayerCmdSet). So we
|
||||
the Player at all times (they go into the PlayerCmdSet). So we
|
||||
make sure to homogenize self.caller to always be the player object
|
||||
for easy handling.
|
||||
for easy handling.
|
||||
|
||||
"""
|
||||
from django.conf import settings
|
||||
|
|
@ -12,7 +12,7 @@ from src.comms.models import Channel, Msg, PlayerChannelConnection, ExternalChan
|
|||
from src.comms import irc, imc2, rss
|
||||
from src.comms.channelhandler import CHANNELHANDLER
|
||||
from src.utils import create, utils
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
# limit symbol import for API
|
||||
__all__ = ("CommCommand", "CmdAddCom", "CmdDelCom", "CmdAllCom",
|
||||
|
|
@ -45,10 +45,10 @@ def find_channel(caller, channelname, silent=False, noaliases=False):
|
|||
class CommCommand(MuxCommand):
|
||||
"""
|
||||
This is a parent for comm-commands. Since
|
||||
These commands are to be available to the
|
||||
Player, we make sure to homogenize the caller
|
||||
here, so it's always seen as a player to the
|
||||
command body.
|
||||
These commands are to be available to the
|
||||
Player, we make sure to homogenize the caller
|
||||
here, so it's always seen as a player to the
|
||||
command body.
|
||||
"""
|
||||
|
||||
def parse(self):
|
||||
|
|
@ -60,14 +60,14 @@ class CommCommand(MuxCommand):
|
|||
if utils.inherits_from(self.caller, "src.objects.objects.Object"):
|
||||
# an object. Convert it to its player.
|
||||
self.caller = self.caller.player
|
||||
|
||||
|
||||
class CmdAddCom(MuxCommand):
|
||||
"""
|
||||
addcom - subscribe to a channel with optional alias
|
||||
|
||||
Usage:
|
||||
addcom [alias=] <channel>
|
||||
|
||||
|
||||
Joins a given channel. If alias is given, this will allow you to
|
||||
refer to the channel by this alias rather than the full channel
|
||||
name. Subsequent calls of this command can be used to add multiple
|
||||
|
|
@ -81,7 +81,7 @@ class CmdAddCom(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"Implement the command"
|
||||
|
||||
|
||||
caller = self.caller
|
||||
args = self.args
|
||||
player = caller
|
||||
|
|
@ -92,7 +92,7 @@ class CmdAddCom(MuxCommand):
|
|||
|
||||
if self.rhs:
|
||||
# rhs holds the channelname
|
||||
channelname = self.rhs
|
||||
channelname = self.rhs
|
||||
alias = self.lhs
|
||||
else:
|
||||
channelname = self.args
|
||||
|
|
@ -101,12 +101,12 @@ class CmdAddCom(MuxCommand):
|
|||
channel = find_channel(caller, channelname)
|
||||
if not channel:
|
||||
# we use the custom search method to handle errors.
|
||||
return
|
||||
return
|
||||
|
||||
# check permissions
|
||||
if not channel.access(player, 'listen'):
|
||||
caller.msg("%s: You are not allowed to listen to this channel." % channel.key)
|
||||
return
|
||||
return
|
||||
|
||||
string = ""
|
||||
if not channel.has_connection(player):
|
||||
|
|
@ -114,16 +114,16 @@ class CmdAddCom(MuxCommand):
|
|||
if not channel.connect_to(player):
|
||||
# if this would have returned True, the player is connected
|
||||
caller.msg("%s: You are not allowed to join this channel." % channel.key)
|
||||
return
|
||||
return
|
||||
else:
|
||||
string += "You now listen to the channel %s. " % channel.key
|
||||
else:
|
||||
string += "You are already connected to channel %s." % channel.key
|
||||
|
||||
|
||||
if alias:
|
||||
# create a nick and add it to the caller.
|
||||
caller.nicks.add(alias, channel.key, nick_type="channel")
|
||||
string += " You can now refer to the channel %s with the alias '%s'."
|
||||
string += " You can now refer to the channel %s with the alias '%s'."
|
||||
caller.msg(string % (channel.key, alias))
|
||||
else:
|
||||
string += " No alias added."
|
||||
|
|
@ -155,26 +155,26 @@ class CmdDelCom(MuxCommand):
|
|||
|
||||
if not self.args:
|
||||
caller.msg("Usage: delcom <alias or channel>")
|
||||
return
|
||||
return
|
||||
ostring = self.args.lower()
|
||||
|
||||
|
||||
channel = find_channel(caller, ostring, silent=True, noaliases=True)
|
||||
if channel:
|
||||
# we have given a channel name - unsubscribe
|
||||
if not channel.has_connection(player):
|
||||
caller.msg("You are not listening to that channel.")
|
||||
return
|
||||
return
|
||||
chkey = channel.key.lower()
|
||||
# find all nicks linked to this channel and delete them
|
||||
for nick in [nick for nick in caller.nicks.get(nick_type="channel")
|
||||
if nick.db_real.lower() == chkey]:
|
||||
for nick in [nick for nick in caller.nicks.get(nick_type="channel")
|
||||
if nick.db_real.lower() == chkey]:
|
||||
nick.delete()
|
||||
channel.disconnect_from(player)
|
||||
caller.msg("You stop listening to channel '%s'. Eventual aliases were removed." % channel.key)
|
||||
return
|
||||
return
|
||||
else:
|
||||
# we are removing a channel nick
|
||||
channame = caller.nicks.get(ostring, nick_type="channel")
|
||||
channame = caller.nicks.get(ostring, nick_type="channel")
|
||||
channel = find_channel(caller, channame, silent=True)
|
||||
if not channel:
|
||||
caller.msg("No channel with alias '%s' was found." % ostring)
|
||||
|
|
@ -184,13 +184,13 @@ class CmdDelCom(MuxCommand):
|
|||
caller.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key))
|
||||
else:
|
||||
caller.msg("You had no such alias defined for this channel.")
|
||||
|
||||
|
||||
class CmdAllCom(MuxCommand):
|
||||
"""
|
||||
allcom - operate on all channels
|
||||
|
||||
Usage:
|
||||
allcom [on | off | who | destroy]
|
||||
Usage:
|
||||
allcom [on | off | who | destroy]
|
||||
|
||||
Allows the user to universally turn off or on all channels they are on,
|
||||
as well as perform a 'who' for all channels they are on. Destroy deletes
|
||||
|
|
@ -198,11 +198,11 @@ class CmdAllCom(MuxCommand):
|
|||
|
||||
Without argument, works like comlist.
|
||||
"""
|
||||
|
||||
|
||||
key = "allcom"
|
||||
locks = "cmd: not pperm(channel_banned)"
|
||||
help_category = "Comms"
|
||||
|
||||
|
||||
def func(self):
|
||||
"Runs the function"
|
||||
|
||||
|
|
@ -224,12 +224,12 @@ class CmdAllCom(MuxCommand):
|
|||
for channel in channels:
|
||||
caller.execute_cmd("delcom %s" % channel.key)
|
||||
elif args == "destroy":
|
||||
# destroy all channels you control
|
||||
# destroy all channels you control
|
||||
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'control')]
|
||||
for channel in channels:
|
||||
caller.execute_cmd("@cdestroy %s" % channel.key)
|
||||
elif args == "who":
|
||||
# run a who, listing the subscribers on visible channels.
|
||||
# run a who, listing the subscribers on visible channels.
|
||||
string = "\n{CChannel subscriptions{n"
|
||||
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'listen')]
|
||||
if not channels:
|
||||
|
|
@ -243,7 +243,7 @@ class CmdAllCom(MuxCommand):
|
|||
string += " <None>"
|
||||
caller.msg(string.strip())
|
||||
else:
|
||||
# wrong input
|
||||
# wrong input
|
||||
caller.msg("Usage: allcom on | off | who | clear")
|
||||
|
||||
class CmdChannels(MuxCommand):
|
||||
|
|
@ -255,7 +255,7 @@ class CmdChannels(MuxCommand):
|
|||
@clist
|
||||
comlist
|
||||
|
||||
Lists all channels available to you, wether you listen to them or not.
|
||||
Lists all channels available to you, wether you listen to them or not.
|
||||
Use 'comlist" to only view your current channel subscriptions.
|
||||
"""
|
||||
key = "@channels"
|
||||
|
|
@ -265,11 +265,11 @@ class CmdChannels(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"Implement function"
|
||||
|
||||
|
||||
caller = self.caller
|
||||
|
||||
|
||||
# all channels we have available to listen to
|
||||
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'listen')]
|
||||
channels = [chan for chan in Channel.objects.get_all_channels() if chan.access(caller, 'listen')]
|
||||
if not channels:
|
||||
caller.msg("No channels available.")
|
||||
return
|
||||
|
|
@ -278,7 +278,7 @@ class CmdChannels(MuxCommand):
|
|||
|
||||
if self.cmdstring != "comlist":
|
||||
|
||||
string = "\nChannels available:"
|
||||
string = "\nChannels available:"
|
||||
cols = [[" "], ["Channel"], ["Aliases"], ["Perms"], ["Description"]]
|
||||
for chan in channels:
|
||||
if chan in subs:
|
||||
|
|
@ -289,10 +289,10 @@ class CmdChannels(MuxCommand):
|
|||
cols[2].append(",".join(chan.aliases))
|
||||
cols[3].append(str(chan.locks))
|
||||
cols[4].append(chan.desc)
|
||||
# put into table
|
||||
# put into table
|
||||
for ir, row in enumerate(utils.format_table(cols)):
|
||||
if ir == 0:
|
||||
string += "\n{w" + "".join(row) + "{n"
|
||||
string += "\n{w" + "".join(row) + "{n"
|
||||
else:
|
||||
string += "\n" + "".join(row)
|
||||
self.caller.msg(string)
|
||||
|
|
@ -306,13 +306,13 @@ class CmdChannels(MuxCommand):
|
|||
for chan in subs:
|
||||
cols[0].append(" ")
|
||||
cols[1].append(chan.key)
|
||||
cols[2].append(",".join([nick.db_nick for nick in nicks
|
||||
cols[2].append(",".join([nick.db_nick for nick in nicks
|
||||
if nick.db_real.lower() == chan.key.lower()] + chan.aliases))
|
||||
cols[3].append(chan.desc)
|
||||
# put into table
|
||||
for ir, row in enumerate(utils.format_table(cols)):
|
||||
if ir == 0:
|
||||
string += "\n{w" + "".join(row) + "{n"
|
||||
string += "\n{w" + "".join(row) + "{n"
|
||||
else:
|
||||
string += "\n" + "".join(row)
|
||||
caller.msg(string)
|
||||
|
|
@ -341,10 +341,10 @@ class CmdCdestroy(MuxCommand):
|
|||
channel = find_channel(caller, self.args)
|
||||
if not channel:
|
||||
caller.msg("Could not find channel %s." % self.args)
|
||||
return
|
||||
return
|
||||
if not channel.access(caller, 'control'):
|
||||
caller.msg("You are not allowed to do that.")
|
||||
return
|
||||
return
|
||||
|
||||
message = "%s is being destroyed. Make sure to change your aliases." % channel
|
||||
msgobj = create.create_message(caller, message, channel)
|
||||
|
|
@ -352,7 +352,7 @@ class CmdCdestroy(MuxCommand):
|
|||
channel.delete()
|
||||
CHANNELHANDLER.update()
|
||||
caller.msg("%s was destroyed." % channel)
|
||||
|
||||
|
||||
class CmdCBoot(MuxCommand):
|
||||
"""
|
||||
@cboot
|
||||
|
|
@ -370,24 +370,24 @@ class CmdCBoot(MuxCommand):
|
|||
key = "@cboot"
|
||||
locks = "cmd: not pperm(channel_banned)"
|
||||
help_category = "Comms"
|
||||
|
||||
|
||||
def func(self):
|
||||
"implement the function"
|
||||
|
||||
|
||||
if not self.args or not self.rhs:
|
||||
string = "Usage: @cboot[/quiet] <channel> = <player> [:reason]"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
channel = find_channel(self.caller, self.lhs)
|
||||
if not channel:
|
||||
return
|
||||
reason = ""
|
||||
if ":" in self.rhs:
|
||||
playername, reason = self.rhs.rsplit(":", 1)
|
||||
playername, reason = self.rhs.rsplit(":", 1)
|
||||
searchstring = playername.lstrip('*')
|
||||
else:
|
||||
searchstring = self.rhs.lstrip('*')
|
||||
searchstring = self.rhs.lstrip('*')
|
||||
player = self.caller.search(searchstring, player=True)
|
||||
if not player:
|
||||
return
|
||||
|
|
@ -396,7 +396,7 @@ class CmdCBoot(MuxCommand):
|
|||
if not channel.access(self.caller, "control"):
|
||||
string = "You don't control this channel."
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
if not PlayerChannelConnection.objects.has_connection(player, channel):
|
||||
string = "Player %s is not connected to channel %s." % (player.key, channel.key)
|
||||
self.caller.msg(string)
|
||||
|
|
@ -405,10 +405,10 @@ class CmdCBoot(MuxCommand):
|
|||
string = "%s boots %s from channel.%s" % (self.caller, player.key, reason)
|
||||
channel.msg(string)
|
||||
# find all player's nicks linked to this channel and delete them
|
||||
for nick in [nick for nick in player.character.nicks.get(nick_type="channel")
|
||||
if nick.db_real.lower() == channel.key]:
|
||||
for nick in [nick for nick in player.character.nicks.get(nick_type="channel")
|
||||
if nick.db_real.lower() == channel.key]:
|
||||
nick.delete()
|
||||
# disconnect player
|
||||
# disconnect player
|
||||
channel.disconnect_from(player)
|
||||
|
||||
class CmdCemit(MuxCommand):
|
||||
|
|
@ -426,9 +426,9 @@ class CmdCemit(MuxCommand):
|
|||
Allows the user to broadcast a message over a channel as long as
|
||||
they control it. It does not show the user's name unless they
|
||||
provide the /sendername switch.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
key = "@cemit"
|
||||
aliases = ["@cmsg"]
|
||||
locks = "cmd: not pperm(channel_banned)"
|
||||
|
|
@ -440,18 +440,18 @@ class CmdCemit(MuxCommand):
|
|||
if not self.args or not self.rhs:
|
||||
string = "Usage: @cemit[/switches] <channel> = <message>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
channel = find_channel(self.caller, self.lhs)
|
||||
if not channel:
|
||||
return
|
||||
if not channel.access(self.caller, "control"):
|
||||
string = "You don't control this channel."
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
message = self.rhs
|
||||
if "sendername" in self.switches:
|
||||
message = "%s: %s" % (self.caller.key, message)
|
||||
if not "noheader" in self.switches:
|
||||
if not "noheader" in self.switches:
|
||||
message = "[%s] %s" % (channel.key, message)
|
||||
channel.msg(message)
|
||||
if not "quiet" in self.switches:
|
||||
|
|
@ -461,8 +461,8 @@ class CmdCemit(MuxCommand):
|
|||
class CmdCWho(MuxCommand):
|
||||
"""
|
||||
@cwho
|
||||
|
||||
Usage:
|
||||
|
||||
Usage:
|
||||
@cwho <channel>
|
||||
|
||||
List who is connected to a given channel you have access to.
|
||||
|
|
@ -473,18 +473,18 @@ class CmdCWho(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"implement function"
|
||||
|
||||
|
||||
if not self.args:
|
||||
string = "Usage: @cwho <channel>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
channel = find_channel(self.caller, self.lhs)
|
||||
if not channel:
|
||||
return
|
||||
return
|
||||
if not channel.access(self.caller, "listen"):
|
||||
string = "You can't access this channel."
|
||||
self.caller.msg(string)
|
||||
self.caller.msg(string)
|
||||
string = "\n{CChannel subscriptions{n"
|
||||
string += "\n{w%s:{n\n" % channel.key
|
||||
conns = PlayerChannelConnection.objects.get_all_connections(channel)
|
||||
|
|
@ -497,13 +497,13 @@ class CmdCWho(MuxCommand):
|
|||
class CmdChannelCreate(MuxCommand):
|
||||
"""
|
||||
@ccreate
|
||||
channelcreate
|
||||
channelcreate
|
||||
Usage:
|
||||
@ccreate <new channel>[;alias;alias...] = description
|
||||
|
||||
Creates a new channel owned by you.
|
||||
"""
|
||||
|
||||
|
||||
key = "@ccreate"
|
||||
aliases = "channelcreate"
|
||||
locks = "cmd:not pperm(channel_banned)"
|
||||
|
|
@ -517,7 +517,7 @@ class CmdChannelCreate(MuxCommand):
|
|||
if not self.args:
|
||||
caller.msg("Usage @ccreate <channelname>[;alias;alias..] = description")
|
||||
return
|
||||
|
||||
|
||||
description = ""
|
||||
|
||||
if self.rhs:
|
||||
|
|
@ -526,25 +526,25 @@ class CmdChannelCreate(MuxCommand):
|
|||
channame = lhs
|
||||
aliases = None
|
||||
if ';' in lhs:
|
||||
channame, aliases = [part.strip().lower()
|
||||
channame, aliases = [part.strip().lower()
|
||||
for part in lhs.split(';', 1) if part.strip()]
|
||||
aliases = [alias.strip().lower()
|
||||
for alias in aliases.split(';') if alias.strip()]
|
||||
channel = Channel.objects.channel_search(channame)
|
||||
aliases = [alias.strip().lower()
|
||||
for alias in aliases.split(';') if alias.strip()]
|
||||
channel = Channel.objects.channel_search(channame)
|
||||
if channel:
|
||||
caller.msg("A channel with that name already exists.")
|
||||
return
|
||||
return
|
||||
# Create and set the channel up
|
||||
lockstring = "send:all();listen:all();control:id(%s)" % caller.id
|
||||
new_chan = create.create_channel(channame, aliases, description, locks=lockstring)
|
||||
new_chan.connect_to(caller)
|
||||
caller.msg("Created channel %s and connected to it." % new_chan.key)
|
||||
|
||||
|
||||
|
||||
class CmdCset(MuxCommand):
|
||||
"""
|
||||
@cset - changes channel access restrictions
|
||||
|
||||
|
||||
Usage:
|
||||
@cset <channel> [= <lockstring>]
|
||||
|
||||
|
|
@ -559,26 +559,26 @@ class CmdCset(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"run the function"
|
||||
|
||||
|
||||
if not self.args:
|
||||
string = "Usage: @cset channel [= lockstring]"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
channel = find_channel(self.caller, self.lhs)
|
||||
if not channel:
|
||||
return
|
||||
return
|
||||
if not self.rhs:
|
||||
# no =, so just view the current locks
|
||||
string = "Current locks on %s:" % channel.key
|
||||
string = "%s\n %s" % (string, channel.locks)
|
||||
self.caller.msg(string)
|
||||
return
|
||||
# we want to add/change a lock.
|
||||
return
|
||||
# we want to add/change a lock.
|
||||
if not channel.access(self.caller, "control"):
|
||||
string = "You don't control this channel."
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
# Try to add the lock
|
||||
channel.locks.add(self.rhs)
|
||||
string = "Lock(s) applied. "
|
||||
|
|
@ -595,7 +595,7 @@ class CmdCdesc(MuxCommand):
|
|||
@cdesc <channel> = <description>
|
||||
|
||||
Changes the description of the channel as shown in
|
||||
channel lists.
|
||||
channel lists.
|
||||
"""
|
||||
|
||||
key = "@cdesc"
|
||||
|
|
@ -604,12 +604,12 @@ class CmdCdesc(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"Implement command"
|
||||
|
||||
|
||||
caller = self.caller
|
||||
|
||||
if not self.rhs:
|
||||
caller.msg("Usage: @cdesc <channel> = <description>")
|
||||
return
|
||||
return
|
||||
channel = find_channel(caller, self.lhs)
|
||||
if not channel:
|
||||
caller.msg("Channel '%s' not found." % self.lhs)
|
||||
|
|
@ -635,7 +635,7 @@ class CmdPage(MuxCommand):
|
|||
Switch:
|
||||
last - shows who you last messaged
|
||||
list - show your last <number> of tells/pages (default)
|
||||
|
||||
|
||||
Send a message to target user (if online). If no
|
||||
argument is given, you will get a list of your latest messages.
|
||||
"""
|
||||
|
|
@ -644,24 +644,24 @@ class CmdPage(MuxCommand):
|
|||
aliases = ['tell']
|
||||
locks = "cmd:not pperm(page_banned)"
|
||||
help_category = "Comms"
|
||||
|
||||
|
||||
def func(self):
|
||||
|
||||
|
||||
"Implement function using the Msg methods"
|
||||
|
||||
caller = self.caller
|
||||
player = caller
|
||||
|
||||
# get the messages we've sent
|
||||
messages_we_sent = list(Msg.objects.get_messages_by_sender(player))
|
||||
pages_we_sent = [msg for msg in messages_we_sent
|
||||
messages_we_sent = list(Msg.objects.get_messages_by_sender(player))
|
||||
pages_we_sent = [msg for msg in messages_we_sent
|
||||
if msg.receivers]
|
||||
# get last messages we've got
|
||||
pages_we_got = list(Msg.objects.get_messages_by_receiver(player))
|
||||
|
||||
pages_we_got = list(Msg.objects.get_messages_by_receiver(player))
|
||||
|
||||
if 'last' in self.switches:
|
||||
if pages_we_sent:
|
||||
string = "You last paged {c%s{n." % (", ".join([obj.name
|
||||
string = "You last paged {c%s{n." % (", ".join([obj.name
|
||||
for obj in pages_we_sent[-1].receivers]))
|
||||
caller.msg(string)
|
||||
return
|
||||
|
|
@ -680,15 +680,15 @@ class CmdPage(MuxCommand):
|
|||
number = int(self.args)
|
||||
except ValueError:
|
||||
caller.msg("Usage: tell [<player> = msg]")
|
||||
return
|
||||
return
|
||||
|
||||
if len(pages) > number:
|
||||
lastpages = pages[-number:]
|
||||
else:
|
||||
lastpages = pages
|
||||
|
||||
lastpages = "\n ".join(["{w%s{n {c%s{n to {c%s{n: %s" % (utils.datetime_format(page.date_sent),
|
||||
page.sender.name,
|
||||
lastpages = pages
|
||||
|
||||
lastpages = "\n ".join(["{w%s{n {c%s{n to {c%s{n: %s" % (utils.datetime_format(page.date_sent),
|
||||
page.sender.name,
|
||||
"{n,{c ".join([obj.name for obj in page.receivers]),
|
||||
page.message)
|
||||
for page in lastpages])
|
||||
|
|
@ -704,16 +704,16 @@ class CmdPage(MuxCommand):
|
|||
# We are sending. Build a list of targets
|
||||
|
||||
if not self.lhs:
|
||||
# If there are no targets, then set the targets
|
||||
# If there are no targets, then set the targets
|
||||
# to the last person they paged.
|
||||
if pages_we_sent:
|
||||
receivers = pages_we_sent[-1].receivers
|
||||
else:
|
||||
caller.msg("Who do you want to page?")
|
||||
return
|
||||
return
|
||||
else:
|
||||
receivers = self.lhslist
|
||||
|
||||
receivers = self.lhslist
|
||||
|
||||
recobjs = []
|
||||
for receiver in set(receivers):
|
||||
if isinstance(receiver, basestring):
|
||||
|
|
@ -724,22 +724,22 @@ class CmdPage(MuxCommand):
|
|||
pobj = receiver.character
|
||||
else:
|
||||
caller.msg("Who do you want to page?")
|
||||
return
|
||||
return
|
||||
recobjs.append(pobj)
|
||||
if not recobjs:
|
||||
caller.msg("No players matching your target were found.")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
header = "{wPlayer{n {c%s{n {wpages:{n" % caller.key
|
||||
message = self.rhs
|
||||
|
||||
# if message begins with a :, we assume it is a 'page-pose'
|
||||
if message.startswith(":"):
|
||||
if message.startswith(":"):
|
||||
message = "%s %s" % (caller.key, message.strip(':').strip())
|
||||
|
||||
# create the persistent message object
|
||||
msg = create.create_message(player, message,
|
||||
receivers=recobjs)
|
||||
msg = create.create_message(player, message,
|
||||
receivers=recobjs)
|
||||
|
||||
# tell the players they got a message.
|
||||
received = []
|
||||
|
|
@ -747,8 +747,8 @@ class CmdPage(MuxCommand):
|
|||
for pobj in recobjs:
|
||||
if not pobj.access(caller, 'msg'):
|
||||
rstrings.append("You are not allowed to page %s." % pobj)
|
||||
continue
|
||||
pobj.msg("%s %s" % (header, message))
|
||||
continue
|
||||
pobj.msg("%s %s" % (header, message))
|
||||
if hasattr(pobj, 'has_player') and not pobj.has_player:
|
||||
received.append("{C%s{n" % pobj.name)
|
||||
rstrings.append("%s is offline. They will see your message if they list their pages later." % received[-1])
|
||||
|
|
@ -768,19 +768,19 @@ class CmdIRC2Chan(MuxCommand):
|
|||
|
||||
Switches:
|
||||
/disconnect - this will delete the bot and remove the irc connection to the channel.
|
||||
/remove - "
|
||||
/remove - "
|
||||
/list - show all irc<->evennia mappings
|
||||
|
||||
Example:
|
||||
@irc2chan myircchan = irc.dalnet.net 6667 myevennia-channel evennia-bot
|
||||
|
||||
This creates an IRC bot that connects to a given IRC network and channel. It will
|
||||
relay everything said in the evennia channel to the IRC channel and vice versa. The
|
||||
bot will automatically connect at server start, so this comman need only be given once.
|
||||
The /disconnect switch will permanently delete the bot. To only temporarily deactivate it,
|
||||
use the @services command instead.
|
||||
This creates an IRC bot that connects to a given IRC network and channel. It will
|
||||
relay everything said in the evennia channel to the IRC channel and vice versa. The
|
||||
bot will automatically connect at server start, so this comman need only be given once.
|
||||
The /disconnect switch will permanently delete the bot. To only temporarily deactivate it,
|
||||
use the @services command instead.
|
||||
"""
|
||||
|
||||
|
||||
key = "@irc2chan"
|
||||
locks = "cmd:serversetting(IRC_ENABLED) and pperm(Immortals)"
|
||||
help_category = "Comms"
|
||||
|
|
@ -811,21 +811,21 @@ class CmdIRC2Chan(MuxCommand):
|
|||
self.caller.msg(string)
|
||||
else:
|
||||
self.caller.msg("No connections found.")
|
||||
return
|
||||
return
|
||||
|
||||
if not self.args or not self.rhs:
|
||||
string = "Usage: @irc2chan[/switches] <evennia_channel> = <ircnetwork> <port> <#irchannel> <botname>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
channel = self.lhs
|
||||
self.rhs = self.rhs.replace('#', ' ') # to avoid Python comment issues
|
||||
try:
|
||||
irc_network, irc_port, irc_channel, irc_botname = [part.strip() for part in self.rhs.split(None, 3)]
|
||||
irc_channel = "#%s" % irc_channel
|
||||
except Exception:
|
||||
except Exception:
|
||||
string = "IRC bot definition '%s' is not valid." % self.rhs
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches:
|
||||
chanmatch = find_channel(self.caller, channel, silent=True)
|
||||
|
|
@ -837,7 +837,7 @@ class CmdIRC2Chan(MuxCommand):
|
|||
self.caller.msg("IRC connection/bot could not be removed, does it exist?")
|
||||
else:
|
||||
self.caller.msg("IRC connection destroyed.")
|
||||
return
|
||||
return
|
||||
|
||||
channel = find_channel(self.caller, channel)
|
||||
if not channel:
|
||||
|
|
@ -845,7 +845,7 @@ class CmdIRC2Chan(MuxCommand):
|
|||
ok = irc.create_connection(channel, irc_network, irc_port, irc_channel, irc_botname)
|
||||
if not ok:
|
||||
self.caller.msg("This IRC connection already exists.")
|
||||
return
|
||||
return
|
||||
self.caller.msg("Connection created. Starting IRC bot.")
|
||||
|
||||
class CmdIMC2Chan(MuxCommand):
|
||||
|
|
@ -857,12 +857,12 @@ class CmdIMC2Chan(MuxCommand):
|
|||
|
||||
Switches:
|
||||
/disconnect - this clear the imc2 connection to the channel.
|
||||
/remove - "
|
||||
/remove - "
|
||||
/list - show all imc2<->evennia mappings
|
||||
|
||||
Example:
|
||||
@imc2chan myimcchan = ievennia
|
||||
|
||||
|
||||
Connect an existing evennia channel to a channel on an IMC2
|
||||
network. The network contact information is defined in settings and
|
||||
should already be accessed at this point. Use @imcchanlist to see
|
||||
|
|
@ -901,27 +901,27 @@ class CmdIMC2Chan(MuxCommand):
|
|||
self.caller.msg(string)
|
||||
else:
|
||||
self.caller.msg("No connections found.")
|
||||
return
|
||||
return
|
||||
|
||||
if not self.args or not self.rhs:
|
||||
string = "Usage: @imc2chan[/switches] <evennia_channel> = <imc2_channel>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
channel = self.lhs
|
||||
imc2_channel = self.rhs
|
||||
|
||||
|
||||
if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches:
|
||||
# we don't search for channels before this since we want to clear the link
|
||||
# also if the channel no longer exists.
|
||||
# also if the channel no longer exists.
|
||||
ok = imc2.delete_connection(channel, imc2_channel)
|
||||
if not ok:
|
||||
self.caller.msg("IMC2 connection could not be removed, does it exist?")
|
||||
else:
|
||||
self.caller.msg("IMC2 connection destroyed.")
|
||||
return
|
||||
return
|
||||
|
||||
# actually get the channel object
|
||||
# actually get the channel object
|
||||
channel = find_channel(self.caller, channel)
|
||||
if not channel:
|
||||
return
|
||||
|
|
@ -929,7 +929,7 @@ class CmdIMC2Chan(MuxCommand):
|
|||
ok = imc2.create_connection(channel, imc2_channel)
|
||||
if not ok:
|
||||
self.caller.msg("The connection %s <-> %s already exists." % (channel.key, imc2_channel))
|
||||
return
|
||||
return
|
||||
self.caller.msg("Created connection channel %s <-> IMC channel %s." % (channel.key, imc2_channel))
|
||||
|
||||
|
||||
|
|
@ -940,18 +940,18 @@ class CmdIMCInfo(MuxCommand):
|
|||
Usage:
|
||||
@imcinfo[/switches]
|
||||
@imcchanlist - list imc2 channels
|
||||
@imclist - list connected muds
|
||||
@imclist - list connected muds
|
||||
@imcwhois <playername> - whois info about a remote player
|
||||
|
||||
Switches for @imcinfo:
|
||||
channels - as @imcchanlist (default)
|
||||
games or muds - as @imclist
|
||||
games or muds - as @imclist
|
||||
whois - as @imcwhois (requires an additional argument)
|
||||
update - force an update of all lists
|
||||
|
||||
|
||||
Shows lists of games or channels on the IMC2 network.
|
||||
"""
|
||||
|
||||
|
||||
key = "@imcinfo"
|
||||
aliases = ["@imcchanlist", "@imclist", "@imcwhois"]
|
||||
locks = "cmd: serversetting(IMC2_ENABLED) and pperm(Wizards)"
|
||||
|
|
@ -966,18 +966,18 @@ class CmdIMCInfo(MuxCommand):
|
|||
return
|
||||
|
||||
if "update" in self.switches:
|
||||
# update the lists
|
||||
# update the lists
|
||||
import time
|
||||
from src.comms.imc2lib import imc2_packets as pck
|
||||
from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CLIENT
|
||||
# update connected muds
|
||||
# update connected muds
|
||||
IMC2_CLIENT.send_packet(pck.IMC2PacketKeepAliveRequest())
|
||||
# prune inactive muds
|
||||
# prune inactive muds
|
||||
for name, mudinfo in IMC2_MUDLIST.mud_list.items():
|
||||
if time.time() - mudinfo.last_updated > 3599:
|
||||
del IMC2_MUDLIST.mud_list[name]
|
||||
# update channel list
|
||||
IMC2_CLIENT.send_packet(pck.IMC2PacketIceRefresh())
|
||||
# update channel list
|
||||
IMC2_CLIENT.send_packet(pck.IMC2PacketIceRefresh())
|
||||
self.caller.msg("IMC2 lists were re-synced.")
|
||||
|
||||
elif "games" in self.switches or "muds" in self.switches or self.cmdstring == "@imclist":
|
||||
|
|
@ -999,24 +999,24 @@ class CmdIMCInfo(MuxCommand):
|
|||
cols[3].append(mud.port)
|
||||
ftable = utils.format_table(cols)
|
||||
for ir, row in enumerate(ftable):
|
||||
if ir == 0:
|
||||
if ir == 0:
|
||||
string += "\n{w" + "".join(row) + "{n"
|
||||
else:
|
||||
string += "\n" + "".join(row)
|
||||
string += "\n %i Muds found." % nmuds
|
||||
self.caller.msg(string)
|
||||
self.caller.msg(string)
|
||||
|
||||
elif "whois" in self.switches or self.cmdstring == "@imcwhois":
|
||||
# find out about a player
|
||||
if not self.args:
|
||||
if not self.args:
|
||||
self.caller.msg("Usage: @imcwhois <playername>")
|
||||
return
|
||||
from src.comms.imc2 import IMC2_CLIENT
|
||||
self.caller.msg("Sending IMC whois request. If you receive no response, no matches were found.")
|
||||
self.caller.msg("Sending IMC whois request. If you receive no response, no matches were found.")
|
||||
IMC2_CLIENT.msg_imc2(None, from_obj=self.caller, packet_type="imcwhois", data={"target":self.args})
|
||||
|
||||
elif not self.switches or "channels" in self.switches or self.cmdstring == "@imcchanlist":
|
||||
# show channels
|
||||
# show channels
|
||||
from src.comms.imc2 import IMC2_CHANLIST, IMC2_CLIENT
|
||||
|
||||
channels = IMC2_CHANLIST.get_channel_list()
|
||||
|
|
@ -1028,12 +1028,12 @@ class CmdIMCInfo(MuxCommand):
|
|||
nchans += 1
|
||||
cols[0].append(channel.name)
|
||||
cols[1].append(channel.localname)
|
||||
cols[2].append(channel.owner)
|
||||
cols[2].append(channel.owner)
|
||||
cols[3].append(channel.level)
|
||||
cols[4].append(channel.policy)
|
||||
ftable = utils.format_table(cols)
|
||||
for ir, row in enumerate(ftable):
|
||||
if ir == 0:
|
||||
if ir == 0:
|
||||
string += "\n{w" + "".join(row) + "{n"
|
||||
else:
|
||||
string += "\n" + "".join(row)
|
||||
|
|
@ -1045,19 +1045,19 @@ class CmdIMCInfo(MuxCommand):
|
|||
string = "Usage: imcinfo|imcchanlist|imclist"
|
||||
self.caller.msg(string)
|
||||
|
||||
# unclear if this is working ...
|
||||
# unclear if this is working ...
|
||||
class CmdIMCTell(MuxCommand):
|
||||
"""
|
||||
imctell - send a page to a remote IMC player
|
||||
|
||||
Usage:
|
||||
imctell User@MUD = <msg>
|
||||
imcpage "
|
||||
Usage:
|
||||
imctell User@MUD = <msg>
|
||||
imcpage "
|
||||
|
||||
Sends a page to a user on a remote MUD, connected
|
||||
over IMC2.
|
||||
over IMC2.
|
||||
"""
|
||||
|
||||
|
||||
key = "imctell"
|
||||
aliases = ["imcpage", "imc2tell", "imc2page"]
|
||||
locks = "cmd: serversetting(IMC2_ENABLED)"
|
||||
|
|
@ -1072,11 +1072,11 @@ class CmdIMCTell(MuxCommand):
|
|||
return
|
||||
|
||||
from src.comms.imc2 import IMC2_CLIENT
|
||||
|
||||
|
||||
if not self.args or not '@' in self.lhs or not self.rhs:
|
||||
string = "Usage: imctell User@Mud = <msg>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
target, destination = self.lhs.split("@", 1)
|
||||
message = self.rhs.strip()
|
||||
data = {"target":target, "destination":destination}
|
||||
|
|
@ -1087,7 +1087,7 @@ class CmdIMCTell(MuxCommand):
|
|||
self.caller.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message))
|
||||
|
||||
|
||||
# RSS connection
|
||||
# RSS connection
|
||||
class CmdRSS2Chan(MuxCommand):
|
||||
"""
|
||||
@rss2chan - link evennia channel to an RSS feed
|
||||
|
|
@ -1097,20 +1097,20 @@ class CmdRSS2Chan(MuxCommand):
|
|||
|
||||
Switches:
|
||||
/disconnect - this will stop the feed and remove the connection to the channel.
|
||||
/remove - "
|
||||
/remove - "
|
||||
/list - show all rss->evennia mappings
|
||||
|
||||
Example:
|
||||
@rss2chan rsschan = http://code.google.com/feeds/p/evennia/updates/basic
|
||||
|
||||
This creates an RSS reader that connects to a given RSS feed url. Updates will be
|
||||
This creates an RSS reader that connects to a given RSS feed url. Updates will be
|
||||
echoed as a title and news link to the given channel. The rate of updating is set
|
||||
with the RSS_UPDATE_INTERVAL variable in settings (default is every 10 minutes).
|
||||
|
||||
with the RSS_UPDATE_INTERVAL variable in settings (default is every 10 minutes).
|
||||
|
||||
When disconnecting you need to supply both the channel and url again so as to identify
|
||||
the connection uniquely.
|
||||
the connection uniquely.
|
||||
"""
|
||||
|
||||
|
||||
key = "@rss2chan"
|
||||
locks = "cmd:serversetting(RSS_ENABLED) and pperm(Immortals)"
|
||||
help_category = "Comms"
|
||||
|
|
@ -1125,7 +1125,7 @@ class CmdRSS2Chan(MuxCommand):
|
|||
|
||||
if 'list' in self.switches:
|
||||
# show all connections
|
||||
connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='rss_')
|
||||
connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='rss_')
|
||||
if connections:
|
||||
cols = [["Evennia-channel"], ["RSS-url"]]
|
||||
for conn in connections:
|
||||
|
|
@ -1141,12 +1141,12 @@ class CmdRSS2Chan(MuxCommand):
|
|||
self.caller.msg(string)
|
||||
else:
|
||||
self.caller.msg("No connections found.")
|
||||
return
|
||||
return
|
||||
|
||||
if not self.args or not self.rhs:
|
||||
string = "Usage: @rss2chan[/switches] <evennia_channel> = <rss url>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
return
|
||||
channel = self.lhs
|
||||
url = self.rhs
|
||||
|
||||
|
|
@ -1160,8 +1160,8 @@ class CmdRSS2Chan(MuxCommand):
|
|||
self.caller.msg("RSS connection/reader could not be removed, does it exist?")
|
||||
else:
|
||||
self.caller.msg("RSS connection destroyed.")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
channel = find_channel(self.caller, channel)
|
||||
if not channel:
|
||||
return
|
||||
|
|
@ -1171,5 +1171,5 @@ class CmdRSS2Chan(MuxCommand):
|
|||
ok = rss.create_connection(channel, url, interval)
|
||||
if not ok:
|
||||
self.caller.msg("This RSS connection already exists.")
|
||||
return
|
||||
return
|
||||
self.caller.msg("Connection created. Starting RSS reader.")
|
||||
|
|
|
|||
|
|
@ -23,17 +23,17 @@ class CmdHome(MuxCommand):
|
|||
home
|
||||
|
||||
Usage:
|
||||
home
|
||||
home
|
||||
|
||||
Teleports the player to their home.
|
||||
"""
|
||||
|
||||
|
||||
key = "home"
|
||||
locks = "cmd:perm(home) or perm(Builders)"
|
||||
locks = "cmd:perm(home) or perm(Builders)"
|
||||
|
||||
def func(self):
|
||||
"Implement the command"
|
||||
caller = self.caller
|
||||
caller = self.caller
|
||||
home = caller.home
|
||||
if not home:
|
||||
caller.msg("You have no home set.")
|
||||
|
|
@ -47,7 +47,7 @@ class CmdLook(MuxCommand):
|
|||
|
||||
Usage:
|
||||
look
|
||||
look <obj>
|
||||
look <obj>
|
||||
look *<player>
|
||||
|
||||
Observes your location or objects in your vicinity.
|
||||
|
|
@ -59,27 +59,27 @@ class CmdLook(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"""
|
||||
Handle the looking.
|
||||
Handle the looking.
|
||||
"""
|
||||
caller = self.caller
|
||||
args = self.args
|
||||
args = self.args
|
||||
if args:
|
||||
# Use search to handle duplicate/nonexistant results.
|
||||
looking_at_obj = caller.search(args, use_nicks=True)
|
||||
if not looking_at_obj:
|
||||
return
|
||||
return
|
||||
else:
|
||||
looking_at_obj = caller.location
|
||||
if not looking_at_obj:
|
||||
caller.msg("You have no location to look at!")
|
||||
return
|
||||
|
||||
|
||||
if not hasattr(looking_at_obj, 'return_appearance'):
|
||||
# this is likely due to us having a player instead
|
||||
looking_at_obj = looking_at_obj.character
|
||||
looking_at_obj = looking_at_obj.character
|
||||
if not looking_at_obj.access(caller, "view"):
|
||||
caller.msg("Could not find '%s'." % args)
|
||||
return
|
||||
return
|
||||
# get object's appearance
|
||||
caller.msg(looking_at_obj.return_appearance(caller))
|
||||
# the object's at_desc() method.
|
||||
|
|
@ -93,16 +93,16 @@ class CmdPassword(MuxCommand):
|
|||
@password <old password> = <new password>
|
||||
|
||||
Changes your password. Make sure to pick a safe one.
|
||||
"""
|
||||
key = "@password"
|
||||
"""
|
||||
key = "@password"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"hook function."
|
||||
|
||||
caller = self.caller
|
||||
caller = self.caller
|
||||
if hasattr(caller, "player"):
|
||||
caller = caller.player
|
||||
caller = caller.player
|
||||
|
||||
if not self.rhs:
|
||||
caller.msg("Usage: @password <oldpass> = <newpass>")
|
||||
|
|
@ -131,16 +131,16 @@ class CmdNick(MuxCommand):
|
|||
nick[/switches] <nickname> = [<string>]
|
||||
alias ''
|
||||
|
||||
Switches:
|
||||
Switches:
|
||||
object - alias an object
|
||||
player - alias a player
|
||||
player - alias a player
|
||||
clearall - clear all your aliases
|
||||
list - show all defined aliases
|
||||
|
||||
list - show all defined aliases
|
||||
|
||||
If no switch is given, a command alias is created, used
|
||||
to replace strings before sending the command. Give an empty
|
||||
right-hand side to clear the nick
|
||||
|
||||
|
||||
Creates a personal nick for some in-game object or
|
||||
string. When you enter that string, it will be replaced
|
||||
with the alternate string. The switches dictate in what
|
||||
|
|
@ -148,15 +148,15 @@ class CmdNick(MuxCommand):
|
|||
is None, the alias (if it exists) will be cleared.
|
||||
Obs - no objects are actually changed with this command,
|
||||
if you want to change the inherent aliases of an object,
|
||||
use the @alias command instead.
|
||||
use the @alias command instead.
|
||||
"""
|
||||
key = "nick"
|
||||
aliases = ["nickname", "nicks", "@nick", "alias"]
|
||||
locks = "cmd:all()"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"Create the nickname"
|
||||
|
||||
|
||||
caller = self.caller
|
||||
switches = self.switches
|
||||
|
||||
|
|
@ -178,20 +178,20 @@ class CmdNick(MuxCommand):
|
|||
if 'clearall' in switches:
|
||||
nicks.delete()
|
||||
caller.msg("Cleared all aliases.")
|
||||
return
|
||||
return
|
||||
if not self.args or not self.lhs:
|
||||
caller.msg("Usage: nick[/switches] nickname = [realname]")
|
||||
return
|
||||
return
|
||||
nick = self.lhs
|
||||
real = self.rhs
|
||||
real = self.rhs
|
||||
|
||||
if real == nick:
|
||||
caller.msg("No point in setting nick same as the string to replace...")
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
# check so we have a suitable nick type
|
||||
if not any(True for switch in switches if switch in ("object", "player", "inputline")):
|
||||
switches = ["inputline"]
|
||||
switches = ["inputline"]
|
||||
string = ""
|
||||
for switch in switches:
|
||||
oldnick = Nick.objects.filter(db_obj=caller.dbobj, db_nick__iexact=nick, db_type__iexact=switch)
|
||||
|
|
@ -204,14 +204,14 @@ class CmdNick(MuxCommand):
|
|||
else:
|
||||
string += "\nNo nick '%s' found, so it could not be removed." % nick
|
||||
else:
|
||||
# creating new nick
|
||||
# creating new nick
|
||||
if oldnick:
|
||||
string += "\nNick %s changed from '%s' to '%s'." % (nick, oldnick[0].db_real, real)
|
||||
else:
|
||||
string += "\nNick set: '%s' = '%s'." % (nick, real)
|
||||
caller.nicks.add(nick, real, nick_type=switch)
|
||||
caller.nicks.add(nick, real, nick_type=switch)
|
||||
caller.msg(string)
|
||||
|
||||
|
||||
class CmdInventory(MuxCommand):
|
||||
"""
|
||||
inventory
|
||||
|
|
@ -219,9 +219,9 @@ class CmdInventory(MuxCommand):
|
|||
Usage:
|
||||
inventory
|
||||
inv
|
||||
|
||||
|
||||
Shows a player's inventory.
|
||||
"""
|
||||
"""
|
||||
key = "inventory"
|
||||
aliases = ["inv", "i"]
|
||||
locks = "cmd:all()"
|
||||
|
|
@ -235,7 +235,7 @@ class CmdInventory(MuxCommand):
|
|||
# format item list into nice collumns
|
||||
cols = [[],[]]
|
||||
for item in items:
|
||||
cols[0].append(item.name)
|
||||
cols[0].append(item.name)
|
||||
desc = item.db.desc
|
||||
if not desc:
|
||||
desc = ""
|
||||
|
|
@ -247,19 +247,19 @@ class CmdInventory(MuxCommand):
|
|||
string += "\n " + "{C%s{n - %s" % (row[0], row[1])
|
||||
self.caller.msg(string)
|
||||
|
||||
class CmdGet(MuxCommand):
|
||||
class CmdGet(MuxCommand):
|
||||
"""
|
||||
get
|
||||
|
||||
Usage:
|
||||
get <obj>
|
||||
|
||||
|
||||
Picks up an object from your location and puts it in
|
||||
your inventory.
|
||||
"""
|
||||
key = "get"
|
||||
aliases = "grab"
|
||||
locks = "cmd:all()"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"implements the command."
|
||||
|
|
@ -287,13 +287,13 @@ class CmdGet(MuxCommand):
|
|||
|
||||
obj.move_to(caller, quiet=True)
|
||||
caller.msg("You pick up %s." % obj.name)
|
||||
caller.location.msg_contents("%s picks up %s." %
|
||||
(caller.name,
|
||||
obj.name),
|
||||
caller.location.msg_contents("%s picks up %s." %
|
||||
(caller.name,
|
||||
obj.name),
|
||||
exclude=caller)
|
||||
# calling hook method
|
||||
obj.at_get(caller)
|
||||
|
||||
|
||||
|
||||
class CmdDrop(MuxCommand):
|
||||
"""
|
||||
|
|
@ -301,14 +301,14 @@ class CmdDrop(MuxCommand):
|
|||
|
||||
Usage:
|
||||
drop <obj>
|
||||
|
||||
Lets you drop an object from your inventory into the
|
||||
|
||||
Lets you drop an object from your inventory into the
|
||||
location you are currently in.
|
||||
"""
|
||||
|
||||
|
||||
key = "drop"
|
||||
locks = "cmd:all()"
|
||||
|
||||
|
||||
def func(self):
|
||||
"Implement command"
|
||||
|
||||
|
|
@ -318,17 +318,17 @@ class CmdDrop(MuxCommand):
|
|||
return
|
||||
|
||||
results = caller.search(self.args, ignore_errors=True)
|
||||
# we process the results ourselves since we want to sift out only
|
||||
# those in our inventory.
|
||||
# we process the results ourselves since we want to sift out only
|
||||
# those in our inventory.
|
||||
results = [obj for obj in results if obj in caller.contents]
|
||||
# now we send it into the handler.
|
||||
obj = AT_SEARCH_RESULT(caller, self.args, results, False)
|
||||
if not obj:
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
obj.move_to(caller.location, quiet=True)
|
||||
caller.msg("You drop %s." % (obj.name,))
|
||||
caller.location.msg_contents("%s drops %s." %
|
||||
caller.location.msg_contents("%s drops %s." %
|
||||
(caller.name, obj.name),
|
||||
exclude=caller)
|
||||
# Call the object script's at_drop() method.
|
||||
|
|
@ -340,33 +340,33 @@ class CmdQuit(MuxCommand):
|
|||
quit
|
||||
|
||||
Usage:
|
||||
@quit
|
||||
@quit
|
||||
|
||||
Gracefully disconnect from the game.
|
||||
"""
|
||||
key = "@quit"
|
||||
locks = "cmd:all()"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
"hook function"
|
||||
"hook function"
|
||||
for session in self.caller.sessions:
|
||||
session.msg("{RQuitting{n. Hope to see you soon again.")
|
||||
session.session_disconnect()
|
||||
|
||||
|
||||
class CmdWho(MuxCommand):
|
||||
"""
|
||||
who
|
||||
|
||||
Usage:
|
||||
who
|
||||
doing
|
||||
who
|
||||
doing
|
||||
|
||||
Shows who is currently online. Doing is an alias that limits info
|
||||
also for those with all permissions.
|
||||
"""
|
||||
|
||||
key = "who"
|
||||
aliases = "doing"
|
||||
aliases = "doing"
|
||||
locks = "cmd:all()"
|
||||
|
||||
def func(self):
|
||||
|
|
@ -386,7 +386,7 @@ class CmdWho(MuxCommand):
|
|||
table = [["Player Name"], ["On for"], ["Idle"], ["Room"], ["Cmds"], ["Host"]]
|
||||
else:
|
||||
table = [["Player Name"], ["On for"], ["Idle"]]
|
||||
|
||||
|
||||
for session in session_list:
|
||||
if not session.logged_in:
|
||||
continue
|
||||
|
|
@ -396,12 +396,12 @@ class CmdWho(MuxCommand):
|
|||
plr_pobject = session.get_character()
|
||||
if not plr_pobject:
|
||||
plr_pobject = session.get_player()
|
||||
show_session_data = False
|
||||
show_session_data = False
|
||||
table = [["Player Name"], ["On for"], ["Idle"]]
|
||||
if show_session_data:
|
||||
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[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])
|
||||
|
|
@ -421,7 +421,7 @@ class CmdWho(MuxCommand):
|
|||
else:
|
||||
string += "\n" + "".join(row)
|
||||
nplayers = (SESSIONS.player_count())
|
||||
if nplayers == 1:
|
||||
if nplayers == 1:
|
||||
string += '\nOne player logged in.'
|
||||
else:
|
||||
string += '\n%d players logged in.' % nplayers
|
||||
|
|
@ -434,14 +434,14 @@ class CmdSay(MuxCommand):
|
|||
|
||||
Usage:
|
||||
say <message>
|
||||
|
||||
Talk to those in your current location.
|
||||
|
||||
Talk to those in your current location.
|
||||
"""
|
||||
|
||||
|
||||
key = "say"
|
||||
aliases = ['"', "'"]
|
||||
locks = "cmd:all()"
|
||||
|
||||
|
||||
def func(self):
|
||||
"Run the say command"
|
||||
|
||||
|
|
@ -458,13 +458,13 @@ class CmdSay(MuxCommand):
|
|||
|
||||
# Feedback for the object doing the talking.
|
||||
caller.msg('You say, "%s{n"' % speech)
|
||||
|
||||
|
||||
# Build the string to emit to neighbors.
|
||||
emit_string = '{c%s{n says, "%s{n"' % (caller.name,
|
||||
emit_string = '{c%s{n says, "%s{n"' % (caller.name,
|
||||
speech)
|
||||
caller.location.msg_contents(emit_string,
|
||||
caller.location.msg_contents(emit_string,
|
||||
exclude=caller)
|
||||
|
||||
|
||||
|
||||
class CmdPose(MuxCommand):
|
||||
"""
|
||||
|
|
@ -477,13 +477,13 @@ class CmdPose(MuxCommand):
|
|||
Example:
|
||||
pose is standing by the wall, smiling.
|
||||
-> others will see:
|
||||
Tom is standing by the wall, smiling.
|
||||
Tom is standing by the wall, smiling.
|
||||
|
||||
Describe an script being taken. The pose text will
|
||||
automatically begin with your name.
|
||||
automatically begin with your name.
|
||||
"""
|
||||
key = "pose"
|
||||
aliases = [":", "emote"]
|
||||
aliases = [":", "emote"]
|
||||
locks = "cmd:all()"
|
||||
|
||||
def parse(self):
|
||||
|
|
@ -491,7 +491,7 @@ class CmdPose(MuxCommand):
|
|||
Custom parse the cases where the emote
|
||||
starts with some special letter, such
|
||||
as 's, at which we don't want to separate
|
||||
the caller's name and the emote with a
|
||||
the caller's name and the emote with a
|
||||
space.
|
||||
"""
|
||||
args = self.args
|
||||
|
|
@ -500,33 +500,33 @@ class CmdPose(MuxCommand):
|
|||
self.args = args
|
||||
|
||||
def func(self):
|
||||
"Hook function"
|
||||
"Hook function"
|
||||
if not self.args:
|
||||
msg = "Do what?"
|
||||
self.caller.msg(msg)
|
||||
else:
|
||||
msg = "%s%s" % (self.caller.name, self.args)
|
||||
self.caller.location.msg_contents(msg)
|
||||
|
||||
|
||||
class CmdEncoding(MuxCommand):
|
||||
"""
|
||||
encoding - set a custom text encoding
|
||||
|
||||
Usage:
|
||||
Usage:
|
||||
@encoding/switches [<encoding>]
|
||||
|
||||
Switches:
|
||||
clear - clear your custom encoding
|
||||
|
||||
|
||||
This sets the text encoding for communicating with Evennia. This is mostly an issue only if
|
||||
|
||||
This sets the text encoding for communicating with Evennia. This is mostly an issue only if
|
||||
you want to use non-ASCII characters (i.e. letters/symbols not found in English). If you see
|
||||
that your characters look strange (or you get encoding errors), you should use this command
|
||||
to set the server encoding to be the same used in your client program.
|
||||
|
||||
to set the server encoding to be the same used in your client program.
|
||||
|
||||
Common encodings are utf-8 (default), latin-1, ISO-8859-1 etc.
|
||||
|
||||
If you don't submit an encoding, the current encoding will be displayed instead.
|
||||
|
||||
If you don't submit an encoding, the current encoding will be displayed instead.
|
||||
"""
|
||||
|
||||
key = "@encoding"
|
||||
|
|
@ -539,7 +539,7 @@ class CmdEncoding(MuxCommand):
|
|||
"""
|
||||
caller = self.caller
|
||||
if hasattr(caller, 'player'):
|
||||
caller = caller.player
|
||||
caller = caller.player
|
||||
|
||||
if 'clear' in self.switches:
|
||||
# remove customization
|
||||
|
|
@ -551,22 +551,22 @@ class CmdEncoding(MuxCommand):
|
|||
del caller.db.encoding
|
||||
elif not self.args:
|
||||
# just list the encodings supported
|
||||
pencoding = caller.db.encoding
|
||||
pencoding = caller.db.encoding
|
||||
string = ""
|
||||
if pencoding:
|
||||
string += "Default encoding: {g%s{n (change with {w@encoding <encoding>{n)" % pencoding
|
||||
if pencoding:
|
||||
string += "Default encoding: {g%s{n (change with {w@encoding <encoding>{n)" % pencoding
|
||||
encodings = settings.ENCODINGS
|
||||
if encodings:
|
||||
string += "\nServer's alternative encodings (tested in this order):\n {g%s{n" % ", ".join(encodings)
|
||||
string += "\nServer's alternative encodings (tested in this order):\n {g%s{n" % ", ".join(encodings)
|
||||
if not string:
|
||||
string = "No encodings found."
|
||||
else:
|
||||
# change encoding
|
||||
else:
|
||||
# change encoding
|
||||
old_encoding = caller.db.encoding
|
||||
encoding = self.args
|
||||
caller.db.encoding = encoding
|
||||
string = "Your custom text encoding was changed from '%s' to '%s'." % (old_encoding, encoding)
|
||||
caller.msg(string.strip())
|
||||
caller.msg(string.strip())
|
||||
|
||||
class CmdAccess(MuxCommand):
|
||||
"""
|
||||
|
|
@ -575,7 +575,7 @@ class CmdAccess(MuxCommand):
|
|||
Usage:
|
||||
access
|
||||
|
||||
This command shows you the permission hierarchy and
|
||||
This command shows you the permission hierarchy and
|
||||
which permission groups you are a member of.
|
||||
"""
|
||||
key = "access"
|
||||
|
|
@ -587,8 +587,8 @@ class CmdAccess(MuxCommand):
|
|||
|
||||
caller = self.caller
|
||||
hierarchy_full = settings.PERMISSION_HIERARCHY
|
||||
string = "\n{wPermission Hierarchy{n (climbing):\n %s" % ", ".join(hierarchy_full)
|
||||
hierarchy = [p.lower() for p in hierarchy_full]
|
||||
string = "\n{wPermission Hierarchy{n (climbing):\n %s" % ", ".join(hierarchy_full)
|
||||
#hierarchy = [p.lower() for p in hierarchy_full]
|
||||
|
||||
if self.caller.player.is_superuser:
|
||||
cperms = "<Superuser>"
|
||||
|
|
@ -603,7 +603,7 @@ class CmdAccess(MuxCommand):
|
|||
string += "\nPlayer {c%s{n: %s" % (caller.player.key, pperms)
|
||||
caller.msg(string)
|
||||
|
||||
# OOC commands
|
||||
# OOC commands
|
||||
|
||||
class CmdOOCLook(CmdLook):
|
||||
"""
|
||||
|
|
@ -614,8 +614,8 @@ class CmdOOCLook(CmdLook):
|
|||
|
||||
This is an OOC version of the look command. Since a
|
||||
Player doesn't have an in-game existence, there is no
|
||||
concept of location or "self". If we are controlling
|
||||
a character, pass control over to normal look.
|
||||
concept of location or "self". If we are controlling
|
||||
a character, pass control over to normal look.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -631,7 +631,7 @@ class CmdOOCLook(CmdLook):
|
|||
if utils.inherits_from(self.caller, "src.objects.objects.Object"):
|
||||
# An object of some type is calling. Convert to player.
|
||||
#print self.caller, self.caller.__class__
|
||||
self.character = self.caller
|
||||
self.character = self.caller
|
||||
if hasattr(self.caller, "player"):
|
||||
self.caller = self.caller.player
|
||||
|
||||
|
|
@ -642,20 +642,20 @@ class CmdOOCLook(CmdLook):
|
|||
else:
|
||||
self.caller = self.character # we have to put this back for normal look to work.
|
||||
super(CmdOOCLook, self).func()
|
||||
|
||||
|
||||
class CmdIC(MuxCommand):
|
||||
"""
|
||||
Switch control to an object
|
||||
|
||||
|
||||
Usage:
|
||||
@ic <character>
|
||||
|
||||
Go in-character (IC) as a given Character.
|
||||
|
||||
Go in-character (IC) as a given Character.
|
||||
|
||||
This will attempt to "become" a different object assuming you have
|
||||
the right to do so. You cannot become an object that is already
|
||||
controlled by another player. In principle <character> can be
|
||||
any in-game object as long as you have access right to puppet it.
|
||||
any in-game object as long as you have access right to puppet it.
|
||||
"""
|
||||
|
||||
key = "@ic"
|
||||
|
|
@ -671,7 +671,7 @@ class CmdIC(MuxCommand):
|
|||
if utils.inherits_from(caller, "src.objects.objects.Object"):
|
||||
caller = caller.player
|
||||
|
||||
new_character = None
|
||||
new_character = None
|
||||
if not self.args:
|
||||
new_character = caller.db.last_puppet
|
||||
if not new_character:
|
||||
|
|
@ -682,19 +682,19 @@ class CmdIC(MuxCommand):
|
|||
new_character = caller.search(self.args, global_search=True)
|
||||
if not new_character:
|
||||
# the search method handles error messages etc.
|
||||
return
|
||||
return
|
||||
if new_character.player:
|
||||
if new_character.player == caller:
|
||||
caller.msg("{RYou already are {c%s{n." % new_character.name)
|
||||
else:
|
||||
caller.msg("{c%s{r is already acted by another player.{n" % new_character.name)
|
||||
return
|
||||
caller.msg("{c%s{r is already acted by another player.{n" % new_character.name)
|
||||
return
|
||||
if not new_character.access(caller, "puppet"):
|
||||
caller.msg("{rYou may not become %s.{n" % new_character.name)
|
||||
return
|
||||
old_char = None
|
||||
old_char = None
|
||||
if caller.character:
|
||||
# save the old character. We only assign this to last_puppet if swap is successful.
|
||||
# save the old character. We only assign this to last_puppet if swap is successful.
|
||||
old_char = caller.character
|
||||
if caller.swap_character(new_character):
|
||||
new_character.msg("\n{gYou become {c%s{n.\n" % new_character.name)
|
||||
|
|
@ -704,7 +704,7 @@ class CmdIC(MuxCommand):
|
|||
loc = new_character.db.prelogout_location
|
||||
if not loc: # still no location; use home
|
||||
loc = new_character.home
|
||||
new_character.location = loc
|
||||
new_character.location = loc
|
||||
if new_character.location:
|
||||
new_character.location.msg_contents("%s has entered the game." % new_character.key, exclude=[new_character])
|
||||
new_character.location.at_object_receive(new_character, new_character.location)
|
||||
|
|
@ -715,10 +715,10 @@ class CmdIC(MuxCommand):
|
|||
class CmdOOC(MuxCommand):
|
||||
"""
|
||||
@ooc - go ooc
|
||||
|
||||
|
||||
Usage:
|
||||
@ooc
|
||||
|
||||
|
||||
Go out-of-character (OOC).
|
||||
|
||||
This will leave your current character and put you in a incorporeal OOC state.
|
||||
|
|
@ -730,8 +730,8 @@ class CmdOOC(MuxCommand):
|
|||
help_category = "General"
|
||||
|
||||
def func(self):
|
||||
"Implement function"
|
||||
|
||||
"Implement function"
|
||||
|
||||
caller = self.caller
|
||||
|
||||
if utils.inherits_from(caller, "src.objects.objects.Object"):
|
||||
|
|
@ -740,18 +740,18 @@ class CmdOOC(MuxCommand):
|
|||
if not caller.character:
|
||||
string = "You are already OOC."
|
||||
caller.msg(string)
|
||||
return
|
||||
return
|
||||
|
||||
caller.db.last_puppet = caller.character
|
||||
# save location as if we were disconnecting from the game entirely.
|
||||
if caller.character.location:
|
||||
caller.character.location.msg_contents("%s has left the game." % caller.character.key, exclude=[caller.character])
|
||||
caller.character.db.prelogout_location = caller.character.location
|
||||
caller.character.location = None
|
||||
|
||||
# disconnect
|
||||
caller.character.location = None
|
||||
|
||||
# disconnect
|
||||
caller.character.player = None
|
||||
caller.character = None
|
||||
caller.character = None
|
||||
|
||||
caller.msg("\n{GYou go OOC.{n\n")
|
||||
caller.execute_cmd("look")
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ command-help is all auto-loaded and searched from the current command
|
|||
set. The normal, database-tied help system is used for collaborative
|
||||
creation of other help topics such as RP help or game-world aides.
|
||||
"""
|
||||
|
||||
|
||||
from src.utils.utils import fill, dedent
|
||||
from src.commands.command import Command
|
||||
from src.help.models import HelpEntry
|
||||
from src.utils import create
|
||||
from src.utils import create
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
# limit symbol import for API
|
||||
|
|
@ -18,43 +18,43 @@ __all__ = ("CmdHelp", "CmdSetHelp")
|
|||
|
||||
LIST_ARGS = ("list", "all")
|
||||
SEP = "{C" + "-"*78 + "{n"
|
||||
|
||||
|
||||
def format_help_entry(title, help_text, aliases=None, suggested=None):
|
||||
"""
|
||||
This visually formats the help entry.
|
||||
"""
|
||||
"""
|
||||
string = SEP + "\n"
|
||||
if title:
|
||||
string += "{CHelp topic for {w%s{n" % (title.capitalize())
|
||||
if title:
|
||||
string += "{CHelp topic for {w%s{n" % (title.capitalize())
|
||||
if aliases:
|
||||
string += " {C(aliases: {w%s{n{C){n" % (", ".join(aliases))
|
||||
if help_text:
|
||||
string += "\n%s" % dedent(help_text.rstrip())
|
||||
if suggested:
|
||||
string += "\n\n{CSuggested:{n "
|
||||
string += "{w%s{n" % fill(", ".join(suggested))
|
||||
string += "{w%s{n" % fill(", ".join(suggested))
|
||||
string.strip()
|
||||
string += "\n" + SEP
|
||||
return string
|
||||
string += "\n" + SEP
|
||||
return string
|
||||
|
||||
def format_help_list(hdict_cmds, hdict_db):
|
||||
"""
|
||||
Output a category-ordered list. The input are the
|
||||
pre-loaded help files for commands and database-helpfiles
|
||||
Output a category-ordered list. The input are the
|
||||
pre-loaded help files for commands and database-helpfiles
|
||||
resectively.
|
||||
"""
|
||||
"""
|
||||
string = ""
|
||||
if hdict_cmds and hdict_cmds.values():
|
||||
string += "\n" + SEP + "\n {CCommand help entries{n\n" + SEP
|
||||
for category in sorted(hdict_cmds.keys()):
|
||||
string += "\n {w%s{n:\n" % (str(category).capitalize())
|
||||
string += "\n {w%s{n:\n" % (str(category).capitalize())
|
||||
string += "{G" + fill(", ".join(sorted(hdict_cmds[category]))) + "{n"
|
||||
if hdict_db and hdict_db.values():
|
||||
string += "\n\n" + SEP + "\n\r {COther help entries{n\n" + SEP
|
||||
string += "\n\n" + SEP + "\n\r {COther help entries{n\n" + SEP
|
||||
for category in sorted(hdict_db.keys()):
|
||||
string += "\n\r {w%s{n:\n" % (str(category).capitalize())
|
||||
string += "{G" + fill(", ".join(sorted([str(topic) for topic in hdict_db[category]]))) + "{n"
|
||||
return string
|
||||
string += "\n\r {w%s{n:\n" % (str(category).capitalize())
|
||||
string += "{G" + fill(", ".join(sorted([str(topic) for topic in hdict_db[category]]))) + "{n"
|
||||
return string
|
||||
|
||||
class CmdHelp(Command):
|
||||
"""
|
||||
|
|
@ -66,15 +66,15 @@ class CmdHelp(Command):
|
|||
help all
|
||||
|
||||
This will search for help on commands and other
|
||||
topics related to the game.
|
||||
topics related to the game.
|
||||
"""
|
||||
key = "help"
|
||||
locks = "cmd:all()"
|
||||
|
||||
# this is a special cmdhandler flag that makes the cmdhandler also pack
|
||||
# the current cmdset with the call to self.func().
|
||||
return_cmdset = True
|
||||
|
||||
# the current cmdset with the call to self.func().
|
||||
return_cmdset = True
|
||||
|
||||
def parse(self):
|
||||
"""
|
||||
input is a string containing the command or topic to match.
|
||||
|
|
@ -85,7 +85,7 @@ class CmdHelp(Command):
|
|||
def func(self):
|
||||
"""
|
||||
Run the dynamic help entry creator.
|
||||
"""
|
||||
"""
|
||||
query, cmdset = self.args, self.cmdset
|
||||
caller = self.caller
|
||||
|
||||
|
|
@ -95,37 +95,37 @@ class CmdHelp(Command):
|
|||
# removing doublets in cmdset, caused by cmdhandler
|
||||
# having to allow doublet commands to manage exits etc.
|
||||
cmdset.make_unique(caller)
|
||||
|
||||
|
||||
# Listing all help entries
|
||||
|
||||
|
||||
if query in LIST_ARGS:
|
||||
# we want to list all available help entries, grouped by category.
|
||||
hdict_cmd = {}
|
||||
for cmd in (cmd for cmd in cmdset if cmd.auto_help and not cmd.is_exit
|
||||
for cmd in (cmd for cmd in cmdset if cmd.auto_help and not cmd.is_exit
|
||||
and not cmd.key.startswith('__') and cmd.access(caller)):
|
||||
try:
|
||||
hdict_cmd[cmd.help_category].append(cmd.key)
|
||||
except KeyError:
|
||||
hdict_cmd[cmd.help_category] = [cmd.key]
|
||||
hdict_cmd[cmd.help_category] = [cmd.key]
|
||||
hdict_db = {}
|
||||
for topic in (topic for topic in HelpEntry.objects.get_all_topics()
|
||||
if topic.access(caller, 'view', default=True)):
|
||||
try:
|
||||
hdict_db[topic.help_category].append(topic.key)
|
||||
hdict_db[topic.help_category].append(topic.key)
|
||||
except KeyError:
|
||||
hdict_db[topic.help_category] = [topic.key]
|
||||
help_entry = format_help_list(hdict_cmd, hdict_db)
|
||||
caller.msg(help_entry)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
# Look for a particular help entry
|
||||
|
||||
# Cmd auto-help dynamic entries
|
||||
|
||||
# Cmd auto-help dynamic entries
|
||||
cmdmatches = [cmd for cmd in cmdset if query in cmd and cmd.auto_help and cmd.access(caller)]
|
||||
if len(cmdmatches) > 1:
|
||||
# multiple matches. Try to limit it down to exact match
|
||||
cmdmatches = [cmd for cmd in cmdmatches if cmd == query] or cmdmatches
|
||||
|
||||
|
||||
# Help-database static entries
|
||||
dbmatches = [topic for topic in
|
||||
HelpEntry.objects.find_topicmatch(query, exact=False)
|
||||
|
|
@ -135,7 +135,7 @@ class CmdHelp(Command):
|
|||
dbmatches = [topic for topic in HelpEntry.objects.find_topicmatch(query, exact=True)
|
||||
if topic.access(caller, 'view', default=True)] or dbmatches
|
||||
|
||||
# Handle result
|
||||
# Handle result
|
||||
if (not cmdmatches) and (not dbmatches):
|
||||
# no normal match. Check if this is a category match instead
|
||||
categ_cmdmatches = [cmd.key for cmd in cmdset if query == cmd.help_category and cmd.access(caller)]
|
||||
|
|
@ -143,13 +143,13 @@ class CmdHelp(Command):
|
|||
if topic.access(caller, 'view', default=True)]
|
||||
cmddict = None
|
||||
dbdict = None
|
||||
|
||||
|
||||
if categ_cmdmatches:
|
||||
cmddict = {query:categ_cmdmatches}
|
||||
if categ_dbmatches:
|
||||
dbdict = {query:categ_dbmatches}
|
||||
if categ_dbmatches:
|
||||
dbdict = {query:categ_dbmatches}
|
||||
if cmddict or dbdict:
|
||||
help_entry = format_help_list(cmddict, dbdict)
|
||||
help_entry = format_help_list(cmddict, dbdict)
|
||||
else:
|
||||
help_entry = "No help entry found for '%s'" % self.original_args
|
||||
|
||||
|
|
@ -187,33 +187,33 @@ class CmdSetHelp(MuxCommand):
|
|||
add - add or replace a new topic with text.
|
||||
append - add text to the end of topic with a newline between.
|
||||
merge - As append, but don't add a newline between the old
|
||||
text and the appended text.
|
||||
text and the appended text.
|
||||
delete - remove help topic.
|
||||
force - (used with add) create help topic also if the topic
|
||||
already exists.
|
||||
already exists.
|
||||
|
||||
Examples:
|
||||
@sethelp/add throw = This throws something at ...
|
||||
@sethelp/append pickpocketing,Thievery,is_thief, is_staff) = This steals ...
|
||||
@sethelp/append pickpocketing, ,is_thief, is_staff) = This steals ...
|
||||
|
||||
|
||||
"""
|
||||
key = "@help"
|
||||
aliases = "@sethelp"
|
||||
locks = "cmd:perm(PlayerHelpers)"
|
||||
help_category = "Building"
|
||||
|
||||
|
||||
def func(self):
|
||||
"Implement the function"
|
||||
|
||||
caller = self.caller
|
||||
|
||||
caller = self.caller
|
||||
switches = self.switches
|
||||
lhslist = self.lhslist
|
||||
rhs = self.rhs
|
||||
|
||||
if not self.args:
|
||||
caller.msg("Usage: @sethelp/[add|del|append|merge] <topic>[,category[,locks,..] = <text>]")
|
||||
return
|
||||
return
|
||||
|
||||
topicstr = ""
|
||||
category = ""
|
||||
|
|
@ -226,12 +226,12 @@ class CmdSetHelp(MuxCommand):
|
|||
pass
|
||||
if not topicstr:
|
||||
caller.msg("You have to define a topic!")
|
||||
return
|
||||
return
|
||||
string = ""
|
||||
#print topicstr, category, lockstring
|
||||
|
||||
if switches and switches[0] in ('append', 'app','merge'):
|
||||
# add text to the end of a help topic
|
||||
# add text to the end of a help topic
|
||||
# find the topic to append to
|
||||
old_entry = HelpEntry.objects.filter(db_key__iexact=topicstr)
|
||||
if not old_entry:
|
||||
|
|
@ -242,14 +242,14 @@ class CmdSetHelp(MuxCommand):
|
|||
if switches[0] == 'merge':
|
||||
old_entry.entrytext = "%s %s" % (entrytext, self.rhs)
|
||||
string = "Added the new text right after the old one (merge)."
|
||||
else:
|
||||
else:
|
||||
old_entry.entrytext = "%s\n\n%s" % (entrytext, self.rhs)
|
||||
string = "Added the new text as a new paragraph after the old one (append)"
|
||||
old_entry.save()
|
||||
|
||||
elif switches and switches[0] in ('delete','del'):
|
||||
#delete a help entry
|
||||
old_entry = HelpEntry.objects.filter(db_key__iexact=topicstr)
|
||||
old_entry = HelpEntry.objects.filter(db_key__iexact=topicstr)
|
||||
if not old_entry:
|
||||
string = "Could not find topic '%s'." % topicstr
|
||||
else:
|
||||
|
|
@ -257,14 +257,14 @@ class CmdSetHelp(MuxCommand):
|
|||
string = "Deleted the help entry '%s'." % topicstr
|
||||
|
||||
else:
|
||||
# add a new help entry.
|
||||
# add a new help entry.
|
||||
force_create = ('for' in switches) or ('force' in switches)
|
||||
old_entry = None
|
||||
old_entry = None
|
||||
try:
|
||||
old_entry = HelpEntry.objects.get(key=topicstr)
|
||||
except Exception:
|
||||
pass
|
||||
if old_entry:
|
||||
if old_entry:
|
||||
if force_create:
|
||||
old_entry.key = topicstr
|
||||
old_entry.entrytext = self.rhs
|
||||
|
|
@ -277,13 +277,13 @@ class CmdSetHelp(MuxCommand):
|
|||
string = "Topic '%s' already exists. Use /force to overwrite it." % topicstr
|
||||
else:
|
||||
# no old entry. Create a new one.
|
||||
new_entry = create.create_help_entry(topicstr,
|
||||
new_entry = create.create_help_entry(topicstr,
|
||||
rhs, category, lockstring)
|
||||
|
||||
if new_entry:
|
||||
string = "Topic '%s' was successfully created." % topicstr
|
||||
else:
|
||||
string = "Error when creating topic '%s'! Maybe it already exists?" % topicstr
|
||||
string = "Error when creating topic '%s'! Maybe it already exists?" % topicstr
|
||||
|
||||
# give feedback
|
||||
caller.msg(string)
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@ System commands
|
|||
These are the default commands called by the system commandhandler
|
||||
when various exceptions occur. If one of these commands are not
|
||||
implemented and part of the current cmdset, the engine falls back
|
||||
to a default solution instead.
|
||||
to a default solution instead.
|
||||
|
||||
Some system commands are shown in this module
|
||||
as a REFERENCE only (they are not all added to Evennia's
|
||||
default cmdset since they don't currently do anything differently from the
|
||||
as a REFERENCE only (they are not all added to Evennia's
|
||||
default cmdset since they don't currently do anything differently from the
|
||||
default backup systems hard-wired in the engine).
|
||||
|
||||
Overloading these commands in a cmdset can be used to create
|
||||
interesting effects. An example is using the NoMatch system command
|
||||
to implement a line-editor where you don't have to start each
|
||||
line with a command (if there is no match to a known command,
|
||||
the line is just added to the editor buffer).
|
||||
the line is just added to the editor buffer).
|
||||
"""
|
||||
|
||||
from src.comms.models import Channel
|
||||
|
|
@ -27,7 +27,7 @@ from src.commands.cmdhandler import CMD_NOINPUT
|
|||
from src.commands.cmdhandler import CMD_NOMATCH
|
||||
from src.commands.cmdhandler import CMD_MULTIMATCH
|
||||
from src.commands.cmdhandler import CMD_CHANNEL
|
||||
|
||||
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
# Command called when there is no input at line
|
||||
|
|
@ -59,7 +59,7 @@ class SystemNoMatch(MuxCommand):
|
|||
def func(self):
|
||||
"""
|
||||
This is given the failed raw string as input.
|
||||
"""
|
||||
"""
|
||||
self.caller.msg("Huh?")
|
||||
|
||||
#
|
||||
|
|
@ -69,13 +69,13 @@ class SystemMultimatch(MuxCommand):
|
|||
"""
|
||||
Multiple command matches.
|
||||
|
||||
The cmdhandler adds a special attribute 'matches' to this
|
||||
system command.
|
||||
The cmdhandler adds a special attribute 'matches' to this
|
||||
system command.
|
||||
|
||||
matches = [(candidate, cmd) , (candidate, cmd), ...],
|
||||
|
||||
|
||||
where candidate is an instance of src.commands.cmdparser.CommandCandidate
|
||||
and cmd is an an instantiated Command object matching the candidate.
|
||||
and cmd is an an instantiated Command object matching the candidate.
|
||||
"""
|
||||
key = CMD_MULTIMATCH
|
||||
locks = "cmd:all()"
|
||||
|
|
@ -84,21 +84,21 @@ class SystemMultimatch(MuxCommand):
|
|||
"""
|
||||
Format multiple command matches to a useful error.
|
||||
|
||||
This is copied directly from the default method in
|
||||
src.commands.cmdhandler.
|
||||
This is copied directly from the default method in
|
||||
src.commands.cmdhandler.
|
||||
|
||||
"""
|
||||
string = "There where multiple matches:"
|
||||
for num, match in enumerate(matches):
|
||||
for num, match in enumerate(matches):
|
||||
# each match is a tuple (candidate, cmd)
|
||||
candidate, cmd = match
|
||||
candidate, cmd = match
|
||||
|
||||
is_channel = hasattr(cmd, "is_channel") and cmd.is_channel
|
||||
if is_channel:
|
||||
is_channel = " (channel)"
|
||||
else:
|
||||
is_channel = ""
|
||||
is_exit = hasattr(cmd, "is_exit") and cmd.is_exit
|
||||
is_exit = hasattr(cmd, "is_exit") and cmd.is_exit
|
||||
if is_exit and cmd.destination:
|
||||
is_exit = " (exit to %s)" % cmd.destination
|
||||
else:
|
||||
|
|
@ -115,7 +115,7 @@ class SystemMultimatch(MuxCommand):
|
|||
id2 = ""
|
||||
string += "\n %s%s%s%s%s" % (id1, candidate.cmdname, id2, is_channel, is_exit)
|
||||
return string
|
||||
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
argument to cmd is a comma-separated string of
|
||||
|
|
@ -126,37 +126,37 @@ class SystemMultimatch(MuxCommand):
|
|||
|
||||
# Command called when the command given at the command line
|
||||
# was identified as a channel name, like there existing a
|
||||
# channel named 'ooc' and the user wrote
|
||||
# > ooc Hello!
|
||||
# channel named 'ooc' and the user wrote
|
||||
# > ooc Hello!
|
||||
|
||||
class SystemSendToChannel(MuxCommand):
|
||||
"""
|
||||
This is a special command that the cmdhandler calls
|
||||
when it detects that the command given matches
|
||||
an existing Channel object key (or alias).
|
||||
an existing Channel object key (or alias).
|
||||
"""
|
||||
|
||||
key = CMD_CHANNEL
|
||||
locks = "cmd:all()"
|
||||
|
||||
def parse(self):
|
||||
channelname, msg = self.args.split(':', 1)
|
||||
channelname, msg = self.args.split(':', 1)
|
||||
self.args = channelname.strip(), msg.strip()
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Create a new message and send it to channel, using
|
||||
the already formatted input.
|
||||
"""
|
||||
caller = self.caller
|
||||
"""
|
||||
caller = self.caller
|
||||
channelkey, msg = self.args
|
||||
if not msg:
|
||||
caller.msg("Say what?")
|
||||
return
|
||||
return
|
||||
channel = Channel.objects.get_channel(channelkey)
|
||||
if not channel:
|
||||
caller.msg("Channel '%s' not found." % channelkey)
|
||||
return
|
||||
return
|
||||
if not channel.has_connection(caller):
|
||||
string = "You are not connected to channel '%s'."
|
||||
caller.msg(string % channelkey)
|
||||
|
|
@ -165,6 +165,6 @@ class SystemSendToChannel(MuxCommand):
|
|||
string = "You are not permitted to send to channel '%s'."
|
||||
caller.msg(string % channelkey)
|
||||
return
|
||||
msg = "[%s] %s: %s" % (channel.key, caller.name, msg)
|
||||
msg = "[%s] %s: %s" % (channel.key, caller.name, msg)
|
||||
msgobj = create.create_message(caller, msg, channels=[channel])
|
||||
channel.msg(msgobj)
|
||||
|
|
|
|||
|
|
@ -8,14 +8,12 @@ import traceback
|
|||
import os, datetime, time
|
||||
import django, twisted
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
from src.scripts.models import ScriptDB
|
||||
from src.objects.models import ObjectDB
|
||||
from src.players.models import PlayerDB
|
||||
from src.server.models import ServerConfig
|
||||
from src.utils import create, logger, utils, gametime
|
||||
from src.utils import logger, utils, gametime
|
||||
from src.commands.default.muxcommand import MuxCommand
|
||||
|
||||
# limit symbol import for API
|
||||
|
|
@ -40,7 +38,7 @@ class CmdReload(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"""
|
||||
Reload the system.
|
||||
Reload the system.
|
||||
"""
|
||||
SESSIONS.announce_all(" Server restarting ...")
|
||||
SESSIONS.server.shutdown(mode='reload')
|
||||
|
|
@ -64,7 +62,7 @@ class CmdReset(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"""
|
||||
Reload the system.
|
||||
Reload the system.
|
||||
"""
|
||||
SESSIONS.announce_all(" Server restarting ...")
|
||||
SESSIONS.server.shutdown(mode='reset')
|
||||
|
|
@ -101,7 +99,7 @@ class CmdShutdown(MuxCommand):
|
|||
|
||||
class CmdPy(MuxCommand):
|
||||
"""
|
||||
Execute a snippet of python code
|
||||
Execute a snippet of python code
|
||||
|
||||
Usage:
|
||||
@py <cmd>
|
||||
|
|
@ -110,10 +108,10 @@ class CmdPy(MuxCommand):
|
|||
available for convenience in order to offer access to the system
|
||||
(you can import more at execution time).
|
||||
|
||||
Available variables in @py environment:
|
||||
Available variables in @py environment:
|
||||
self, me : caller
|
||||
here : caller.location
|
||||
ev : the evennia API
|
||||
ev : the evennia API
|
||||
inherits_from(obj, parent) : check object inheritance
|
||||
|
||||
{rNote: In the wrong hands this command is a severe security risk.
|
||||
|
|
@ -160,7 +158,7 @@ class CmdPy(MuxCommand):
|
|||
caller.msg(ret)
|
||||
|
||||
# helper function. Kept outside so it can be imported and run
|
||||
# by other commands.
|
||||
# by other commands.
|
||||
|
||||
def format_script_list(scripts):
|
||||
"Takes a list of scripts and formats the output."
|
||||
|
|
@ -216,7 +214,7 @@ class CmdScripts(MuxCommand):
|
|||
|
||||
Usage:
|
||||
@scripts[/switches] [<obj or scriptid>]
|
||||
|
||||
|
||||
Switches:
|
||||
stop - stops an existing script
|
||||
kill - kills a script - without running its cleanup hooks
|
||||
|
|
@ -232,7 +230,7 @@ class CmdScripts(MuxCommand):
|
|||
aliases = "@listscripts"
|
||||
locks = "cmd:perm(listscripts) or perm(Wizards)"
|
||||
help_category = "System"
|
||||
|
||||
|
||||
def func(self):
|
||||
"implement method"
|
||||
|
||||
|
|
@ -247,7 +245,7 @@ class CmdScripts(MuxCommand):
|
|||
if not scripts:
|
||||
# try to find an object instead.
|
||||
objects = ObjectDB.objects.object_search(args, caller=caller, global_search=True)
|
||||
if objects:
|
||||
if objects:
|
||||
scripts = []
|
||||
for obj in objects:
|
||||
# get all scripts on the object(s)
|
||||
|
|
@ -267,7 +265,7 @@ class CmdScripts(MuxCommand):
|
|||
string = "No scripts/objects matching '%s'. " % args
|
||||
string += "Be more specific."
|
||||
elif len(scripts) == 1:
|
||||
# we have a unique match!
|
||||
# we have a unique match!
|
||||
if 'kill' in self.switches:
|
||||
string = "Killing script '%s'" % scripts[0].key
|
||||
scripts[0].stop(kill=True)
|
||||
|
|
@ -300,8 +298,8 @@ class CmdObjects(MuxCommand):
|
|||
Usage:
|
||||
@objects [<nr>]
|
||||
|
||||
Gives statictics on objects in database as well as
|
||||
a list of <nr> latest objects in database. If not
|
||||
Gives statictics on objects in database as well as
|
||||
a list of <nr> latest objects in database. If not
|
||||
given, <nr> defaults to 10.
|
||||
"""
|
||||
key = "@objects"
|
||||
|
|
@ -379,7 +377,7 @@ class CmdService(MuxCommand):
|
|||
list - shows all available services (default)
|
||||
start - activates a service
|
||||
stop - stops a service
|
||||
|
||||
|
||||
Service management system. Allows for the listing,
|
||||
starting, and stopping of services. If no switches
|
||||
are given, services will be listed.
|
||||
|
|
@ -487,8 +485,8 @@ class CmdTime(MuxCommand):
|
|||
@time
|
||||
|
||||
Usage:
|
||||
@time
|
||||
|
||||
@time
|
||||
|
||||
Server local time.
|
||||
"""
|
||||
key = "@time"
|
||||
|
|
@ -498,12 +496,12 @@ class CmdTime(MuxCommand):
|
|||
|
||||
def func(self):
|
||||
"Show times."
|
||||
|
||||
|
||||
table = [["Current server uptime:",
|
||||
"Total server running time:",
|
||||
"Total in-game time (realtime x %g):" % (gametime.TIMEFACTOR),
|
||||
"Server time stamp:"
|
||||
],
|
||||
],
|
||||
[utils.time_format(time.time() - SESSIONS.server.start_time, 3),
|
||||
utils.time_format(gametime.runtime(format=False), 2),
|
||||
utils.time_format(gametime.gametime(format=False), 2),
|
||||
|
|
@ -523,13 +521,13 @@ class CmdTime(MuxCommand):
|
|||
self.caller.msg(string)
|
||||
|
||||
class CmdServerLoad(MuxCommand):
|
||||
"""
|
||||
"""
|
||||
server load statistics
|
||||
|
||||
Usage:
|
||||
@serverload
|
||||
|
||||
Show server load statistics in a table.
|
||||
Show server load statistics in a table.
|
||||
"""
|
||||
key = "@serverload"
|
||||
locks = "cmd:perm(list) or perm(Immortals)"
|
||||
|
|
@ -607,9 +605,9 @@ class CmdServerLoad(MuxCommand):
|
|||
# class CmdPs(MuxCommand):
|
||||
# """
|
||||
# list processes
|
||||
|
||||
|
||||
# Usage
|
||||
# @ps
|
||||
# @ps
|
||||
|
||||
# Shows the process/event table.
|
||||
# """
|
||||
|
|
|
|||
|
|
@ -182,13 +182,14 @@ its and @/./+/-/_ only.") # this echoes the restrictions made by django's auth m
|
|||
typeclass = settings.BASE_CHARACTER_TYPECLASS
|
||||
permissions = settings.PERMISSION_PLAYER_DEFAULT
|
||||
|
||||
new_character = create.create_player(playername, email, password,
|
||||
permissions=permissions,
|
||||
character_typeclass=typeclass,
|
||||
character_location=default_home,
|
||||
character_home=default_home)
|
||||
if not new_character:
|
||||
session.msg("There was an error creating the default Character/Player. This error was logged. Contact an admin.")
|
||||
try:
|
||||
new_character = create.create_player(playername, email, password,
|
||||
permissions=permissions,
|
||||
character_typeclass=typeclass,
|
||||
character_location=default_home,
|
||||
character_home=default_home)
|
||||
except Exception, e:
|
||||
session.msg("There was an error creating the default Character/Player:\n%s\n If this problem persists, contact an admin.")
|
||||
return
|
||||
new_player = new_character.player
|
||||
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ class Object(TypeClass):
|
|||
|
||||
|
||||
"""
|
||||
self.dbobj.swap_typeclass(new_typeclass, clean_attributes=clean_attributes, no_default=no_default)
|
||||
return self.dbobj.swap_typeclass(new_typeclass, clean_attributes=clean_attributes, no_default=no_default)
|
||||
|
||||
def access(self, accessing_obj, access_type='read', default=False):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -58,9 +58,6 @@ def create_objects():
|
|||
create_character=True,
|
||||
character_typeclass=character_typeclass)
|
||||
|
||||
if not god_character:
|
||||
raise Exception(_("#1 could not be created. Check the Player/Character typeclass for bugs."))
|
||||
|
||||
god_character.id = 1
|
||||
god_character.db.desc = _('This is User #1.')
|
||||
god_character.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all();puppet:false()")
|
||||
|
|
@ -164,7 +161,11 @@ def create_admin_media_links():
|
|||
on system.
|
||||
"""
|
||||
import django, os
|
||||
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
|
||||
|
||||
if django.get_version() < 1.4:
|
||||
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'media')
|
||||
else:
|
||||
dpath = os.path.join(django.__path__[0], 'contrib', 'admin', 'static', 'admin')
|
||||
apath = os.path.join(settings.ADMIN_MEDIA_ROOT)
|
||||
if os.path.isdir(apath):
|
||||
print _(" ADMIN_MEDIA_ROOT already exists. Ignored.")
|
||||
|
|
@ -177,8 +178,8 @@ def create_admin_media_links():
|
|||
try:
|
||||
os.symlink(dpath, apath)
|
||||
print _(" Admin-media symlinked to ADMIN_MEDIA_ROOT.")
|
||||
except OSError:
|
||||
print _(" There was an error symlinking Admin-media to ADMIN_MEDIA_ROOT. If you see issues, link manually.")
|
||||
except OSError, e:
|
||||
print _(" There was an error symlinking Admin-media to ADMIN_MEDIA_ROOT:\n %s\n -> \n %s\n (%s)\n If you see issues, link manually." % (dpath, apath, e))
|
||||
else:
|
||||
print _(" Admin-media files should be copied manually to ADMIN_MEDIA_ROOT.")
|
||||
|
||||
|
|
@ -194,7 +195,7 @@ def at_initial_setup():
|
|||
return
|
||||
try:
|
||||
mod = __import__(modname, fromlist=[None])
|
||||
except ImportError, ValueError:
|
||||
except (ImportError, ValueError):
|
||||
return
|
||||
print _(" Running at_initial_setup() hook.")
|
||||
if mod.__dict__.get("at_initial_setup", None):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ etc.
|
|||
"""
|
||||
import re
|
||||
from src.utils.utils import make_iter
|
||||
from src.utils import logger
|
||||
|
||||
# variables
|
||||
MSDP = chr(69)
|
||||
|
|
@ -24,7 +25,7 @@ MSDP_ARRAY_CLOSE = chr(6)
|
|||
|
||||
regex_array = re.compile(r"%s(.*?)%s%s(.*?)%s" % (MSDP_VAR, MSDP_VAL, MSDP_ARRAY_OPEN, MSDP_ARRAY_CLOSE)) # return 2-tuple
|
||||
regex_table = re.compile(r"%s(.*?)%s%s(.*?)%s" % (MSDP_VAR, MSDP_VAL, MSDP_TABLE_OPEN, MSDP_TABLE_CLOSE)) # return 2-tuple (may be nested)
|
||||
regex_varval = re.compile(r"%s(.*?)%s(.*?)[%s]" % (MSDP_VAR, MSDP_VAL, ENDING)) # return 2-tuple
|
||||
regex_varval = re.compile(r"%s(.*?)%s(.*?)" % (MSDP_VAR, MSDP_VAL)) # return 2-tuple
|
||||
|
||||
class Msdp(object):
|
||||
"""
|
||||
|
|
@ -111,8 +112,8 @@ class Msdp(object):
|
|||
tables[table[0]] = dict(regex_varval(table[1]))
|
||||
for array in regex_array.findall(data):
|
||||
arrays[array[0]] = dict(regex_varval(array[1]))
|
||||
variables = dict(regex._varval(regex_array.sub("", regex_table.sub("", data))))
|
||||
|
||||
variables = dict(regex_varval(regex_array.sub("", regex_table.sub("", data))))
|
||||
print variables
|
||||
|
||||
|
||||
# MSDP Commands
|
||||
|
|
@ -125,7 +126,7 @@ class Msdp(object):
|
|||
The List command allows for retrieving various info about the server/client
|
||||
"""
|
||||
if arg == 'COMMANDS':
|
||||
return self.func_to_msdp(arg, MSDP_COMMANDS.keys())
|
||||
return self.func_to_msdp(arg, self.MSDP_COMMANDS.keys())
|
||||
elif arg == 'LISTS':
|
||||
return self.func_to_msdp(arg, ("COMMANDS", "LISTS",
|
||||
"CONFIGURABLE_VARIABLES",
|
||||
|
|
@ -133,11 +134,11 @@ class Msdp(object):
|
|||
elif arg == 'CONFIGURABLE_VARIABLES':
|
||||
return self.func_to_msdp(arg, ("CLIENT_NAME", "CLIENT_VERSION", "PLUGIN_ID"))
|
||||
elif arg == 'REPORTABLE_VARIABLES':
|
||||
return self.func_to_msdp(arg, MSDP_REPORTABLE.keys())
|
||||
return self.func_to_msdp(arg, self.MSDP_REPORTABLE.keys())
|
||||
elif arg == 'REPORTED_VARIABLES':
|
||||
return self.func_to_msdp(arg, MSDP_REPORTED.keys())
|
||||
return self.func_to_msdp(arg, self.MSDP_REPORTED.keys())
|
||||
elif arg == 'SENDABLE_VARIABLES':
|
||||
return self.func_to_msdp(arg, MSDP_SEND.keys())
|
||||
return self.func_to_msdp(arg, self.MSDP_SEND.keys())
|
||||
else:
|
||||
return self.func_to_msdp("LIST", arg)
|
||||
|
||||
|
|
@ -147,7 +148,7 @@ class Msdp(object):
|
|||
reportable variable to the client.
|
||||
"""
|
||||
try:
|
||||
MSDP_REPORTABLE[arg](report=True)
|
||||
self.MSDP_REPORTABLE[arg](report=True)
|
||||
except Exception:
|
||||
logger.log_trace()
|
||||
|
||||
|
|
@ -156,16 +157,16 @@ class Msdp(object):
|
|||
Unreport a previously reported variable
|
||||
"""
|
||||
try:
|
||||
MSDP_REPORTABLE[arg](eport=False)
|
||||
self.MSDP_REPORTABLE[arg](eport=False)
|
||||
except Exception:
|
||||
logger.log_trace()
|
||||
self.logger.log_trace()
|
||||
|
||||
def msdp_cmd_reset(self, arg):
|
||||
"""
|
||||
The reset command resets a variable to its initial state.
|
||||
"""
|
||||
try:
|
||||
MSDP_REPORTABLE[arg](reset=True)
|
||||
self.MSDP_REPORTABLE[arg](reset=True)
|
||||
except Exception:
|
||||
logger.log_trace()
|
||||
|
||||
|
|
@ -177,21 +178,22 @@ class Msdp(object):
|
|||
arg - this is a list of variables the client wants.
|
||||
"""
|
||||
ret = []
|
||||
for var in makeiter(arg):
|
||||
for var in make_iter(arg):
|
||||
try:
|
||||
ret.append(MSDP_REPORTABLE[arg](send=True))
|
||||
ret.append(self.MSDP_REPORTABLE[arg](send=True))
|
||||
except Exception:
|
||||
logger.log_trace()
|
||||
return ret
|
||||
|
||||
MSDP_COMMANDS = {
|
||||
"LIST": self.msdp_list,
|
||||
"LIST": "msdp_list",
|
||||
"REPORT":"mspd_report",
|
||||
"RESET":"mspd_reset",
|
||||
"SEND":"mspd_send",
|
||||
"UNREPORT":"mspd_unreport"
|
||||
}
|
||||
|
||||
|
||||
# MSDP_MAP is a standard suggestions for making it easy to create generic guis.
|
||||
# this maps MSDP command names to Evennia commands found in OOB_FUNC_MODULE. It
|
||||
# is up to these commands to return data on proper form.
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ class ServerSession(Session):
|
|||
else:
|
||||
logger.log_errmsg("oob_data_in error: funcname '%s' not found in OOB_FUNC_MODULE." % funcname)
|
||||
if outdata:
|
||||
# we have a result, send it back
|
||||
self.oob_data_out(outdata)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -951,6 +951,7 @@ class TypedObject(SharedMemoryModel):
|
|||
# If we reach this point we couldn't import any typeclasses. Return default. It's up to the calling
|
||||
# method to use e.g. self.is_typeclass() to detect that the result is not the one asked for.
|
||||
_GA(self, "_display_errmsg")(errstring)
|
||||
_SA(self, "typeclass_lasterrmsg", errstring)
|
||||
return _GA(self, "_get_default_typeclass")(cache=False, silent=False, save=False)
|
||||
|
||||
#@typeclass.deleter
|
||||
|
|
@ -961,6 +962,11 @@ class TypedObject(SharedMemoryModel):
|
|||
# typeclass property
|
||||
typeclass = property(__typeclass_get, fdel=__typeclass_del)
|
||||
|
||||
# the last error string will be stored here for accessing methods to access.
|
||||
# It is set by _display_errmsg, which will print to log if error happens
|
||||
# during server startup.
|
||||
typeclass_last_errmsg = ""
|
||||
|
||||
def _path_import(self, path):
|
||||
"""
|
||||
Import a class from a python path of the
|
||||
|
|
@ -973,17 +979,19 @@ class TypedObject(SharedMemoryModel):
|
|||
return None
|
||||
try:
|
||||
modpath, class_name = path.rsplit('.', 1)
|
||||
module = __import__(modpath, fromlist=[class_name])
|
||||
module = __import__(modpath, fromlist=["none"])
|
||||
return module.__dict__[class_name]
|
||||
except ImportError:
|
||||
trc = sys.exc_traceback
|
||||
if not trc.tb_next:
|
||||
# we separate between not finding the module, and finding a buggy one.
|
||||
errstring += "(Tried path '%s')." % path
|
||||
errstring = "Typeclass not found trying path '%s'." % path
|
||||
else:
|
||||
# a bug in the module is reported normally.
|
||||
trc = traceback.format_exc()
|
||||
errstring += "\n%sError importing '%s'." % (trc, path)
|
||||
errstring = "\n%sError importing '%s'." % (trc, path)
|
||||
except (ValueError, TypeError):
|
||||
errstring = "Malformed typeclass path '%s'." % path
|
||||
except KeyError:
|
||||
errstring = "No class '%s' was found in module '%s'."
|
||||
errstring = errstring % (class_name, modpath)
|
||||
|
|
@ -997,26 +1005,32 @@ class TypedObject(SharedMemoryModel):
|
|||
"""
|
||||
Helper function to display error.
|
||||
"""
|
||||
infochan = None
|
||||
cmessage = message
|
||||
try:
|
||||
from src.comms.models import Channel
|
||||
infochan = settings.CHANNEL_MUDINFO
|
||||
infochan = Channel.objects.get_channel(infochan[0])
|
||||
if infochan:
|
||||
cname = infochan.key
|
||||
cmessage = "\n".join(["[%s]: %s" % (cname, line) for line in message.split('\n') if line])
|
||||
cmessage = cmessage.strip()
|
||||
infochan.msg(cmessage)
|
||||
else:
|
||||
# no mudinfo channel is found. Log instead.
|
||||
cmessage = "\n".join(["[NO MUDINFO CHANNEL]: %s" % line for line in message.split('\n')])
|
||||
logger.log_errmsg(cmessage)
|
||||
except Exception:
|
||||
if ServerConfig.objects.conf("server_starting_mode"):
|
||||
print cmessage
|
||||
else:
|
||||
logger.log_trace(cmessage)
|
||||
if ServerConfig.objects.conf("server_starting_mode"):
|
||||
print message.strip()
|
||||
else:
|
||||
_SA(self, "typeclass_last_errmsg", message.strip())
|
||||
return
|
||||
|
||||
#infochan = None
|
||||
#cmessage = message
|
||||
#try:
|
||||
# from src.comms.models import Channel
|
||||
# infochan = settings.CHANNEL_MUDINFO
|
||||
# infochan = Channel.objects.get_channel(infochan[0])
|
||||
# if infochan:
|
||||
# cname = infochan.key
|
||||
# cmessage = "\n".join(["[%s]: %s" % (cname, line) for line in message.split('\n') if line])
|
||||
# cmessage = cmessage.strip()
|
||||
# infochan.msg(cmessage)
|
||||
# else:
|
||||
# # no mudinfo channel is found. Log instead.
|
||||
# cmessage = "\n".join(["[NO MUDINFO CHANNEL]: %s" % line for line in message.split('\n')])
|
||||
# logger.log_errmsg(cmessage)
|
||||
#except Exception:
|
||||
# if ServerConfig.objects.conf("server_starting_mode"):
|
||||
# print cmessage
|
||||
# else:
|
||||
# logger.log_trace(cmessage)
|
||||
|
||||
def _get_default_typeclass(self, cache=False, silent=False, save=False):
|
||||
"""
|
||||
|
|
@ -1064,7 +1078,9 @@ class TypedObject(SharedMemoryModel):
|
|||
"""
|
||||
Returns true if this object has this type
|
||||
OR has a typeclass which is an subclass of
|
||||
the given typeclass.
|
||||
the given typeclass. This operates on the actually
|
||||
loaded typeclass (this is important since a failing
|
||||
typeclass may instead have its default currently loaded)
|
||||
|
||||
typeclass - can be a class object or the
|
||||
python path to such an object to match against.
|
||||
|
|
@ -1079,7 +1095,7 @@ class TypedObject(SharedMemoryModel):
|
|||
pass
|
||||
typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in _GA(self, "_typeclass_paths")]
|
||||
if exact:
|
||||
current_path = _GA(self, "_cached_db_typeclass_path")
|
||||
current_path = _GA(self.typeclass, "path") #"_GA(self, "_cached_db_typeclass_path")
|
||||
return typeclass and any((current_path == typec for typec in typeclasses))
|
||||
else:
|
||||
# check parent chain
|
||||
|
|
@ -1158,10 +1174,9 @@ class TypedObject(SharedMemoryModel):
|
|||
self.nattr(nattr, delete=True)
|
||||
else:
|
||||
#print "deleting attrs ..."
|
||||
self.get_all_attributes()
|
||||
for attr in self.get_all_attributes():
|
||||
attr.delete()
|
||||
for nattr in self.ndb.all():
|
||||
for nattr in self.ndb.all:
|
||||
del nattr
|
||||
|
||||
# run hooks for this new typeclass
|
||||
|
|
@ -1328,8 +1343,9 @@ class TypedObject(SharedMemoryModel):
|
|||
_GA(self, 'obj').set_attribute(attrname, value)
|
||||
def __delattr__(self, attrname):
|
||||
_GA(self, 'obj').del_attribute(attrname)
|
||||
def all(self):
|
||||
def get_all(self):
|
||||
return _GA(self, 'obj').get_all_attributes()
|
||||
all = property(get_all)
|
||||
self._db_holder = DbHolder(self)
|
||||
return self._db_holder
|
||||
#@db.setter
|
||||
|
|
@ -1386,9 +1402,10 @@ class TypedObject(SharedMemoryModel):
|
|||
except AttributeError:
|
||||
class NdbHolder(object):
|
||||
"Holder for storing non-persistent attributes."
|
||||
def all(self):
|
||||
def get_all(self):
|
||||
return [val for val in self.__dict__.keys()
|
||||
if not val.startswith['_']]
|
||||
if not val.startswith('_')]
|
||||
all = property(get_all)
|
||||
def __getattribute__(self, key):
|
||||
# return None if no matching attribute was found.
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ shorter "create.object()".
|
|||
The respective object managers hold more methods for manipulating and
|
||||
searching objects already existing in the database.
|
||||
|
||||
Models covered:
|
||||
Models covered:
|
||||
Objects
|
||||
Scripts
|
||||
Help
|
||||
Message
|
||||
Channel
|
||||
Channel
|
||||
Players
|
||||
"""
|
||||
|
||||
|
|
@ -26,8 +26,7 @@ from django.conf import settings
|
|||
from django.contrib.auth.models import User
|
||||
from django.db import IntegrityError
|
||||
from src.utils.idmapper.models import SharedMemoryModel
|
||||
from src.utils import logger, utils, idmapper
|
||||
from src.utils.utils import is_iter, has_parent, inherits_from
|
||||
from src.utils import utils, logger
|
||||
|
||||
# limit symbol import from API
|
||||
__all__ = ("create_object", "create_script", "create_help_entry", "create_message", "create_channel", "create_player")
|
||||
|
|
@ -35,23 +34,28 @@ __all__ = ("create_object", "create_script", "create_help_entry", "create_messag
|
|||
GA = object.__getattribute__
|
||||
|
||||
#
|
||||
# Game Object creation
|
||||
# Game Object creation
|
||||
#
|
||||
|
||||
|
||||
def create_object(typeclass, key=None, location=None,
|
||||
home=None, player=None, permissions=None, locks=None,
|
||||
aliases=None, destination=None):
|
||||
home=None, player=None, permissions=None, locks=None,
|
||||
aliases=None, destination=None, report_to=None):
|
||||
"""
|
||||
Create a new in-game object. Any game object is a combination
|
||||
of a database object that stores data persistently to
|
||||
the database, and a typeclass, which on-the-fly 'decorates'
|
||||
the database object into whataver different type of object
|
||||
it is supposed to be in the game.
|
||||
it is supposed to be in the game.
|
||||
|
||||
See src.objects.managers for methods to manipulate existing objects
|
||||
in the database. src.objects.objects holds the base typeclasses
|
||||
and src.objects.models hold the database model.
|
||||
and src.objects.models hold the database model.
|
||||
|
||||
report_to is an optional object for reporting errors to in string form.
|
||||
If report_to is not set, errors will be raised as en Exception
|
||||
containing the error message. If set, this method will return
|
||||
None upon errors.
|
||||
"""
|
||||
# deferred import to avoid loops
|
||||
from src.objects.objects import Object
|
||||
|
|
@ -64,32 +68,36 @@ def create_object(typeclass, key=None, location=None,
|
|||
typeclass = typeclass.typeclass.path
|
||||
elif isinstance(typeclass, Object) or utils.inherits_from(typeclass, Object):
|
||||
# this is already an object typeclass, extract its path
|
||||
typeclass = typeclass.path
|
||||
typeclass = typeclass.path
|
||||
|
||||
# create new database object
|
||||
# create new database object
|
||||
new_db_object = ObjectDB()
|
||||
|
||||
# assign the typeclass
|
||||
|
||||
# assign the typeclass
|
||||
typeclass = utils.to_unicode(typeclass)
|
||||
new_db_object.typeclass_path = typeclass
|
||||
|
||||
# the name/key is often set later in the typeclass. This
|
||||
# is set here as a failsafe.
|
||||
# is set here as a failsafe.
|
||||
if key:
|
||||
new_db_object.key = key
|
||||
new_db_object.key = key
|
||||
else:
|
||||
new_db_object.key = "#%i" % new_db_object.id
|
||||
|
||||
# this will either load the typeclass or the default one
|
||||
new_object = new_db_object.typeclass
|
||||
|
||||
|
||||
if not GA(new_db_object, "is_typeclass")(typeclass, exact=True):
|
||||
if not GA(new_object, "is_typeclass")(typeclass, exact=True):
|
||||
# this will fail if we gave a typeclass as input and it still gave us a default
|
||||
SharedMemoryModel.delete(new_db_object)
|
||||
return None
|
||||
if report_to:
|
||||
GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_object.key, typeclass,
|
||||
GA(new_db_object, "typeclass_last_errmsg")))
|
||||
return None
|
||||
else:
|
||||
raise Exception(GA(new_db_object, "typeclass_last_errmsg"))
|
||||
|
||||
# from now on we can use the typeclass object
|
||||
# from now on we can use the typeclass object
|
||||
# as if it was the database object.
|
||||
|
||||
if player:
|
||||
|
|
@ -97,14 +105,14 @@ def create_object(typeclass, key=None, location=None,
|
|||
new_object.player = player
|
||||
player.obj = new_object
|
||||
|
||||
new_object.destination = destination
|
||||
new_object.destination = destination
|
||||
|
||||
# call the hook method. This is where all at_creation
|
||||
# customization happens as the typeclass stores custom
|
||||
# things on its database object.
|
||||
# things on its database object.
|
||||
new_object.basetype_setup() # setup the basics of Exits, Characters etc.
|
||||
new_object.at_object_creation()
|
||||
|
||||
|
||||
# custom-given perms/locks overwrite hooks
|
||||
if permissions:
|
||||
new_object.permissions = permissions
|
||||
|
|
@ -119,15 +127,15 @@ def create_object(typeclass, key=None, location=None,
|
|||
else:
|
||||
new_object.home = settings.CHARACTER_DEFAULT_HOME
|
||||
|
||||
|
||||
|
||||
if location:
|
||||
new_object.move_to(location, quiet=True)
|
||||
else:
|
||||
# rooms would have location=None.
|
||||
new_object.location = None
|
||||
new_object.location = None
|
||||
|
||||
# post-hook setup (mainly used by Exits)
|
||||
new_object.basetype_posthook_setup()
|
||||
new_object.basetype_posthook_setup()
|
||||
|
||||
new_object.save()
|
||||
return new_object
|
||||
|
|
@ -136,12 +144,12 @@ def create_object(typeclass, key=None, location=None,
|
|||
object = create_object
|
||||
|
||||
#
|
||||
# Script creation
|
||||
# Script creation
|
||||
#
|
||||
|
||||
def create_script(typeclass, key=None, obj=None, locks=None,
|
||||
interval=None, start_delay=None, repeats=None,
|
||||
persistent=None, autostart=True):
|
||||
def create_script(typeclass, key=None, obj=None, locks=None,
|
||||
interval=None, start_delay=None, repeats=None,
|
||||
persistent=None, autostart=True, report_to=None):
|
||||
"""
|
||||
Create a new script. All scripts are a combination
|
||||
of a database object that communicates with the
|
||||
|
|
@ -149,42 +157,47 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
|||
database object into being different types of scripts.
|
||||
It's behaviour is similar to the game objects except
|
||||
scripts has a time component and are more limited in
|
||||
scope.
|
||||
scope.
|
||||
|
||||
Argument 'typeclass' can be either an actual
|
||||
typeclass object or a python path to such an object.
|
||||
Only set key here if you want a unique name for this
|
||||
particular script (set it in config to give
|
||||
same key to all scripts of the same type). Set obj
|
||||
to tie this script to a particular object.
|
||||
to tie this script to a particular object.
|
||||
|
||||
See src.scripts.manager for methods to manipulate existing
|
||||
scripts in the database.
|
||||
|
||||
report_to is an obtional object to receive error messages.
|
||||
If report_to is not set, an Exception with the
|
||||
error will be raised. If set, this method will
|
||||
return None upon errors.
|
||||
"""
|
||||
|
||||
# deferred import to avoid loops.
|
||||
from src.scripts.scripts import Script
|
||||
#print "in create_script", typeclass
|
||||
from src.scripts.models import ScriptDB
|
||||
#print "in create_script", typeclass
|
||||
from src.scripts.models import ScriptDB
|
||||
|
||||
if not typeclass:
|
||||
typeclass = settings.BASE_SCRIPT_TYPECLASS
|
||||
elif isinstance(typeclass, ScriptDB):
|
||||
# this is already an scriptdb instance, extract its typeclass
|
||||
typeclass = new_db_object.typeclass.path
|
||||
typeclass = typeclass.typeclass.path
|
||||
elif isinstance(typeclass, Script) or utils.inherits_from(typeclass, Script):
|
||||
# this is already an object typeclass, extract its path
|
||||
typeclass = typeclass.path
|
||||
typeclass = typeclass.path
|
||||
|
||||
# create new database script
|
||||
new_db_script = ScriptDB()
|
||||
new_db_script = ScriptDB()
|
||||
|
||||
# assign the typeclass
|
||||
# assign the typeclass
|
||||
typeclass = utils.to_unicode(typeclass)
|
||||
new_db_script.typeclass_path = typeclass
|
||||
|
||||
|
||||
# the name/key is often set later in the typeclass. This
|
||||
# is set here as a failsafe.
|
||||
# is set here as a failsafe.
|
||||
if key:
|
||||
new_db_script.key = key
|
||||
else:
|
||||
|
|
@ -195,15 +208,19 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
|||
|
||||
if not GA(new_db_script, "is_typeclass")(typeclass, exact=True):
|
||||
# this will fail if we gave a typeclass as input and it still gave us a default
|
||||
print "failure:", new_db_script, typeclass
|
||||
SharedMemoryModel.delete(new_db_script)
|
||||
return None
|
||||
if report_to:
|
||||
GA(report_to, "msg")("Error creating %s (%s): %s" % (new_db_script.key, typeclass,
|
||||
GA(new_db_script, "typeclass_last_errmsg")))
|
||||
return None
|
||||
else:
|
||||
raise Exception(GA(new_db_script, "typeclass_last_errmsg"))
|
||||
|
||||
if obj:
|
||||
try:
|
||||
new_script.obj = obj
|
||||
except ValueError:
|
||||
new_script.obj = obj.dbobj
|
||||
new_script.obj = obj.dbobj
|
||||
|
||||
# call the hook method. This is where all at_creation
|
||||
# customization happens as the typeclass stores custom
|
||||
|
|
@ -212,10 +229,10 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
|||
|
||||
# custom-given variables override the hook
|
||||
if key:
|
||||
new_script.key = key
|
||||
new_script.key = key
|
||||
if locks:
|
||||
new_script.locks.add(locks)
|
||||
if interval != None:
|
||||
if interval != None:
|
||||
new_script.interval = interval
|
||||
if start_delay != None:
|
||||
new_script.start_delay = start_delay
|
||||
|
|
@ -223,13 +240,13 @@ def create_script(typeclass, key=None, obj=None, locks=None,
|
|||
new_script.repeats = repeats
|
||||
if persistent != None:
|
||||
new_script.persistent = persistent
|
||||
|
||||
|
||||
# a new created script should usually be started.
|
||||
if autostart:
|
||||
new_script.start()
|
||||
|
||||
|
||||
new_db_script.save()
|
||||
return new_script
|
||||
return new_script
|
||||
#alias
|
||||
script = create_script
|
||||
|
||||
|
|
@ -243,7 +260,7 @@ def create_help_entry(key, entrytext, category="General", locks=None):
|
|||
help entries are dynamic and directly taken from the __doc__ entries
|
||||
of the command. The database-stored help entries are intended for more
|
||||
general help on the game, more extensive info, in-game setting information
|
||||
and so on.
|
||||
and so on.
|
||||
"""
|
||||
|
||||
from src.help.models import HelpEntry
|
||||
|
|
@ -255,19 +272,19 @@ def create_help_entry(key, entrytext, category="General", locks=None):
|
|||
if locks:
|
||||
new_help.locks.add(locks)
|
||||
new_help.save()
|
||||
return new_help
|
||||
return new_help
|
||||
except IntegrityError:
|
||||
string = "Could not add help entry: key '%s' already exists." % key
|
||||
logger.log_errmsg(string)
|
||||
return None
|
||||
except Exception:
|
||||
logger.log_trace()
|
||||
return None
|
||||
return None
|
||||
# alias
|
||||
help_entry = create_help_entry
|
||||
|
||||
#
|
||||
# Comm system methods
|
||||
# Comm system methods
|
||||
#
|
||||
|
||||
def create_message(senderobj, message, channels=None,
|
||||
|
|
@ -279,7 +296,7 @@ def create_message(senderobj, message, channels=None,
|
|||
senderobj - the player sending the message. This must be the actual object.
|
||||
message - text with the message. Eventual headers, titles etc
|
||||
should all be included in this text string. Formatting
|
||||
will be retained.
|
||||
will be retained.
|
||||
channels - a channel or a list of channels to send to. The channels
|
||||
may be actual channel objects or their unique key strings.
|
||||
receivers - a player to send to, or a list of them. May be Player objects
|
||||
|
|
@ -289,7 +306,7 @@ def create_message(senderobj, message, channels=None,
|
|||
The Comm system is created very open-ended, so it's fully possible
|
||||
to let a message both go to several channels and to several receivers
|
||||
at the same time, it's up to the command definitions to limit this as
|
||||
desired.
|
||||
desired.
|
||||
"""
|
||||
from src.comms.models import Msg
|
||||
from src.players.models import PlayerDB
|
||||
|
|
@ -304,10 +321,10 @@ def create_message(senderobj, message, channels=None,
|
|||
elif hasattr(obj, 'db_player'):
|
||||
return obj.db_player
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
|
||||
if not message:
|
||||
# we don't allow empty messages.
|
||||
# we don't allow empty messages.
|
||||
return
|
||||
|
||||
new_message = Msg()
|
||||
|
|
@ -315,19 +332,19 @@ def create_message(senderobj, message, channels=None,
|
|||
new_message.message = message
|
||||
new_message.save()
|
||||
if channels:
|
||||
if not is_iter(channels):
|
||||
if not utils.is_iter(channels):
|
||||
channels = [channels]
|
||||
new_message.channels = [channel for channel in
|
||||
[to_object(channel, objtype='channel')
|
||||
for channel in channels] if channel]
|
||||
for channel in channels] if channel]
|
||||
if receivers:
|
||||
#print "Found receiver:", receivers
|
||||
if not is_iter(receivers):
|
||||
if not utils.is_iter(receivers):
|
||||
receivers = [receivers]
|
||||
#print "to_player: %s" % to_player(receivers[0])
|
||||
new_message.receivers = [to_player(receiver) for receiver in
|
||||
[to_object(receiver) for receiver in receivers]
|
||||
if receiver]
|
||||
if receiver]
|
||||
if locks:
|
||||
new_message.locks.add(locks)
|
||||
new_message.save()
|
||||
|
|
@ -343,20 +360,20 @@ def create_channel(key, aliases=None, desc=None,
|
|||
specifying the receivers explicitly. Instead players may
|
||||
'connect' to the channel and follow the flow of messages. By
|
||||
default the channel allows access to all old messages, but
|
||||
this can be turned off with the keep_log switch.
|
||||
this can be turned off with the keep_log switch.
|
||||
|
||||
key - this must be unique.
|
||||
key - this must be unique.
|
||||
aliases - list of alternative (likely shorter) keynames.
|
||||
locks - lock string definitions
|
||||
"""
|
||||
|
||||
from src.comms.models import Channel
|
||||
from src.comms import channelhandler
|
||||
from src.comms.models import Channel
|
||||
from src.comms import channelhandler
|
||||
try:
|
||||
new_channel = Channel()
|
||||
new_channel.key = key
|
||||
new_channel.key = key
|
||||
if aliases:
|
||||
if not is_iter(aliases):
|
||||
if not utils.is_iter(aliases):
|
||||
aliases = [aliases]
|
||||
new_channel.aliases = ",".join([alias for alias in aliases])
|
||||
new_channel.desc = desc
|
||||
|
|
@ -369,33 +386,33 @@ def create_channel(key, aliases=None, desc=None,
|
|||
new_channel.locks.add(locks)
|
||||
new_channel.save()
|
||||
channelhandler.CHANNELHANDLER.add_channel(new_channel)
|
||||
return new_channel
|
||||
return new_channel
|
||||
|
||||
channel = create_channel
|
||||
|
||||
channel = create_channel
|
||||
|
||||
#
|
||||
# Player creation methods
|
||||
# Player creation methods
|
||||
#
|
||||
|
||||
def create_player(name, email, password,
|
||||
user=None,
|
||||
typeclass=None,
|
||||
is_superuser=False,
|
||||
is_superuser=False,
|
||||
locks=None, permissions=None,
|
||||
create_character=True, character_typeclass=None,
|
||||
character_location=None, character_home=None,
|
||||
player_dbobj=None):
|
||||
player_dbobj=None, report_to=None):
|
||||
|
||||
|
||||
|
||||
"""
|
||||
This creates a new player, handling the creation of the User
|
||||
object and its associated Player object.
|
||||
object and its associated Player object.
|
||||
|
||||
If player_dbobj is given, this player object is used instead of
|
||||
If player_dbobj is given, this player object is used instead of
|
||||
creating a new one. This is called by the admin interface since it
|
||||
needs to create the player object in order to relate it automatically
|
||||
to the user.
|
||||
|
||||
to the user.
|
||||
|
||||
If create_character is
|
||||
True, a game player object with the same name as the User/Player will
|
||||
also be created. Its typeclass and base properties can also be given.
|
||||
|
|
@ -403,15 +420,15 @@ def create_player(name, email, password,
|
|||
Returns the new game character, or the Player obj if no
|
||||
character is created. For more info about the typeclass argument,
|
||||
see create_objects() above.
|
||||
|
||||
Note: if user is supplied, it will NOT be modified (args name, email,
|
||||
passw and is_superuser will be ignored). Change those properties
|
||||
directly on the User instead.
|
||||
|
||||
Note: if user is supplied, it will NOT be modified (args name, email,
|
||||
passw and is_superuser will be ignored). Change those properties
|
||||
directly on the User instead.
|
||||
|
||||
If no permissions are given (None), the default permission group
|
||||
as defined in settings.PERMISSION_PLAYER_DEFAULT will be
|
||||
as defined in settings.PERMISSION_PLAYER_DEFAULT will be
|
||||
assigned. If permissions are given, no automatic assignment will
|
||||
occur.
|
||||
occur.
|
||||
|
||||
Concerning is_superuser:
|
||||
A superuser should have access to everything
|
||||
|
|
@ -420,18 +437,18 @@ def create_player(name, email, password,
|
|||
django's own creation, not this one).
|
||||
Usually only the server admin should need to be superuser, all
|
||||
other access levels can be handled with more fine-grained
|
||||
permissions or groups.
|
||||
permissions or groups.
|
||||
Since superuser overrules all permissions, we don't
|
||||
set any in this case.
|
||||
|
||||
|
||||
"""
|
||||
# The system should already have checked so the name/email
|
||||
# isn't already registered, and that the password is ok before
|
||||
# getting here.
|
||||
# getting here.
|
||||
|
||||
from src.players.models import PlayerDB
|
||||
from src.players.player import Player
|
||||
|
||||
|
||||
if not email:
|
||||
email = "dummy@dummy.com"
|
||||
if user:
|
||||
|
|
@ -441,7 +458,7 @@ def create_player(name, email, password,
|
|||
if is_superuser:
|
||||
new_user = User.objects.create_superuser(name, email, password)
|
||||
else:
|
||||
new_user = User.objects.create_user(name, email, password)
|
||||
new_user = User.objects.create_user(name, email, password)
|
||||
try:
|
||||
if not typeclass:
|
||||
typeclass = settings.BASE_PLAYER_TYPECLASS
|
||||
|
|
@ -450,7 +467,7 @@ def create_player(name, email, password,
|
|||
typeclass = typeclass.typeclass.path
|
||||
elif isinstance(typeclass, Player) or utils.inherits_from(typeclass, Player):
|
||||
# this is already an object typeclass, extract its path
|
||||
typeclass = typeclass.path
|
||||
typeclass = typeclass.path
|
||||
|
||||
if player_dbobj:
|
||||
new_db_player = player_dbobj
|
||||
|
|
@ -458,7 +475,7 @@ def create_player(name, email, password,
|
|||
new_db_player = PlayerDB(db_key=name, user=new_user)
|
||||
new_db_player.save()
|
||||
|
||||
# assign the typeclass
|
||||
# assign the typeclass
|
||||
typeclass = utils.to_unicode(typeclass)
|
||||
new_db_player.typeclass_path = typeclass
|
||||
|
||||
|
|
@ -468,13 +485,18 @@ def create_player(name, email, password,
|
|||
if not GA(new_db_player, "is_typeclass")(typeclass, exact=True):
|
||||
# this will fail if we gave a typeclass as input and it still gave us a default
|
||||
SharedMemoryModel.delete(new_db_player)
|
||||
return None
|
||||
if report_to:
|
||||
GA(report_to, "msg")("Error creating %s (%s):\n%s" % (new_db_player.key, typeclass,
|
||||
GA(new_db_player, "typeclass_last_errmsg")))
|
||||
return None
|
||||
else:
|
||||
raise Exception(GA(new_db_player, "typeclass_last_errmsg"))
|
||||
|
||||
new_player.basetype_setup() # setup the basic locks and cmdset
|
||||
# call hook method (may override default permissions)
|
||||
new_player.at_player_creation()
|
||||
|
||||
# custom given arguments potentially overrides the hook
|
||||
# custom given arguments potentially overrides the hook
|
||||
if permissions:
|
||||
new_player.permissions = permissions
|
||||
elif not new_player.permissions:
|
||||
|
|
@ -483,19 +505,19 @@ def create_player(name, email, password,
|
|||
if locks:
|
||||
new_player.locks.add(locks)
|
||||
|
||||
# create *in-game* 'player' object
|
||||
# create *in-game* 'player' object
|
||||
if create_character:
|
||||
if not character_typeclass:
|
||||
character_typeclass = settings.BASE_CHARACTER_TYPECLASS
|
||||
# creating the object automatically links the player
|
||||
# and object together by player.obj <-> obj.player
|
||||
new_character = create_object(character_typeclass, key=name,
|
||||
location=None, home=character_location,
|
||||
location=None, home=character_location,
|
||||
permissions=permissions,
|
||||
player=new_player)
|
||||
player=new_player, report_to=report_to)
|
||||
return new_character
|
||||
return new_player
|
||||
except Exception,e:
|
||||
except Exception:
|
||||
# a failure in creating the character
|
||||
if not user:
|
||||
# in there was a failure we clean up everything we can
|
||||
|
|
@ -507,12 +529,12 @@ def create_player(name, email, password,
|
|||
try:
|
||||
new_player.delete()
|
||||
except Exception:
|
||||
pass
|
||||
pass
|
||||
try:
|
||||
del new_character
|
||||
except Exception:
|
||||
pass
|
||||
raise
|
||||
pass
|
||||
raise
|
||||
|
||||
# alias
|
||||
player = create_player
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue