Cleaned up @link, @open and @dig, making these commands more useful and less buggy with strange input. Also made them work not only with #dbrefs but with any unique game object (possibly one should limit this to e.g. room's); if there's a multiple match a list of the relevant dbrefs are shown. You can also now inspect links/home settins using this command.

@open also supports script_parents when creating exits.
/Griatch
This commit is contained in:
Griatch 2009-10-05 23:06:57 +00:00
parent 66095a0b16
commit 42254355a0
3 changed files with 201 additions and 105 deletions

View file

@ -439,6 +439,8 @@ def cmd_create(command):
have a correct parent object defined in parents/examples/red_button.py, you would have a correct parent object defined in parents/examples/red_button.py, you would
load create a new object inheriting from this parent like this: load create a new object inheriting from this parent like this:
@create button:examples.red_button @create button:examples.red_button
(See also @destroy, @dig and @open.)
""" """
source_object = command.source_object source_object = command.source_object
@ -557,77 +559,119 @@ GLOBAL_CMD_TABLE.add_command("@nextfree", cmd_nextfree,
priv_tuple=("objects.info",),auto_help=True,staff_help=True) priv_tuple=("objects.info",),auto_help=True,staff_help=True)
def cmd_open(command): def cmd_open(command):
""" """@open
Handle the opening of exits. Usage:
@open <new exit> [:parent] [= <destination> [,<return exit> [:parent]]]
Forms: Handles the creation of exits. If a destination is given, the exit
@open <Name> will point there. The <return exit> argument sets up an exit at the
@open <Name>=<Dbref> destination leading back to the current room. Destination name
@open <Name>=<Dbref>,<Name> can be given both as a #dbref and a name, if that name is globally
unique.
(See also @create, @dig and @link.)
""" """
source_object = command.source_object source_object = command.source_object
args = command.command_argument
if not command.command_argument: if not args:
source_object.emit_to("Usage: @open <name> [=dbref [,<name>]]") source_object.emit_to("Usage: @open <new exit> [:parent] [= <destination> [,<return exit> [:parent]]]")
return return
dest_name = ""
return_exit = ""
exit_parent = None
return_exit_parent = None
# handle all arguments
arglist = args.split('=', 1)
#left side of =
largs = arglist[0].split(':')
if len(largs) > 1:
exit_name, exit_parent = largs[0].strip(), largs[1].strip()
else:
exit_name = largs[0].strip()
if len(arglist) > 1:
# right side of =
rargs = arglist[1].split(',',1)
if len(rargs) > 1:
dest_name, rargs = rargs[0].strip(),rargs[1].strip()
rargs = rargs.split(":")
if len(rargs) > 1:
return_exit, return_exit_parent = rargs[0].strip(), rargs[1].strip()
else:
return_exit = rargs[0].strip()
else:
dest_name = rargs[0].strip()
eq_args = command.command_argument.split('=', 1) # sanity checking
exit_name = eq_args[0] if not exit_name:
if len(exit_name) == 0:
source_object.emit_to("You must supply an exit name.") source_object.emit_to("You must supply an exit name.")
return return
# If we have more than one entry in our '=' delimited argument list, if not dest_name:
# then we're doing a @open <Name>=<Dbref>[,<Name>]. If not, we're doing # we want an unlinked exit.
# an un-linked exit, @open <Name>. new_object = Object.objects.create_object(exit_name,
if len(eq_args) > 1: defines_global.OTYPE_EXIT,
# Opening an exit to another location via @open <Name>=<Dbref>[,<Name>]. source_object.get_location(),
comma_split = eq_args[1].split(',', 1) source_object,
# Use search_for_object to handle duplicate/nonexistant results. None,
destination = source_object.search_for_object(comma_split[0]) script_parent=exit_parent)
ptext = ""
if exit_parent:
if new_object.get_script_parent() == exit_parent:
ptext += " of type %s" % exit_parent
else:
ptext += " of default type (parent '%s' failed!)" % exit_parent
source_object.emit_to("Created unlinked exit%s named '%s'." % (ptext,new_object))
else:
# We have the name of a destination. Try to find it.
destination = Object.objects.global_object_name_search(dest_name)
if not destination: if not destination:
source_object.emit_to("No matches found for '%s'." % dest_name)
return return
if len(destination) > 1:
s = "There are multiple matches. Please use #dbref to be more specific."
for d in destination:
s += "\n %s" % destination.get_name()
source_object.emit_to(s)
return
destination = destination[0]
if destination.is_exit(): if destination.is_exit():
source_object.emit_to("You can't open an exit to an exit!") source_object.emit_to("You can't open an exit to an exit!")
return return
#build the exit from here to destination
new_object = Object.objects.create_object(exit_name, new_object = Object.objects.create_object(exit_name,
defines_global.OTYPE_EXIT, defines_global.OTYPE_EXIT,
source_object.get_location(), source_object.get_location(),
source_object, source_object,
destination) destination,
script_parent=exit_parent)
ptext = ""
if exit_parent:
if new_object.get_script_parent() == exit_parent:
ptext += " of type %s" % exit_parent
else:
ptext += " of default type (parent '%s' failed!)" % exit_parent
source_object.emit_to("Created exit%s to %s named '%s'." % (ptext,destination,new_object))
source_object.emit_to("You open the an exit - %s to %s" % ( if return_exit:
new_object.get_name(), new_object = Object.objects.create_object(return_exit,
destination.get_name()))
if len(comma_split) > 1:
second_exit_name = ','.join(comma_split[1:])
#odat = {"name": second_exit_name,
# "type": defines_global.OTYPE_EXIT,
# "location": destination,
# "owner": source_object,
# "home": source_object.get_location()}
new_object = Object.objects.create_object(second_exit_name,
defines_global.OTYPE_EXIT, defines_global.OTYPE_EXIT,
destination, destination,
source_object, source_object,
source_object.get_location()) source_object.get_location(),
source_object.emit_to("You open the an exit - %s to %s" % ( script_parent=return_exit_parent)
new_object.get_name(), ptext = ""
source_object.get_location().get_name())) if return_exit_parent:
if new_object.get_script_parent() == return_exit_parent:
else: ptext += " of type %s" % return_exit_parent
# Create an un-linked exit. else:
new_object = Object.objects.create_object(exit_name, ptext += " of default type (parent '%s' failed!)" % return_exit_parent
defines_global.OTYPE_EXIT, source_object.emit_to("Created exit%s back from %s named %s." % \
source_object.get_location(), (ptext, destination, new_object))
source_object,
None)
source_object.emit_to("You open an unlinked exit - %s" % new_object)
GLOBAL_CMD_TABLE.add_command("@open", cmd_open, GLOBAL_CMD_TABLE.add_command("@open", cmd_open,
priv_tuple=("objects.dig",)) priv_tuple=("objects.dig",),auto_help=True,staff_help=True)
def cmd_chown(command): def cmd_chown(command):
""" """
@ -733,56 +777,95 @@ def cmd_chzone(command):
GLOBAL_CMD_TABLE.add_command("@chzone", cmd_chzone, priv_tuple=("objects.dig",)) GLOBAL_CMD_TABLE.add_command("@chzone", cmd_chzone, priv_tuple=("objects.dig",))
def cmd_link(command): def cmd_link(command):
""" """@link
Sets an object's home or an exit's destination. Usage:
@link <object> = <target>
@link <object> =
@link <object>
Forms: If <object> is an exit, set its destination. For all other object types, this
@link <Object>=<Target> command sets the object's Home.
The second form sets the destination/home to None and the third form inspects
the current value of destination/home on <object>.
(See also @create, @dig and @open)
""" """
source_object = command.source_object source_object = command.source_object
if not command.command_argument: if not command.command_argument:
source_object.emit_to("Usage: @link <object> = <target>") source_object.emit_to("Usage: @link <object> = <target>")
return return
dest_name = ""
arglist = command.command_argument.split('=', 1)
if len(arglist) > 1:
obj_name, dest_name = arglist[0].strip(), arglist[1].strip()
else:
obj_name = arglist[0].strip()
eq_args = command.command_argument.split('=', 1) # sanity checks
target_name = eq_args[0] if not obj_name:
dest_name = eq_args[1]
if len(target_name) == 0:
source_object.emit_to("What do you want to link?") source_object.emit_to("What do you want to link?")
return return
if len(eq_args) > 1: # Use search_for_object to handle duplicate/nonexistant results.
target_obj = source_object.search_for_object(target_name) obj = source_object.search_for_object(obj_name)
# Use search_for_object to handle duplicate/nonexistant results. if not obj:
if not target_obj: return
return otype = obj.get_type()
if not source_object.controls_other(target_obj): if not dest_name:
# We haven't provided a target.
if len(arglist) > 1:
# the command looks like '@link obj =', this means we unlink the
if not source_object.controls_other(obj):
source_object.emit_to(defines_global.NOCONTROL_MSG)
return
oldhome = obj.get_home()
ohome_text = ""
if oldhome:
ohome_text = " (was %s)" % oldhome
obj.set_home(None)
if otype == "EXIT":
source_object.emit_to("You have unlinked %s%s." % (obj,ohome_text))
else:
source_object.emit_to("You removed %s's home setting%s." % (obj,ohome_text))
return
else:
# the command looks like '@link obj', we just inspect the object.
if otype == "EXIT":
source_object.emit_to("%s currently links to %s." % (obj.get_name(), obj.get_home()))
else:
source_object.emit_to("%s's current home is %s." % (obj.get_name(), obj.get_home()))
return
else:
# we have a destination, search for it globally.
if not source_object.controls_other(obj):
source_object.emit_to(defines_global.NOCONTROL_MSG) source_object.emit_to(defines_global.NOCONTROL_MSG)
return return
destination = Object.objects.global_object_name_search(dest_name)
# If we do something like "@link blah=", we unlink the object.
if len(dest_name) == 0:
target_obj.set_home(None)
source_object.emit_to("You have unlinked %s." % (target_obj,))
return
destination = source_object.search_for_object(dest_name)
# Use search_for_object to handle duplicate/nonexistant results.
if not destination: if not destination:
source_object.emit_to("No matches found for '%s'." % dest_name)
return return
if len(destination) > 1:
s = "There are multiple matches. Please use #dbref to be more specific."
for d in destination:
s += "\n %s" % destination.get_name()
source_object.emit_to(s)
return
destination = destination[0]
target_obj.set_home(destination) # do the link.
source_object.emit_to("You link %s to %s." % (target_obj, destination)) oldhome = obj.get_home()
ohome_text = ""
else: if oldhome:
# We haven't provided a target. ohome_text = " (was %s)" % oldhome
source_object.emit_to("You must provide a destination to link to.") obj.set_home(destination)
return if otype == "EXIT":
source_object.emit_to("You link %s to %s%s." % (obj, destination, ohome_text))
else:
source_object.emit_to("You set the home location of %s to %s%s." % (obj, destination, ohome_text))
GLOBAL_CMD_TABLE.add_command("@link", cmd_link, GLOBAL_CMD_TABLE.add_command("@link", cmd_link,
priv_tuple=("objects.dig",)) priv_tuple=("objects.dig",), auto_help=True, staff_help=True)
def cmd_unlink(command): def cmd_unlink(command):
""" """
@ -811,20 +894,19 @@ GLOBAL_CMD_TABLE.add_command("@unlink", cmd_unlink,
priv_tuple=("objects.dig",)) priv_tuple=("objects.dig",))
def cmd_dig(command): def cmd_dig(command):
""" """@dig
Creates a new room object and optionally connects it to
where you are.
Usage: Usage:
@dig[/switches] roomname [:parent] [= exit_to_there [: parent][;alias]] [, exit_to_here [: parent][;alias]] @dig[/switches] roomname [:parent] [= exit_to_there [: parent][;alias]] [, exit_to_here [: parent][;alias]]
switches: switches:
teleport - move yourself to the new room teleport - move yourself to the new room
example: example:
@dig kitchen = north; n, south; s @dig kitchen = north; n, south; s
This command is a convenient way to build rooms quickly; it creates the new room and you can optionally
set up exits back and forth between your current room and the new one.
((NOTE - ALIASES ARE NOT YET FUNCTIONAL.))
(See also @create, @open and @link.)
""" """
source_object = command.source_object source_object = command.source_object
args = command.command_argument args = command.command_argument
@ -894,7 +976,8 @@ def cmd_dig(command):
defines_global.OTYPE_EXIT, defines_global.OTYPE_EXIT,
location, location,
source_object, source_object,
destination) destination,
script_parent=exit_parents[0])
ptext = "" ptext = ""
if exit_parents[0]: if exit_parents[0]:
script_parent = exit_parents[0] script_parent = exit_parents[0]
@ -915,7 +998,8 @@ def cmd_dig(command):
defines_global.OTYPE_EXIT, defines_global.OTYPE_EXIT,
destination, destination,
source_object, source_object,
location) location,
script_parent=exit_parents[1])
ptext = "" ptext = ""
if exit_parents[1]: if exit_parents[1]:
script_parent = exit_parents[1] script_parent = exit_parents[1]
@ -935,7 +1019,7 @@ def cmd_dig(command):
source_object.move_to(new_room) source_object.move_to(new_room)
GLOBAL_CMD_TABLE.add_command("@dig", cmd_dig, GLOBAL_CMD_TABLE.add_command("@dig", cmd_dig,
priv_tuple=("objects.dig",)) priv_tuple=("objects.dig",), auto_help=True, staff_help=True)
def cmd_name(command): def cmd_name(command):
""" """
@ -1104,6 +1188,8 @@ def cmd_destroy(command):
@recover command. The contents of a room will be moved out before it is destroyed, @recover command. The contents of a room will be moved out before it is destroyed,
and all exits leading to and fro the room will also be destroyed. Note that destroyed and all exits leading to and fro the room will also be destroyed. Note that destroyed
player objects can not be recovered by the @recover command. player objects can not be recovered by the @recover command.
(See also @create and @open.)
""" """
source_object = command.source_object source_object = command.source_object

View file

@ -133,15 +133,20 @@ class ObjectManager(models.Manager):
except IndexError: except IndexError:
return None return None
def global_object_name_search(self, ostring, exact_match=False): def global_object_name_search(self, ostring, exact_match=False, limit_types=[]):
""" """
Searches through all objects for a name match. Searches through all objects for a name match.
limit_types is a list of types as defined in defines_global.
""" """
if self.is_dbref(ostring):
return [self.dbref_search(ostring, limit_types=limit_types)]
if exact_match: if exact_match:
o_query = self.filter(name__iexact=ostring) o_query = self.filter(name__iexact=ostring)
else: else:
o_query = self.filter(name__icontains=ostring) o_query = self.filter(name__icontains=ostring)
if limit_types:
o_query = o_query.include(type__in=limit_types)
return o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE, return o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE,
defines_global.OTYPE_GOING]) defines_global.OTYPE_GOING])

View file

@ -2,6 +2,7 @@
This is where all of the crucial, core object models reside. This is where all of the crucial, core object models reside.
""" """
import re import re
import traceback
try: import cPickle as pickle try: import cPickle as pickle
except ImportError: import pickle except ImportError: import pickle
@ -603,12 +604,16 @@ class Object(models.Model):
attrib: (str) The attribute's name. attrib: (str) The attribute's name.
""" """
if self.has_attribute(attrib): if self.has_attribute(attrib):
attrib = Attribute.objects.filter(attr_object=self).filter(attr_name=attrib)[0] try:
attrib = Attribute.objects.filter(attr_object=self).filter(attr_name=attrib)[0]
except:
# safety, if something goes wrong (like unsynced db), catch it.
logger.log_errmsg(traceback.print_exc())
return default
return attrib.get_value() return attrib.get_value()
else: else:
return default return default
def get_attribute_obj(self, attrib): def get_attribute_obj(self, attrib):
""" """
Returns the attribute object matching the specified name. Returns the attribute object matching the specified name.