mirror of
https://github.com/evennia/evennia.git
synced 2026-03-29 12:07:17 +02:00
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:
parent
922a7d5064
commit
9459178c43
8 changed files with 107 additions and 56 deletions
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
2
src/utils/idmapper/MANIFEST.in
Normal file
2
src/utils/idmapper/MANIFEST.in
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
include setup.py README.rst LICENSE MANIFEST.in
|
||||
global-exclude *~
|
||||
35
src/utils/idmapper/README.rst
Normal file
35
src/utils/idmapper/README.rst
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue