diff --git a/evennia/trunk/apps/objects/models.py b/evennia/trunk/apps/objects/models.py index a9c0cc25bd..c80b655391 100755 --- a/evennia/trunk/apps/objects/models.py +++ b/evennia/trunk/apps/objects/models.py @@ -60,6 +60,41 @@ class Object(models.Model): """ BEGIN COMMON METHODS """ + def emit_to(self, message): + """ + Emits something to any sessions attached to the object. + + message: (str) The message to send + """ + + def is_staff(self): + """ + Returns TRUE if the object is a staff player. + """ + if not self.is_player(): + return False + + profile = User.objects.filter(id=self.id) + + if len(profile) == 0: + return False + else: + return profile[0].is_staff + + def is_superuser(self): + """ + Returns TRUE if the object is a super user player. + """ + if not self.is_player(): + return False + + profile = User.objects.filter(id=self.id) + + if len(profile) == 0: + return False + else: + return profile[0].is_superuser + def set_name(self, new_name): """ Rename an object. @@ -112,13 +147,45 @@ class Object(models.Model): """ attribs = Attribute.objects.filter(object=self) return attribs - - def delete(self, server): + + def destroy(self, session_list): """ - Deletes an object. + Destroys an object, sets it to GOING. Can still be recovered + if the user decides to. - server: (Server) Reference to the server object. + session_list: (list) The server's session_list attribute. """ + + # See if we need to kick the player off. + session = functions_db.session_from_object(session_list, self) + if session: + session.msg("You have been destroyed, goodbye.") + session.handle_close() + + # If the object is a player, set the player account object to inactive. + # It can still be recovered at this point. + if self.is_player(): + print 'PLAYER' + uobj = User.objects.get(id=self.id) + print 'VICTIM', uobj + uobj.is_active = False + uobj.save() + + # Set the object type to GOING + self.type = 5 + self.save() + + def delete(self, session_list): + """ + Deletes an object permanently. Marks it for re-use by a new object. + + session_list: (list) The server's session_list attribute. + """ + # Delete the associated player object permanently. + uobj = User.objects.filter(id=self.id) + if len(uobj) > 0: + uobj[0].delete() + # Set the object to type GARBAGE. self.type = 6 self.save() @@ -177,8 +244,8 @@ class Object(models.Model): if value == False and has_flag: # Clear the flag. - if functions_db.not_saved_flag(flag): - # Not a savable flag. + if functions_db.is_unsavable_flag(flag): + # Not a savable flag (CONNECTED, etc) flags = self.nosave_flags.split() flags.remove(flag) self.nosave_flags = ' '.join(flags) @@ -197,8 +264,8 @@ class Object(models.Model): pass else: # Setting a flag. - if functions_db.not_saved_flag(flag): - # Not a savable flag. + if functions_db.is_unsavable_flag(flag): + # Not a savable flag (CONNECTED, etc) flags = self.nosave_flags.split() flags.append(flag) self.nosave_flags = ' '.join(flags) @@ -231,7 +298,7 @@ class Object(models.Model): """ return self.location - def get_attribute_value(self, attrib): + def get_attribute_value(self, attrib, default=False): """ Returns the value of an attribute on an object. @@ -242,7 +309,10 @@ class Object(models.Model): attrib_value = attrib[0].value return attrib_value.value else: - return False + if default: + return default + else: + return False def get_attribute_obj(self, attrib): """ diff --git a/evennia/trunk/commands_general.py b/evennia/trunk/commands_general.py index 0ca2b81999..50f90519ab 100644 --- a/evennia/trunk/commands_general.py +++ b/evennia/trunk/commands_general.py @@ -2,12 +2,31 @@ import settings import time import functions_general import functions_db +import global_defines from ansi import * """ Generic command module. Pretty much every command should go here for now. """ +def cmd_inventory(cdat): + """ + Shows a player's inventory. + """ + session = cdat['session'] + pobject = session.get_pobject() + session.msg("You are carrying:") + + for item in pobject.get_contents(): + session.msg(" %s" % (item,)) + + money = pobject.get_attribute_value("MONEY", default=0) + if money > 0: + money_name = functions_db.get_server_config("MONEY_NAME_PLURAL") + else: + money_name = functions_db.get_server_config("MONEY_NAME_SINGULAR") + + session.msg("You have %d %s." % (money,money_name)) def cmd_look(cdat): """ @@ -16,7 +35,7 @@ def cmd_look(cdat): session = cdat['session'] pobject = session.get_pobject() args = cdat['uinput']['splitted'][1:] - + if len(args) == 0: target_obj = pobject.get_location() else: @@ -49,10 +68,10 @@ def cmd_look(cdat): con_exits = [] for obj in target_obj.get_contents(): - if obj.is_player: + if obj.is_player(): if obj != pobject: con_players.append(obj) - elif obj.is_exit: + elif obj.is_exit(): con_exits.append(obj) else: con_things.append(obj) @@ -62,7 +81,7 @@ def cmd_look(cdat): for player in con_players: session.msg('%s' %(player,)) if con_things: - session.msg("%sThings:%s" % (ansi["hilite"], ansi["normal"],)) + session.msg("%sContents:%s" % (ansi["hilite"], ansi["normal"],)) for thing in con_things: session.msg('%s' %(thing,)) if con_exits: diff --git a/evennia/trunk/commands_staff.py b/evennia/trunk/commands_staff.py index 3c4b92152c..ca4eeda24e 100644 --- a/evennia/trunk/commands_staff.py +++ b/evennia/trunk/commands_staff.py @@ -18,6 +18,11 @@ def cmd_destroy(cdat): session = cdat['session'] pobject = session.get_pobject() args = cdat['uinput']['splitted'][1:] + switches = cdat['uinput']['root_chunk'][1:] + switch_override = False + + if "override" in switches: + switch_override = True if len(args) == 0: session.msg("Destroy what?") @@ -34,13 +39,27 @@ def cmd_destroy(cdat): session.msg("I don't see that here.") return elif results[0].is_player(): - session.msg("You must @nuke players, not @destroy them.") + if pobject.id == results[0].id: + session.msg("You can't destroy yourself.") + return + if not switch_override: + session.msg("You must use @destroy/override on players.") + return + if results[0].is_superuser(): + session.msg("You can't destroy a superuser.") + return + target_obj = results[0] + elif results[0].is_going(): + session.msg("That object is already destroyed.") + return + elif results[0].is_garbage(): + session.msg("That object is already destroyed.") return else: target_obj = results[0] session.msg("You destroy %s." % (target_obj,)) - target_obj.delete(session.server) + target_obj.destroy(session.server.session_list) def cmd_name(cdat): """ @@ -90,7 +109,7 @@ def cmd_dig(cdat): else: # Create and set the object up. odat = {"name": roomname, "type": 2, "location": None, "owner": pobject} - new_object = functions_db.create_object(server, odat) + new_object = functions_db.create_object(odat) session.msg("You create a new room: %s" % (new_object,)) @@ -109,7 +128,7 @@ def cmd_create(cdat): else: # Create and set the object up. odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject} - new_object = functions_db.create_object(server, odat) + new_object = functions_db.create_object(odat) session.msg("You create a new thing: %s" % (new_object,)) @@ -118,10 +137,12 @@ def cmd_nextfree(cdat): Returns the next free object number. """ session = cdat['session'] - server = cdat['server'] nextfree = functions_db.get_nextfree_dbnum() - retval = "Next free object number: #%s" % (nextfree,) + if str(nextfree).isdigit(): + retval = "Next free object number: #%s" % (nextfree,) + else: + retval = "Next free object number: #%s (GARBAGE)" % (nextfree.id,) session.msg(retval) @@ -174,7 +195,7 @@ def cmd_open(cdat): else: # Create an un-linked exit. odat = {"name": thingname, "type": 3, "location": pobject, "owner": pobject} - new_object = functions_db.create_object(server, odat) + new_object = functions_db.create_object(odat) session.msg("You create a new thing: %s" % (new_object,)) @@ -291,7 +312,7 @@ def cmd_set(cdat): attrib_value = eq_args[1][splicenum:] # In global_defines.py, see NOSET_ATTRIBS for protected attribute names. - if not functions_db.modifiable_attrib(attrib_name): + if not functions_db.is_modifiable_attrib(attrib_name): session.msg("You can't modify that attribute.") return @@ -313,14 +334,14 @@ def cmd_set(cdat): if flag[0] == '!': # We're un-setting the flag. flag = flag[1:] - if not functions_db.modifiable_flag(flag): + if not functions_db.is_modifiable_flag(flag): session.msg("You can't set/unset the flag - %s." % (flag,)) else: session.msg('%s - %s cleared.' % (victim.get_name(), flag.upper(),)) victim.set_flag(flag, False) else: # We're setting the flag. - if not functions_db.modifiable_flag(flag): + if not functions_db.is_modifiable_flag(flag): session.msg("You can't set/unset the flag - %s." % (flag,)) else: session.msg('%s - %s set.' % (victim.get_name(), flag.upper(),)) diff --git a/evennia/trunk/functions_db.py b/evennia/trunk/functions_db.py index c80209f2f3..91a8d4733e 100644 --- a/evennia/trunk/functions_db.py +++ b/evennia/trunk/functions_db.py @@ -2,15 +2,22 @@ import sets from django.db import connection from django.contrib.auth.models import User from apps.objects.models import Object +from apps.config.models import ConfigValue import global_defines -def not_saved_flag(flagname): +def get_server_config(configname): """ - Returns TRUE if the flag is not a savable flag. + Returns a server config value. + """ + return ConfigValue.objects.get(conf_key=configname).conf_value + +def is_unsavable_flag(flagname): + """ + Returns TRUE if the flag is an unsavable flag. """ return flagname in global_defines.NOSAVE_FLAGS -def modifiable_flag(flagname): +def is_modifiable_flag(flagname): """ Check to see if a particular flag is modifiable. """ @@ -19,7 +26,7 @@ def modifiable_flag(flagname): else: return False -def modifiable_attrib(attribname): +def is_modifiable_attrib(attribname): """ Check to see if a particular attribute is modifiable. """ @@ -31,18 +38,22 @@ def modifiable_attrib(attribname): def get_nextfree_dbnum(): """ Figure out what our next free database reference number is. + + If we need to recycle a GARBAGE object, return the object to recycle + Otherwise, return the first free dbref. """ # First we'll see if there's an object of type 6 (GARBAGE) that we # can recycle. nextfree = Object.objects.filter(type__exact=6) if nextfree: # We've got at least one garbage object to recycle. - #return nextfree.id - return nextfree[0].id + print 'GARB' + return nextfree[0] else: # No garbage to recycle, find the highest dbnum and increment it # for our next free. - return Object.objects.order_by('-id')[0].id + 1 + print 'NOTGARB' + return int(Object.objects.order_by('-id')[0].id + 1) def list_search_object_namestr(searchlist, ostring, dbref_only=False): """ @@ -96,8 +107,11 @@ def is_dbref(dbstring): def session_from_object(session_list, targobject): """ Return the session object given a object (if there is one open). + + session_list: (list) The server's session_list attribute. + targobject: (Object) The object to match. """ - results = [prospect for prospect in session_list if prospect.get_pobject() == targobject] + results = [prospect for prospect in session_list if prospect.get_pobject().id == targobject.id] if results: return results[0] else: @@ -106,6 +120,8 @@ def session_from_object(session_list, targobject): def session_from_dbref(session_list, dbstring): """ Return the session object given a dbref (if there is one open). + + dbstring: (int) The dbref number to match against. """ if is_dbref(dbstring): results = [prospect for prospect in session_list if prospect.get_pobject().dbref_match(dbstring)] @@ -120,7 +136,7 @@ def get_object_from_dbref(dbref): """ return Object.objects.get(id=dbref) -def create_object(server, odat): +def create_object(odat): """ Create a new object. odat is a dictionary that contains the following keys. REQUIRED KEYS: @@ -132,7 +148,13 @@ def create_object(server, odat): * home: Reference to another object to home to. If not specified, use location key for home. """ - new_object = Object() + next_dbref = get_nextfree_dbnum() + if not str(next_dbref).isdigit(): + # Recycle a garbage object. + new_object = next_dbref + else: + new_object = Object() + new_object.name = odat["name"] new_object.type = odat["type"] @@ -154,8 +176,6 @@ def create_object(server, odat): new_object.home = odat["location"] new_object.save() - - # Add the object to our server's dictionary of objects. new_object.move_to(odat['location']) return new_object @@ -189,7 +209,7 @@ def create_user(cdat, uname, email, password): # Create a player object of the same ID in the Objects table. odat = {"id": uid, "name": uname, "type": 1, "location": start_room_obj, "owner": None} - user_object = create_object(server, odat) + user_object = create_object(odat) # Activate the player's session and set them loose. session.login(user) diff --git a/evennia/trunk/global_defines.py b/evennia/trunk/global_defines.py index 9dae2219a3..4fd49390d5 100644 --- a/evennia/trunk/global_defines.py +++ b/evennia/trunk/global_defines.py @@ -20,4 +20,4 @@ NOSAVE_FLAGS = ["CONNECTED"] NOSET_FLAGS = ["CONNECTED"] # These attribute names can't be modified by players. -NOSET_ATTRIBS = ["TEST"] +NOSET_ATTRIBS = ["MONEY"] diff --git a/evennia/trunk/server.py b/evennia/trunk/server.py index 7959b94861..c1a2f96631 100755 --- a/evennia/trunk/server.py +++ b/evennia/trunk/server.py @@ -10,6 +10,7 @@ from apps.objects.models import Object, Attribute from scheduler import Scheduler import functions_db import functions_general +import global_defines class Server(dispatcher): """ @@ -38,6 +39,7 @@ class Server(dispatcher): self.bind(('', int(self.configvalue['site_port']))) self.listen(100) self.start_time = time.time() + print ' %s started on port %s.' % (self.configvalue['site_name'], self.configvalue['site_port'],) print '-'*50 diff --git a/evennia/trunk/sessions.py b/evennia/trunk/sessions.py index 1169a096b5..0561187edd 100755 --- a/evennia/trunk/sessions.py +++ b/evennia/trunk/sessions.py @@ -61,7 +61,7 @@ class PlayerSession(async_chat): async_chat.handle_close(self) self.logged_in = False self.server.remove_session(self) - print 'Sessions active:', len(self.server.session_list) + print 'Sessions active:', len(self.server.get_session_list()) def get_pobject(self): """