Added gamesrc/utils.py as a convenient shorthand for often-used methods from the engine

Added a @deluser command and gave it and @boot an option to give a reason for booting/deleting a player
Fixed a bug in @dig that confused exit directions in text
Small bug fixes
/Griatch
This commit is contained in:
Griatch 2009-12-20 20:51:26 +00:00
parent 81bec61d7d
commit df29defbcd
8 changed files with 239 additions and 28 deletions

View file

@ -11,6 +11,7 @@ as 'game.gamesrc.commands.examples.misc_tests'.
None of these commands are auto-added to the help database
(they have no docstrings) in order to help make it clean.
"""
from src.cmdtable import GLOBAL_CMD_TABLE
#------------------------------------------------------------

123
game/gamesrc/utils.py Normal file
View file

@ -0,0 +1,123 @@
"""
This module offers a collection of useful general functions from the
game engine to make things easier to find.
Just import game.gamesrc.utils and refer to the globals defined herein.
Note that this is not intended as a comprehensive collection, merely
a convenient place to refer to for the methods we have found to be
often used. You will still have to refer to the modules
in evennia/src for more specialized operations.
You will also want to be well familiar with all the facilities each
object offers. The object model is defined in src/objects/models.py.
"""
#------------------------------------------------------------
# imports
#------------------------------------------------------------
from django.conf import settings as in_settings
from src import logger
from src import scheduler as in_scheduler
from src.objects.models import Object
from src import defines_global
from src.cmdtable import GLOBAL_CMD_TABLE as in_GLOBAL_CMD_TABLE
from src.statetable import GLOBAL_STATE_TABLE as in_GLOBAL_STATE_TABLE
from src.events import IntervalEvent as in_IntervalEvent
#------------------------------------------------------------
# Import targets
#------------------------------------------------------------
settings = in_settings
GLOBAL_CMD_TABLE = in_GLOBAL_CMD_TABLE
GLOBAL_STATE_TABLE = in_GLOBAL_STATE_TABLE
# Events
scheduler = in_scheduler
IntervalEvent = in_IntervalEvent
#------------------------------------------------------------
# Log to file/stdio
# log_xxxmsg(msg)
#------------------------------------------------------------
log_errmsg = logger.log_errmsg
log_warnmsg = logger.log_warnmsg
log_infomsg = logger.log_infomsg
#------------------------------------------------------------
# Search methods
#------------------------------------------------------------
# NOTE: All objects also has search_for_object() defined
# directly on themselves, which is a convenient entryway into a
# local and global search with automatic feedback to the
# calling player.
# def get_object_from_dbref(dbref):
# Returns an object when given a dbref.
get_object_from_dbref = Object.objects.get_object_from_dbref
# def dbref_search(dbref_string, limit_types=False):
# Searches for a given dbref.
dbref_search = Object.objects.dbref_search
# def global_object_name_search(ostring, exact_match=True, limit_types=[]):
# Searches through all objects for a name match.
global_object_name_search = Object.objects.global_object_name_search
# def global_object_script_parent_search(script_parent):
# Searches through all objects returning those which has a certain script parent.
global_object_script_parent_search = Object.objects.global_object_script_parent_search
# def player_name_search(searcher, ostring):
# Search players by name.
player_name_search = Object.objects.player_name_search
# def local_and_global_search(searcher, ostring, search_contents=True,
# search_location=True, dbref_only=False,
# limit_types=False, attribute_name=None):
# Searches an object's location then globally for a dbref or name match.
local_and_global_search = Object.objects.local_and_global_search
#------------------------------------------------------------
# Creation commands
#------------------------------------------------------------
# def create_object(name, otype, location, owner, home=None, script_parent=None):
# Create a new object
create_object = Object.objects.create_object
# def copy_object(original_object, new_name=None, new_location=None, reset=False):
# Create and return a new object as a copy of the source object. All will
# be identical to the original except for the dbref. Does not allow the
# copying of Player objects.
copy_object = Object.objects.copy_object
#------------------------------------------------------------
# Validation
#------------------------------------------------------------
# NOTE: The easiest way to check if an object
# is of a particular type is to use each object's
# is_X() function, like is_superuser(), is_thing(),
# is_room(), is_player(), is_exit() and get_type().
OTYPE_NOTHING = defines_global.OTYPE_NOTHING
OTYPE_PLAYER = defines_global.OTYPE_PLAYER
OTYPE_ROOM = defines_global.OTYPE_ROOM
OTYPE_THING = defines_global.OTYPE_THING
OTYPE_EXIT = defines_global.OTYPE_EXIT
OTYPE_GOING = defines_global.OTYPE_GOING
TYPE_GARBAGE = defines_global.OTYPE_GARBAGE
NOPERMS_MSG = defines_global.NOPERMS_MSG
NOCONTROL_MSG = defines_global.NOCONTROL_MSG
# def is_dbref(self, dbstring, require_pound=True):
# Is the input a well-formed dbref number?
is_dbref = Object.objects.is_dbref

View file

@ -1085,7 +1085,7 @@ def cmd_dig(command):
else:
ptext += " of default type (parent '%s' failed!)" % script_parent
source_object.emit_to("Created exit%s back from %s to %s named '%s'." % \
(ptext, destination, location, new_object))
(ptext, location, destination, new_object))
if new_room and 'teleport' in switches:
source_object.move_to(new_room)

View file

@ -3,7 +3,7 @@ This file contains commands that require special permissions to use. These
are generally @-prefixed commands, but there are exceptions.
"""
from django.contrib.auth.models import Permission, Group
from django.contrib.auth.models import Permission, Group, User
from django.conf import settings
from src.objects.models import Object
from src import session_mgr
@ -79,9 +79,14 @@ def cmd_boot(command):
@boot
Usage
@boot <player obj>
@boot[/switches] <player obj> [: reason]
Switches:
quiet - Silently boot without informing player
port - boot by port number instead of name or dbref
Boot a player object from the server.
Boot a player object from the server. If a reason is
supplied it will be echoed to the user unless /quiet is set.
"""
source_object = command.source_object
switch_quiet = False
@ -96,23 +101,27 @@ def cmd_boot(command):
switch_port = True
if not command.command_argument:
source_object.emit_to("Who would you like to boot?")
source_object.emit_to("Usage: @boot[/switches] <player> [:reason]")
return
else:
arg = command.command_argument
reason = ""
if ':' in arg:
arg, reason = [a.strip() for a in arg.split(':',1)]
boot_list = []
if switch_port:
# Boot a particular port.
sessions = session_mgr.get_session_list(True)
for sess in sessions:
# Find the session with the matching port number.
if sess.getClientAddress()[1] == int(command.command_argument):
if sess.getClientAddress()[1] == int(arg):
boot_list.append(sess)
# Match found, kill the loop and continue with booting.
break
else:
# Grab the objects that match
objs = Object.objects.local_and_global_search(source_object,
command.command_argument)
objs = Object.objects.local_and_global_search(source_object, arg)
if not objs:
source_object.emit_to("No name or dbref match found for booting.")
@ -145,7 +154,10 @@ def cmd_boot(command):
# Carry out the booting of the sessions in the boot list.
for boot in boot_list:
if not switch_quiet:
boot.msg("You have been disconnected by %s." % (source_object.name))
msg = "You have been disconnected by %s." % (source_object.name)
if reason:
msg += "\n Reason given:\n '%s'" % reason
boot.msg(msg)
boot.disconnectClient()
session_mgr.remove_session(boot)
return
@ -153,6 +165,54 @@ GLOBAL_CMD_TABLE.add_command("@boot", cmd_boot,
priv_tuple=("genperms.manage_players",),
help_category="Admin")
def cmd_delplayer(command):
"""
delplayer - delete player from server
Usage:
@delplayer <name> [: reason]
Completely deletes a user from the server database,
making their nick and e-mail again available.
"""
source_object = command.source_object
arg = command.command_argument
if not arg:
source_object.emit_to("Usage: @delplayer <player name or #id>")
return
reason = ""
if ':' in arg:
arg, reason = [a.strip() for a in arg.split(':',1)]
objs = Object.objects.local_and_global_search(source_object, arg)
if not objs:
source_object.emit_to("No player object matches found for '%s'." % arg)
return
pobj = objs[0]
if not source_object.controls_other(pobj):
if pobj.is_superuser():
source_object.emit_to("You cannot delete a Superuser.")
return
else:
source_object.emit_to("You do not have permission to delete that player.")
return
# boot the player then delete
source_object.emit_to("Booting and informing player if currently online ...")
name = pobj.get_name()
msg = "\nYour account '%s' is being *permanently* deleted.\n" % name
if reason:
msg += " Reason given:\n '%s'" % reason
pobj.emit_to(msg)
source_object.execute_cmd("@boot %s" % arg)
pobj.delete()
source_object.emit_to("Player %s was successfully deleted." % name)
GLOBAL_CMD_TABLE.add_command("@delplayer", cmd_delplayer,
priv_tuple=("genperms.manage_players",),
help_category="Admin")
def cmd_newpassword(command):
"""
@newpassword

View file

@ -131,7 +131,8 @@ def plr_set_channel_listening(session, alias, listening):
alias: (str) The channel alias.
listening: (bool) A True or False value to determine listening status.
"""
membership = session.pobject.channel_membership_set.get(user_alias=alias)
membership = session.get_pobject().channel_membership_set.get(user_alias=alias)
membership.is_listening = listening
membership.save()
plr_get_cdict(session).get(alias)[1] = listening

View file

@ -64,8 +64,10 @@ class ObjectManager(models.Manager):
"""
Returns an object when given a dbref.
"""
if len(dbref)>1 and dbref[0]=="#":
dbref = dbref[1:]
if type(dbref) == type(str()):
if len(dbref)>1 and dbref[0]=="#":
dbref = dbref[1:]
dbref = "%s" % dbref
try:
return self.get(id=dbref)
except self.model.DoesNotExist:

View file

@ -573,6 +573,11 @@ class Object(models.Model):
# Delete the associated player object permanently.
uobj = User.objects.filter(id=self.id)
if len(uobj) > 0:
# clean out channel memberships
memberships = self.channel_membership_set.filter(listener=self)
for membership in memberships:
membership.delete()
# delete user
uobj[0].delete()
# Set the object to type GARBAGE.
@ -1045,16 +1050,27 @@ class Object(models.Model):
self.emit_to(lock_desc)
else:
self.emit_to("That destination is blocked from you.")
return
# Before the move, call eventual pre-commands.
if self.scriptlink.at_before_move(target) != None:
return
return
source_location = self.location
owner = self.get_owner()
errtxt = "There was a bug in a move_to() scriptlink. Contact an admin.\n"
# Before the move, call eventual pre-commands.
try:
if self.scriptlink.at_before_move(target) != None:
return
except:
owner.emit_to("%s%s" % (errtxt, traceback.print_exc()))
return
if not quiet:
#tell the old room we are leaving
self.scriptlink.announce_move_from(target)
source_location = self.location
try:
self.scriptlink.announce_move_from(target)
except:
owner.emit_to("%s%s" % (errtxt, traceback.print_exc()))
# Perform move
self.location = target
@ -1062,15 +1078,23 @@ class Object(models.Model):
if not quiet:
# Tell the new room we are there.
self.scriptlink.announce_move_to(source_location)
try:
self.scriptlink.announce_move_to(source_location)
except:
owner.emit_to("%s%s" % (errtxt, traceback.print_exc()))
# Execute eventual extra commands on this object after moving it
self.scriptlink.at_after_move()
try:
self.scriptlink.at_after_move(source_location)
except:
owner.emit_to("%s%s" % (errtxt, traceback.print_exc()))
# Perform eventual extra commands on the receiving location
target.scriptlink.at_obj_receive(self)
if force_look and self.is_player():
try:
target.scriptlink.at_obj_receive(self, source_location)
except:
owner.emit_to("%s%s" % (errtxt, traceback.print_exc()))
if force_look and self.is_player():
self.execute_cmd('look')
def dbref_match(self, oname):

View file

@ -109,7 +109,7 @@ class EvenniaBasicObject(object):
if loc.is_player():
loc.emit_to("%s is now in your inventory." % obj.get_name())
def at_after_move(self):
def at_after_move(self, old_loc=None):
"""
This hook is called just after the object was successfully moved.
No return values.
@ -127,7 +127,7 @@ class EvenniaBasicObject(object):
#print "SCRIPT TEST: %s dropped %s." % (pobject, self.scripted_obj)
pass
def at_obj_receive(self, object=None):
def at_obj_receive(self, object=None, old_loc=None):
"""
Called whenever an object is added to the contents of this object.
"""