Fixed character swap mechanisms. Created an example command @puppet for switching control between characters (note that it does not currently check permissions, nor make sure the target has the appropriate cmdsets).

This commit is contained in:
Griatch 2010-10-18 21:07:26 +00:00
parent 922a7d5064
commit 9459178c43
8 changed files with 107 additions and 56 deletions

View file

@ -75,6 +75,7 @@ class DefaultCmdSet(CmdSet):
self.add(objmanip.CmdDestroy())
self.add(objmanip.CmdExamine())
self.add(objmanip.CmdTypeclass())
self.add(objmanip.CmdPuppet())
# Comm commands
self.add(comms.CmdAddCom())

View file

@ -1635,3 +1635,35 @@ class CmdTypeclass(MuxCommand):
string += "same-named attributes on the existing object."
caller.msg(string)
class CmdPuppet(MuxCommand):
"""
Switch control to an object
Usage:
@puppet <character object>
This will attempt to "become" a different character. Note that this command does not check so that
the target object has the appropriate cmdset. You cannot puppet a character that is already "taken".
"""
key = "@puppet"
permissions = "cmd:puppet"
help_category = "Admin"
def func(self):
"""
Simple puppet method (does not check permissions)
"""
caller = self.caller
if not self.args:
caller.msg("Usage: @puppet <character>")
return
player = caller.player
new_character = caller.search(self.args)
if not new_character:
return
if player.swap_character(new_character):
new_character.msg("You now control %s." % new_character.name)
else:
caller.msg("You couldn't control %s." % new_character.name)

View file

@ -343,58 +343,3 @@ class ObjectManager(TypedObjectManager):
new_object.attr(attr.attr_name, attr.value)
return new_object
#
# ObjectManager User control
#
def user_swap_object(self, uid, new_obj_id, delete_old_obj=False):
"""
This moves the user from one database object to another.
The new object must already exist.
delete_old_obj (bool) - Delete the user's old dbobject.
This is different from ObjectDB.swap_type() since it actually
swaps the database object the user is connected to, rather
than change any typeclass on the same dbobject. This means
that the old object (typeclass and all) can remain unchanged
in-game except it is now not tied to any user.
Note that the new object will be unchanged, the only
difference is that its 'user' property is set to the
user. No other initializations are done here, such as
setting the default cmdset - this has to be done
separately when calling this method.
This method raises Exceptions instead of logging feedback
since this is a method which might be very useful to embed in
your own game implementation.
Also note that this method don't check any permissions beyond
making sure no other user is connected to the object before
swapping.
"""
# get the objects.
try:
user = User.get(uid)
new_obj = self.get(new_obj_id)
except:
raise Exception("OBJ_FIND_ERROR")
# check so the new object is not already controlled.
if new_obj.user:
if new_obj.user == user:
raise Exception("SELF_CONTROL_ERROR")
else:
raise Exception("CONTROL_ERROR")
# set user to new object.
new_obj.user = user
new_obj.save()
# get old object, sets its user to None and/or delete it
for old_obj in self.get_object_with_user(uid):
if delete_old_obj:
old_obj.delete()
else:
old_obj.user = None
old_obj.save()

View file

@ -76,7 +76,7 @@ class ObjectDB(TypedObject):
typeclass - auto-linked typeclass
date_created - time stamp of object creation
permissions - perm strings
dbref - #id of object
Dbref - #id of object
db - persistent attribute storage
ndb - non-persistent attribute storage

View file

@ -156,3 +156,32 @@ class PlayerManager(models.Manager):
if not players:
players = self.filter(user__username=ostring)
return players
def swap_character(self, player, new_character, delete_old_character=False):
"""
This disconnects a player from the current character (if any) and connects
to a new character object.
"""
if new_character.player:
# the new character is already linked to a player!
return False
# do the swap
old_character = player.character
if old_character:
old_character.player = None
try:
player.character = new_character
new_character.player = player
except Exception:
# recover old setup
old_character.player = player
player.character = old_character
return False
if delete_old_character:
old_character.delete()
return True

View file

@ -271,3 +271,10 @@ class PlayerDB(TypedObject):
"""
self.msg(message, from_obj)
def swap_character(self, new_character, delete_old_character=False):
"""
Swaps character, if possible
"""
return self.__class__.objects.swap_character(self, new_character, delete_old_character=delete_old_character)

View file

@ -0,0 +1,2 @@
include setup.py README.rst LICENSE MANIFEST.in
global-exclude *~

View file

@ -0,0 +1,35 @@
Django Identity Mapper
======================
A pluggable Django application which allows you to explicitally mark your models to use an identity mapping pattern. This will share instances of the same model in memory throughout your interpreter.
Please note, that deserialization (such as from the cache) will *not* use the identity mapper.
Usage
-----
To use the shared memory model you simply need to inherit from it (instead of models.Model). This enable all queries (and relational queries) to this model to use the shared memory instance cache, effectively creating a single instance for each unique row (based on primary key) in the queryset.
For example, if you want to simply mark all of your models as a SharedMemoryModel, you might as well just import it as models.
::
from idmapper import models
class MyModel(models.SharedMemoryModel):
name = models.CharField(...)
Because the system is isolated, you may mix and match SharedMemoryModel's with regular Model's.
::
from idmapper import models
class MyModel(models.SharedMemoryModel):
name = models.CharField(...)
fkey = models.ForeignKey('Other')
class Other(models.Model):
name = models.CharField(...)
References
----------
Original code and concept: http://code.djangoproject.com/ticket/17