evennia/src/commands/default/general.py

450 lines
No EOL
13 KiB
Python

"""
General Character commands usually availabe to all characters
"""
from django.conf import settings
from src.utils import utils, prettytable
from src.commands.default.muxcommand import MuxCommand
# limit symbol import for API
__all__ = ("CmdHome", "CmdLook", "CmdNick",
"CmdInventory", "CmdGet", "CmdDrop", "CmdGive",
"CmdSay", "CmdPose", "CmdAccess")
AT_SEARCH_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
class CmdHome(MuxCommand):
"""
home
Usage:
home
Teleports you to your home location.
"""
key = "home"
locks = "cmd:perm(home) or perm(Builders)"
def func(self):
"Implement the command"
caller = self.caller
home = caller.home
if not home:
caller.msg("You have no home!")
elif home == caller.location:
caller.msg("You are already home!")
else:
caller.move_to(home)
caller.msg("There's no place like home ...")
class CmdLook(MuxCommand):
"""
look
Usage:
look
look <obj>
look *<player>
Observes your location or objects in your vicinity.
"""
key = "look"
aliases = ["l", "ls"]
locks = "cmd:all()"
arg_regex = r"\s.*?|$"
def func(self):
"""
Handle the looking.
"""
caller = self.caller
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
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
if not looking_at_obj.access(caller, "view"):
caller.msg("Could not find '%s'." % args)
return
# get object's appearance
caller.msg(looking_at_obj.return_appearance(caller))
# the object's at_desc() method.
looking_at_obj.at_desc(looker=caller)
class CmdNick(MuxCommand):
"""
Define a personal alias/nick
Usage:
nick[/switches] <nickname> = [<string>]
alias ''
Switches:
object - alias an object
player - alias a player
clearall - clear all your aliases
list - show all defined aliases (also "nicks" works)
Examples:
nick hi = say Hello, I'm Sarah!
nick/object tom = the tall man
A 'nick' is a personal shortcut you create for your own use. When
you enter the nick, the alternative string will be sent instead.
The switches control in which situations the substitution will
happen. The default is that it will happen when you enter a
command. The 'object' and 'player' nick-types kick in only when
you use commands that requires an object or player as a target -
you can then use the nick to refer to them.
Note that no objects are actually renamed or changed by this
command - the nick is only available to you. If you want to
permanently add keywords to an object for everyone to use, you
need build privileges and to use the @alias command.
"""
key = "nick"
aliases = ["nickname", "nicks", "@nick", "alias"]
locks = "cmd:all()"
def func(self):
"Create the nickname"
caller = self.caller
switches = self.switches
nicks = caller.nicks.get(category="channel")
if 'list' in switches:
table = prettytable.PrettyTable(["{wNickType",
"{wNickname",
"{wTranslates-to"])
for nick in nicks:
table.add_row([nick.db_category, nick.db_key, nick.db_data])
string = "{wDefined Nicks:{n\n%s" % table
caller.msg(string)
return
if 'clearall' in switches:
caller.nicks.clear()
caller.msg("Cleared all aliases.")
return
if not self.args or not self.lhs:
caller.msg("Usage: nick[/switches] nickname = [realname]")
return
nick = self.lhs
real = self.rhs
if real == nick:
caller.msg("No point in setting nick same as the string to replace...")
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"]
string = ""
for switch in switches:
oldnick = caller.nicks.get(key=nick, category=switch)
#oldnick = Nick.objects.filter(db_obj=caller.dbobj, db_nick__iexact=nick, db_type__iexact=switch)
if not real:
# removal of nick
if oldnick:
# clear the alias
string += "\nNick '%s' (= '%s') was cleared." % (nick, oldnick[0].db_real)
caller.nicks.delete(nick, category=switch)
else:
string += "\nNo nick '%s' found, so it could not be removed." % nick
else:
# 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, category=switch)
caller.msg(string)
class CmdInventory(MuxCommand):
"""
inventory
Usage:
inventory
inv
Shows your inventory.
"""
key = "inventory"
aliases = ["inv", "i"]
locks = "cmd:all()"
def func(self):
"check inventory"
items = self.caller.contents
if not items:
string = "You are not carrying anything."
else:
table = prettytable.PrettyTable(["name", "desc"])
table.header = False
table.border = False
for item in items:
table.add_row(["{C%s{n" % item.name, item.db.desc and item.db.desc or ""])
string = "{wYou are carrying:\n%s" % table
self.caller.msg(string)
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()"
def func(self):
"implements the command."
caller = self.caller
if not self.args:
caller.msg("Get what?")
return
#print "general/get:", caller, caller.location, self.args, caller.location.contents
obj = caller.search(self.args, location=caller.location)
if not obj:
return
if caller == obj:
caller.msg("You can't get yourself.")
return
#print obj, obj.location, caller, caller==obj.location
if caller == obj.location:
caller.msg("You already hold that.")
return
if not obj.access(caller, 'get'):
if obj.db.get_err_msg:
caller.msg(obj.db.get_err_msg)
else:
caller.msg("You can't get that.")
return
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),
exclude=caller)
# calling hook method
obj.at_get(caller)
class CmdDrop(MuxCommand):
"""
drop
Usage:
drop <obj>
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"
caller = self.caller
if not self.args:
caller.msg("Drop what?")
return
# Because the DROP command by definition looks for items
# in inventory, call the search function using location = caller
results = caller.search(self.args, location=caller, quiet=True)
# now we send it into the error handler (this will output consistent
# error messages if there are problems).
obj = AT_SEARCH_RESULT(caller, self.args, results, False,
nofound_string="You don't carry %s." % self.args,
multimatch_string="You carry more than one %s:" % self.args)
if not obj:
return
obj.move_to(caller.location, quiet=True)
caller.msg("You drop %s." % (obj.name,))
caller.location.msg_contents("%s drops %s." %
(caller.name, obj.name),
exclude=caller)
# Call the object script's at_drop() method.
obj.at_drop(caller)
class CmdGive(MuxCommand):
"""
give away things
Usage:
give <inventory obj> = <target>
Gives an items from your inventory to another character,
placing it in their inventory.
"""
key = "give"
locks = "cmd:all()"
def func(self):
"Implement give"
caller = self.caller
if not self.args or not self.rhs:
caller.msg("Usage: give <inventory object> = <target>")
return
to_give = caller.search(self.lhs)
target = caller.search(self.rhs)
if not (to_give and target):
return
if target == caller:
caller.msg("You keep %s to yourself." % to_give.key)
return
if not to_give.location == caller:
caller.msg("You are not holding %s." % to_give.key)
return
# give object
to_give.location = target
caller.msg("You give %s to %s." % (to_give.key, target.key))
target.msg("%s gives you %s." % (caller.key, to_give.key))
class CmdSay(MuxCommand):
"""
say
Usage:
say <message>
Talk to those in your current location.
"""
key = "say"
aliases = ['"', "'"]
locks = "cmd:all()"
def func(self):
"Run the say command"
caller = self.caller
if not self.args:
caller.msg("Say what?")
return
speech = self.args
# calling the speech hook on the location
speech = caller.location.at_say(caller, speech)
# 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,
speech)
caller.location.msg_contents(emit_string,
exclude=caller)
class CmdPose(MuxCommand):
"""
pose - strike a pose
Usage:
pose <pose text>
pose's <pose text>
Example:
pose is standing by the wall, smiling.
-> others will see:
Tom is standing by the wall, smiling.
Describe an action being taken. The pose text will
automatically begin with your name.
"""
key = "pose"
aliases = [":", "emote"]
locks = "cmd:all()"
def parse(self):
"""
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
space.
"""
args = self.args
if args and not args[0] in ["'", ",", ":"]:
args = " %s" % args.strip()
self.args = args
def func(self):
"Hook function"
if not self.args:
msg = "What do you want to do?"
self.caller.msg(msg)
else:
msg = "%s%s" % (self.caller.name, self.args)
self.caller.location.msg_contents(msg)
class CmdAccess(MuxCommand):
"""
access - show access groups
Usage:
access
This command shows you the permission hierarchy and
which permission groups you are a member of.
"""
key = "access"
aliases = ["groups", "hierarchy"]
locks = "cmd:all()"
def func(self):
"Load the permission groups"
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]
if self.caller.player.is_superuser:
cperms = "<Superuser>"
pperms = "<Superuser>"
else:
cperms = ", ".join(caller.permissions.all())
pperms = ", ".join(caller.player.permissions.all())
string += "\n{wYour access{n:"
string += "\nCharacter {c%s{n: %s" % (caller.key, cperms)
if hasattr(caller, 'player'):
string += "\nPlayer {c%s{n: %s" % (caller.player.key, pperms)
caller.msg(string)