diff --git a/evennia/trunk/ansi.py b/evennia/trunk/ansi.py index 4d76485ffe..9916aa3089 100755 --- a/evennia/trunk/ansi.py +++ b/evennia/trunk/ansi.py @@ -41,14 +41,23 @@ ansi["return"] = "\n\r" ansi["tab"] = "\t" ansi["space"] = " " -def parse_ansi(string, strip_ansi=False): +def parse_ansi(string, strip_ansi=False, strip_formatting=False): """ Parses a string, subbing color codes as needed. """ + if strip_formatting: + char_return = "" + char_tab = "" + char_space = "" + else: + char_return = ansi["return"] + char_tab = ansi["tab"] + char_space = ansi["space"] + ansi_subs = [ - (r'%r', ansi["return"]), - (r'%t', ansi["tab"]), - (r'%b', ansi["space"]), + (r'%r', char_return), + (r'%t', char_tab), + (r'%b', char_space), (r'%cf', ansi["blink"]), (r'%ci', ansi["inverse"]), (r'%ch', ansi["hilite"]), @@ -77,5 +86,9 @@ def parse_ansi(string, strip_ansi=False): string = p.sub("", string) else: string = p.sub(sub[1], string) - - return '%s%s' % (string, ansi["normal"]) + + if strip_ansi: + return '%s' % (string) + else: + return '%s%s' % (string, ansi["normal"]) + diff --git a/evennia/trunk/apps/objects/models.py b/evennia/trunk/apps/objects/models.py index cfa3716e99..d22174559d 100755 --- a/evennia/trunk/apps/objects/models.py +++ b/evennia/trunk/apps/objects/models.py @@ -1,6 +1,7 @@ from django.db import models from django.contrib.auth.models import User import global_defines +import ansi class Attribute(models.Model): """ @@ -96,11 +97,19 @@ class Object(models.Model): else: return profile[0].is_superuser + def set_home(self, new_home): + """ + Sets an object's home. + """ + self.home = new_home + self.save() + def set_name(self, new_name): """ Rename an object. """ - self.name = new_name + self.name = ansi.parse_ansi(new_name, strip_ansi=True) + self.ansi_name = ansi.parse_ansi(new_name, strip_formatting=True) self.save() # If it's a player, we need to update their user object as well. @@ -108,12 +117,40 @@ class Object(models.Model): pobject = User.objects.get(id=self.id) pobject.name = new_name pobject.save() - - def get_name(self): + + def set_description(self, new_desc): + """ + Rename an object. + """ + self.description = ansi.parse_ansi(new_desc) + self.save() + + def get_name(self, fullname=False): """ Returns an object's name. """ - return self.name + if fullname: + return ansi.parse_ansi(self.name, strip_ansi=True) + else: + return ansi.parse_ansi(self.name.split(';')[0], strip_ansi=True) + + def get_ansiname(self, fullname=False): + """ + Returns an object's ANSI'd name. + """ + if fullname: + return ansi.parse_ansi(self.ansi_name) + else: + return ansi.parse_ansi(self.ansi_name.split(';')[0]) + + def get_description(self): + """ + Returns an object's ANSI'd description. + """ + try: + return ansi.parse_ansi(self.description) + except: + return None def get_flags(self): """ @@ -457,7 +494,7 @@ class Object(models.Model): return type_string def __str__(self): - return "%s(#%d%s)" % (self.name, self.id, self.flag_string()) + return "%s(#%d%s)" % (self.get_ansiname(), self.id, self.flag_string()) import functions_db import session_mgr diff --git a/evennia/trunk/commands_general.py b/evennia/trunk/commands_general.py index 983032dfd3..b95a2146a5 100644 --- a/evennia/trunk/commands_general.py +++ b/evennia/trunk/commands_general.py @@ -53,14 +53,12 @@ def cmd_look(cdat): else: target_obj = results[0] - retval = "%s%s%s(#%i%s)%s\r\n%s" % ( + retval = "%s%s(#%i%s)\r\n%s" % ( + target_obj.get_ansiname(), ansi["normal"], - ansi["hilite"], - target_obj.name, target_obj.id, target_obj.flag_string(), - ansi["normal"], - target_obj.description, + target_obj.get_description(), ) session.msg(retval) @@ -114,13 +112,11 @@ def cmd_examine(cdat): else: target_obj = results[0] - session.msg("%s%s%s(#%i%s)%s" % ( + session.msg("%s%s(#%i%s)" % ( + target_obj.get_ansiname(fullname=True), ansi["normal"], - ansi["hilite"], - target_obj.name, target_obj.id, target_obj.flag_string(), - ansi["normal"], )) session.msg("Type: %s Flags: %s" % (target_obj.get_type(), target_obj.get_flags())) session.msg("Owner: %s " % (target_obj.get_owner(),)) @@ -154,7 +150,11 @@ def cmd_examine(cdat): session.msg('%s' %(exit,)) if not target_obj.is_room(): - session.msg("Home: %s" % (target_obj.get_home(),)) + if target_obj.is_exit(): + session.msg("Destination: %s" % (target_obj.get_home(),)) + else: + session.msg("Home: %s" % (target_obj.get_home(),)) + session.msg("Location: %s" % (target_obj.get_location(),)) def cmd_quit(cdat): diff --git a/evennia/trunk/commands_staff.py b/evennia/trunk/commands_staff.py index 4282e0676c..13f1ee7e93 100644 --- a/evennia/trunk/commands_staff.py +++ b/evennia/trunk/commands_staff.py @@ -3,6 +3,7 @@ import functions_general import commands_general import cmdhandler import session_mgr +import ansi from apps.objects.models import Object """ Staff commands may be a bad description for this file, but it'll do for @@ -61,6 +62,37 @@ def cmd_destroy(cdat): session.msg("You destroy %s." % (target_obj,)) target_obj.destroy() +def cmd_description(cdat): + """ + Set an object's description. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + eq_args = ' '.join(args).split('=') + searchstring = ''.join(eq_args[0]) + + if len(args) == 0: + session.msg("What do you want to describe?") + elif len(eq_args) < 2: + session.msg("How would you like to describe that object?") + else: + results = functions_db.local_and_global_search(pobject, searchstring) + + if len(results) > 1: + session.msg("More than one match found (please narrow target):") + for result in results: + session.msg(" %s" % (result,)) + return + elif len(results) == 0: + session.msg("I don't see that here.") + return + else: + new_desc = '='.join(eq_args[1:]) + target_obj = results[0] + session.msg("%s - DESCRIPTION set." % (target_obj,)) + target_obj.set_description(new_desc) + def cmd_name(cdat): """ Handle naming an object. @@ -91,7 +123,7 @@ def cmd_name(cdat): else: newname = '='.join(eq_args[1:]) target_obj = results[0] - session.msg("You have renamed %s to %s." % (target_obj,newname)) + session.msg("You have renamed %s to %s." % (target_obj, ansi.parse_ansi(newname, strip_formatting=True))) target_obj.set_name(newname) def cmd_dig(cdat): @@ -176,7 +208,8 @@ def cmd_open(cdat): # an un-linked exit, @open . if len(eq_args) > 1: # Opening an exit to another location via @open =[,]. - destination = functions_db.local_and_global_search(pobject, eq_args[1]) + comma_split = eq_args[1].split(',') + destination = functions_db.local_and_global_search(pobject, comma_split[0]) if len(destination) == 0: session.msg("I can't find the location to link to.") @@ -184,21 +217,114 @@ def cmd_open(cdat): elif len(destination) > 1: session.msg("Multiple results returned for exit destination!") else: + destination = destination[0] if destination.is_exit(): session.msg("You can't open an exit to an exit!") return - session.msg("You open the exit.") - #victim[0].move_to(server, destination[0]) + + odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":destination} + new_object = functions_db.create_object(odat) - # Create the object and stuff. + session.msg("You open the exit - %s" % (new_object,)) + if len(comma_split) > 1: + second_exit_name = ','.join(comma_split[1:]) + odat = {"name": second_exit_name, "type": 4, "location": destination, "owner": pobject, "home": pobject.get_location()} + new_object = functions_db.create_object(odat) else: # Create an un-linked exit. - odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject} + odat = {"name": exit_name, "type": 4, "location": pobject.get_location(), "owner": pobject, "home":None} new_object = functions_db.create_object(odat) - session.msg("You create a new thing: %s" % (new_object,)) + session.msg("You open an unlinked exit - %s" % (new_object,)) +def cmd_link(cdat): + """ + Sets an object's home or an exit's destination. + + Forms: + @link = + """ + session = cdat['session'] + pobject = session.get_pobject() + server = cdat['server'] + args = cdat['uinput']['splitted'][1:] + + if len(args) == 0: + session.msg("Link what?") + return + + eq_args = args[0].split('=') + target_name = eq_args[0] + dest_name = '='.join(eq_args[1:]) + + if len(target_name) == 0: + session.msg("What do you want to link?") + return + + if len(eq_args) > 1: + target = functions_db.local_and_global_search(pobject, target_name) + + if len(target) == 0: + session.msg("I can't find the object you want to link.") + return + elif len(target) > 1: + session.msg("Multiple results returned for link target.") + return + + # We know we can get the first entry now. + target = target[0] + + # If we do something like "@link blah=", we unlink the object. + if len(dest_name) == 0: + target.set_home(None) + session.msg("You have unlinked %s." % (target,)) + return + + destination = functions_db.local_and_global_search(pobject, dest_name) + + if len(destination) == 0: + session.msg("I can't find the location to link to.") + return + elif len(destination) > 1: + session.msg("Multiple results returned for destination.") + return + + destination = destination[0] + target.set_home(destination) + session.msg("You link %s to %s." % (target,destination)) + + else: + # We haven't provided a target. + session.msg("You must provide a destination to link to.") + return + +def cmd_unlink(cdat): + """ + Unlinks an object. + """ + session = cdat['session'] + pobject = session.get_pobject() + args = cdat['uinput']['splitted'][1:] + + if len(args) == 0: + session.msg("Unlink what?") + return + else: + results = functions_db.local_and_global_search(pobject, ' '.join(args)) + + if len(results) > 1: + session.msg("More than one match found (please narrow target):") + for result in results: + session.msg(" %s" % (result,)) + return + elif len(results) == 0: + session.msg("I don't see that here.") + return + else: + results[0].set_home(None) + session.msg("You have unlinked %s." % (results[0],)) + def cmd_teleport(cdat): """ Teleports an object somewhere. diff --git a/evennia/trunk/functions_db.py b/evennia/trunk/functions_db.py index ba43691ef5..2ba7faa3c5 100644 --- a/evennia/trunk/functions_db.py +++ b/evennia/trunk/functions_db.py @@ -133,8 +133,8 @@ def create_object(odat): else: new_object = Object() - new_object.name = odat["name"] new_object.type = odat["type"] + new_object.set_name(odat["name"]) # If this is a player, we don't want him owned by anyone. # The get_owner() function will return that the player owns @@ -150,10 +150,13 @@ def create_object(odat): # If we have a 'home' key, use that for our home value. Otherwise use # the location key. - if odat.get("home",False): + if odat.has_key("home"): new_object.home = odat["home"] else: - new_object.home = odat["location"] + if new_object.is_exit(): + new_object.home = None + else: + new_object.home = odat["location"] new_object.save() new_object.move_to(odat['location']) diff --git a/evennia/trunk/functions_general.py b/evennia/trunk/functions_general.py index 777e91659d..4945077cce 100644 --- a/evennia/trunk/functions_general.py +++ b/evennia/trunk/functions_general.py @@ -79,3 +79,20 @@ def announce_all(message, with_ann_prefix=True, with_nl=True): for session in session_mgr.get_session_list(): session.msg_no_nl('%s %s%s' % (prefix, message,newline,)) + +def word_wrap(text, width=78): + """ + A word-wrap function that preserves existing line breaks + and most spaces in the text. Expects that existing line + breaks are posix newlines (\n). + + Function originally by Mike Brown + """ + return reduce(lambda line, word, width=width: '%s%s%s' % + (line, + ' \n'[(len(line)-line.rfind('\n')-1 + + len(word.split('\n',1)[0] + ) >= width)], + word), + text.split(' ') + )