OBS: You need to resync your database! The Nickname system is now a separate database model with the result that also channel nicks are more robust. Also nickname replacement has been adjusted to fix some exceptional circumstances. Fixed a host of issues in the channel and nick handlers and adjoining commands that caused the channel-syscommands to fail in some situations. Resolves issue131. Resolves issue 132. Resolves issue 134.

This commit is contained in:
Griatch 2011-02-27 22:27:56 +00:00
parent 7ebcefae2e
commit 2bdaf034c8
17 changed files with 298 additions and 305 deletions

View file

@ -109,8 +109,9 @@ def get_and_merge_cmdsets(caller):
exit_cmdset = EXITHANDLER.get_cmdset(caller)
location = caller.location
if location and not caller_cmdset.no_objs:
# Gather all cmdsets stored on objects in the room.
local_objlist = location.contents
# Gather all cmdsets stored on objects in the room and
# also in the caller's inventory
local_objlist = location.contents + caller.contents
local_objects_cmdsets = [obj.cmdset.current
for obj in local_objlist
if obj.cmdset.outside_access]
@ -154,7 +155,7 @@ def match_command(cmd_candidates, cmdset, logged_caller=None):
# Searching possible command matches in the given cmdset
matches = []
prev_found_cmds = [] # to avoid aliases clashing with themselves
for cmd_candidate in cmd_candidates:
for cmd_candidate in cmd_candidates:
cmdmatches = list(set([cmd for cmd in cmdset
if cmd == cmd_candidate.cmdname and
cmd not in prev_found_cmds]))

View file

@ -81,8 +81,7 @@ class DefaultCmdSet(CmdSet):
# Comm commands
self.add(comms.CmdAddCom())
self.add(comms.CmdDelCom())
self.add(comms.CmdComlist())
self.add(comms.CmdClist())
self.add(comms.CmdChannels())
self.add(comms.CmdCdestroy())
self.add(comms.CmdChannelCreate())
self.add(comms.CmdCdesc())

View file

@ -3,38 +3,43 @@ Comsys command module.
"""
from src.comms.models import Channel, Msg, ChannelConnection
from src.comms.channelhandler import CHANNELHANDLER
from src.utils import create, utils
from src.permissions.permissions import has_perm
from src.commands.default.muxcommand import MuxCommand
def find_channel(caller, channelname):
def find_channel(caller, channelname, silent=False):
"""
Helper function for searching for a single channel with
some error handling.
"""
channels = Channel.objects.channel_search(channelname)
if not channels:
caller.msg("Channel '%s' not found." % channelname)
if not silent:
caller.msg("Channel '%s' not found." % channelname)
return None
elif len(channels) > 1:
matches = ", ".join(["%s(%s)" % (chan.key, chan.id) for chan in channels])
caller.msg("Multiple channels match (be more specific): \n%s" % matches)
if not silent:
caller.msg("Multiple channels match (be more specific): \n%s" % matches)
return None
return channels[0]
class CmdAddCom(MuxCommand):
"""
addcom - join a channel with alias
addcom - subscribe to a channel with optional alias
Usage:
addcom [alias=] <channel>
Allows adding an alias for a channel to make is easier and
faster to use. Subsequent calls of this command can
be used to add multiple aliases.
Joins a given channel. If alias is given, this will allow you to
refer to the channel by this alias rather than the full channel
name. Subsequent calls of this command can be used to add multiple
aliases to an already joined channel.
"""
key = "addcom"
aliases = ["aliaschan","chanalias"]
help_category = "Comms"
def func(self):
@ -78,9 +83,7 @@ class CmdAddCom(MuxCommand):
if alias:
# create a nick and add it to the caller.
nicks = caller.nicks
nicks[alias.strip()] = channel.key
caller.nicks = nicks # nicks auto-save to database.
caller.nickhandler(alias, channel.key, nick_type="channel")
string += "You can now refer to the channel %s with the alias '%s'."
caller.msg(string % (channel.key, alias))
else:
@ -90,106 +93,55 @@ class CmdAddCom(MuxCommand):
class CmdDelCom(MuxCommand):
"""
delcom - remove a channel alias
delcom - unsubscribe from channel or remove channel alias
Usage:
delcom <alias>
delcom <alias or channel>
Removes the specified alias to a channel. If this is the last alias,
the user is effectively removed from the channel.
If the full channel name is given, unsubscribe from the
channel. If an alias is given, remove the alias but don't
unsubscribe.
"""
key = "delcom"
aliases = ["delaliaschan, delchanalias"]
help_category = "Comms"
def func(self):
"Implementing the command. "
caller = self.caller
player = caller.player
if not self.args:
caller.msg("Usage: delcom <alias>")
caller.msg("Usage: delcom <alias or channel>")
return
#find all the nicks defining this channel
searchnick = self.args.lower()
nicks = caller.nicks
channicks = [nick for nick in nicks.keys()
if nick == searchnick]
if not channicks:
caller.msg("You don't have any such alias defined.")
return
#if there are possible nick matches, look if they match a channel.
channel = None
for nick in channicks:
channel = find_channel(caller, nicks[nick])
if channel:
break
if not channel:
caller.msg("No channel with alias '%s' found." % searchnick)
return
player = caller.player
ostring = self.args.lower()
if not channel.has_connection(player):
caller.msg("You are not on that channel.")
channel = find_channel(caller, ostring, silent=True)
if channel:
# we have given a channel name - unsubscribe
if not channel.has_connection(player):
caller.msg("You are listening to that channel.")
return
chkey = channel.key.lower()
# find all nicks linked to this channel and delete them
for nick in [nick for nick in caller.nicks
if nick.db_type == "channel" and nick.db_real.lower() == chkey]:
nick.delete()
channel.disconnect_from(player)
caller.msg("You stop listening to channel '%s'. Eventual aliases were removed." % channel.key)
return
else:
if len(channicks) > 1:
del nicks[searchnick]
caller.msg("Your alias '%s' for channel %s was cleared." % (searchnick,
channel.key))
# we are removing a channel nick
channame = caller.nickhandler(ostring, nick_type="channel")
channel = find_channel(caller, channame, silent=True)
if not channel:
caller.msg("No channel with alias '%s' was found." % ostring)
else:
del nicks[searchnick]
channel.disconnect_from(player)
caller.msg("You stop listening to channel '%s'." % channel.key)
# have to save nicks back too
caller.nicks = nicks
class CmdComlist(MuxCommand):
"""
comlist - list channel memberships
Usage:
comlist
Lists the channels a user is subscribed to.
"""
key = "comlist"
aliases = ["channels"]
help_category = "Comms"
def func(self):
"Implement the command"
caller = self.caller
player = caller.player
connections = ChannelConnection.objects.get_all_player_connections(player)
if not connections:
caller.msg("You don't listen to any channels.")
return
# get aliases:
nicks = caller.nicks
channicks = {}
for connection in connections:
channame = connection.channel.key.lower()
channicks[channame] = ", ".join([nick for nick in nicks
if nicks[nick].lower() == channame])
caller.nickhandler(ostring, nick_type="channel", delete=True)
caller.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key))
string = "Your subscribed channels (use @clist for full chan list)\n"
string += "** Alias Channel Status\n"
for connection in connections:
string += " %s%s %-15.14s%-22.15s\n" % ('-', '-',
channicks[connection.channel.key.lower()],
connection.channel.key)
string = string[:-1]
caller.msg(string)
# def cmd_allcom(command):
# """
# allcom - operate on all channels
@ -282,43 +234,74 @@ class CmdComlist(MuxCommand):
## GLOBAL_CMD_TABLE.add_self("clearcom", cmd_clearcom)
class CmdClist(MuxCommand):
class CmdChannels(MuxCommand):
"""
@clist
Usage:
@channels
@clist
list channels
all channels
comlist
Lists all available channels in the game.
Lists all available channels available to you, wether you listen to them or not.
Use 'comlist" to only view your current channel subscriptions.
"""
key = "@clist"
aliases = ["channellist", "all channels"]
key = "@channels"
aliases = ["@clist", "channels", "comlist", "chanlist", "channellist", "all channels"]
help_category = "Comms"
def func(self):
"Implement function"
caller = self.caller
string = "All channels (use comlist to see your subscriptions)\n"
string += "** Channel Perms Description\n"
channels = Channel.objects.get_all_channels()
# all channels we have available to listen to
channels = [chan for chan in Channel.objects.get_all_channels() if has_perm(caller, chan, 'can_listen')]
if not channels:
string += "(No channels) "
for chan in channels:
if has_perm(caller, chan, 'can_listen'):
string += " %s%s %-15.14s%-22.15s%s\n" % \
('-',
'-',
chan.key,
chan.permissions,
#chan.get_owner().get_name(show_dbref=False),
chan.desc)
string = string[:-1]
#s += "** End of Channel List **"
caller.msg("No channels available")
return
# all channel we are already subscribed to
subs = [conn.channel for conn in ChannelConnection.objects.get_all_player_connections(caller.player)]
if self.cmdstring != "comlist":
string = "\nAll available channels:"
cols = [[" "], ["Channel"], ["Aliases"], ["Perms"], ["Description"]]
for chan in channels:
if chan in subs:
cols[0].append(">")
else:
cols[0].append(" ")
cols[1].append(chan.key)
cols[2].append(",".join(chan.aliases))
cols[3].append(",".join(chan.permissions))
cols[4].append(chan.desc)
# put into table
for ir, row in enumerate(utils.format_table(cols)):
if ir == 0:
string += "\n{w" + "".join(row) + "{n"
else:
string += "\n" + "".join(row)
self.caller.msg(string)
string = "\nYour channel subscriptions:"
if not subs:
string += "(None)"
else:
nicks = [nick for nick in caller.nicks if nick.db_type == 'channel']
print nicks
cols = [["Channel"], ["Aliases"], ["Description"]]
for chan in subs:
cols[0].append(chan.key)
cols[1].append(",".join([nick.db_nick for nick in nicks
if nick.db_real.lower() == chan.key.lower()] + chan.aliases))
cols[2].append(chan.desc)
# put into table
for ir, row in enumerate(utils.format_table(cols)):
if ir == 0:
string += "\n{w" + "".join(row) + "{n"
else:
string += "\n" + "".join(row)
caller.msg(string)
class CmdCdestroy(MuxCommand):
@ -349,11 +332,12 @@ class CmdCdestroy(MuxCommand):
caller.msg("You are not allowed to do that.")
return
message = "Channel %s is being destroyed. Make sure to change your aliases." % channel.key
message = "%s is being destroyed. Make sure to change your aliases." % channel
msgobj = create.create_message(caller, message, channel)
channel.msg(msgobj)
channel.delete()
caller.msg("Channel %s was destroyed." % channel)
CHANNELHANDLER.update()
caller.msg("%s was destroyed." % channel)
## def cmd_cset(self):
@ -741,7 +725,7 @@ class CmdPage(MuxCommand):
if 'list' in self.switches:
pages = pages_we_sent + pages_we_got
pages.sort(lambda x,y: cmp(x.date_sent, y.date_sent))
pages.sort(lambda x, y: cmp(x.date_sent, y.date_sent))
number = 10
if self.args:

View file

@ -9,6 +9,7 @@ from src.permissions.models import PermissionGroup
from src.permissions.permissions import has_perm, has_perm_string
from src.objects.models import HANDLE_SEARCH_ERRORS
from src.utils import utils
from src.objects.models import Nick
from src.commands.default.muxcommand import MuxCommand
class CmdHome(MuxCommand):
@ -41,8 +42,9 @@ class CmdLook(MuxCommand):
Usage:
look
look <obj>
look *<player>
Observes your location or objects in your vicinity.
Observes your location or objects in your vicinity.
"""
key = "look"
aliases = ["l"]
@ -56,7 +58,7 @@ class CmdLook(MuxCommand):
if args:
# Use search to handle duplicate/nonexistant results.
looking_at_obj = caller.search(args)
looking_at_obj = caller.search(args, use_nicks=True)
if not looking_at_obj:
return
else:
@ -64,6 +66,9 @@ class CmdLook(MuxCommand):
if not looking_at_obj:
caller.msg("Location: None")
return
if not hasattr(looking_at_obj, 'return_appearance'):
# this is likely due to us having a player instead
looking_at_obj = looking_at_obj.character
# get object's appearance
caller.msg(looking_at_obj.return_appearance(caller))
# the object's at_desc() method.
@ -109,16 +114,18 @@ class CmdNick(MuxCommand):
Define a personal alias/nick
Usage:
alias[/switches] <alias> = [<string>]
nick ''
nick[/switches] <nickname> = [<string>]
alias ''
Switches: obj - alias an object
Switches:
object - alias an object
player - alias a player
clearall - clear all your aliases
list - show all defined aliases
If no switch is given, a command/channel alias is created, used
to replace strings before sending the command.
If no switch is given, a command alias is created, used
to replace strings before sending the command. Give an empty
right-hand side to clear the nick
Creates a personal nick for some in-game object or
string. When you enter that string, it will be replaced
@ -129,8 +136,8 @@ class CmdNick(MuxCommand):
if you want to change the inherent aliases of an object,
use the @alias command instead.
"""
key = "nickname"
aliases = ["nick, @nick, alias"]
key = "nick"
aliases = ["nickname", "nicks", "@nick", "alias"]
def func(self):
"Create the nickname"
@ -138,55 +145,58 @@ class CmdNick(MuxCommand):
caller = self.caller
switches = self.switches
if 'list' in switches:
string = "{wAliases:{n \n"
string = string + "\n\r".join(["%s = %s" % (alias, replace)
for alias, replace
in caller.nicks.items()])
nicks = Nick.objects.filter(db_obj=caller.dbobj).exclude(db_type="channel")
if 'list' in switches or self.cmdstring == "nicks":
string = "{wDefined Nicks:{n"
cols = [["Type"],["Nickname"],["Translates-to"] ]
for nick in nicks:
cols[0].append(nick.db_type)
cols[1].append(nick.db_nick)
cols[2].append(nick.db_real)
for ir, row in enumerate(utils.format_table(cols)):
if ir == 0:
string += "\n{w" + "".join(row) + "{n"
else:
string += "\n" + "".join(row)
caller.msg(string)
return
if 'clearall' in switches:
del caller.nicks
nicks.delete()
caller.msg("Cleared all aliases.")
return
if not self.args or not self.lhs:
caller.msg("Usage: nick[/switches] nickname = [realname]")
return
nick = self.lhs
real = self.rhs
if real == nick:
caller.msg("No point in setting nick same as the string to replace...")
return
if not self.args or not self.lhs:
caller.msg("Usage: alias[/switches] string = [alias]")
return
alias = self.lhs
rstring = self.rhs
err = None
if rstring == alias:
err = "No point in setting alias same as the string to replace..."
caller.msg(err)
return
elif 'obj' in switches:
# object alias, for adressing objects
# (including user-controlled ones)
err = caller.set_nick("_obj:%s" % alias, rstring)
atype = "Object"
elif 'player' in switches:
# player alias, used for messaging
err = caller.set_nick("_player:%s" % alias, rstring)
atype = "Player "
else:
# a command/channel alias - these are replaced if
# they begin a command string.
caller.msg(rstring)
caller.msg("going in: %s %s" % (alias, rstring))
err = caller.set_nick(alias, rstring)
atype = "Command/channel "
if err:
if rstring:
err = "%salias %s changed from '%s' to '%s'." % (atype, alias, err, rstring)
# check so we have a suitable nick type
if not any(True for switch in switches if switch in ("object", "player", "inputline")):
switches = ["inputline"]
string = ""
for switch in switches:
oldnick = Nick.objects.filter(db_obj=caller.dbobj, db_nick__iexact=nick, db_type__iexact=switch)
if not real:
# removal of nick
if oldnick:
# clear the alias
string += "\nNick '%s' (= '%s') was cleared." % (nick, oldnick[0].db_real)
caller.nickhandler(nick, nick_type=switch, delete=True)
else:
string += "\nNo nick '%s' found, so it could not be removed." % nick
else:
err = "Cleared %salias '%s'(='%s')." % (atype, alias, err)
else:
err = "Set %salias '%s' = '%s'" % (atype, alias, rstring)
caller.msg(err.capitalize())
# creating new nick
if oldnick:
string += "\nNick %s changed from '%s' to '%s'." % (nick, oldnick[0].db_real, real)
else:
string += "\nNick set: '%s' = '%s'." % (nick, real)
caller.nickhandler(nick, real, nick_type=switch)
caller.msg(string)
class CmdInventory(MuxCommand):
"""
inventory
@ -362,8 +372,8 @@ class CmdWho(MuxCommand):
plr_pobject = session.get_character()
if show_session_data:
table[0].append(plr_pobject.name[:25])
table[1].append(utils.time_format(delta_conn,0))
table[2].append(utils.time_format(delta_cmd,1))
table[1].append(utils.time_format(delta_conn, 0))
table[2].append(utils.time_format(delta_cmd, 1))
table[3].append(plr_pobject.location.id)
table[4].append(session.cmd_total)
table[5].append(session.address[0])

View file

@ -54,10 +54,10 @@ class CmdReload(MuxCommand):
if attempt < max_attempts-1:
caller.msg(" Waiting for modules(s) to finish (%s) ..." % attempt)
else:
string = " ... The module(s) took too long to reload, "
string = "{r ... The module(s) took too long to reload, "
string += "\n so the remaining reloads where skipped."
string += "\n Re-run @reload again when modules have fully "
string += "\n re-initialized."
string += "\n re-initialized.{n"
caller.msg(string)
class CmdPy(MuxCommand):

View file

@ -34,14 +34,15 @@ class ChannelCommand(command.Command):
Usage:
<channel name or alias> <message>
This is a channel. You can send to it by entering
its name or alias, followed by the text you want to send.
This is a channel. If you have subscribed to it, you can send to
it by entering its name or alias, followed by the text you want to
send.
"""
# this flag is what identifies this cmd as a channel cmd
# and branches off to the system send-to-channel command
# (which is customizable by admin)
key = "general"
help_category = "Channels"
help_category = "Channel Names"
permissions = "cmd:use_channels"
is_channel = True
obj = None
@ -64,6 +65,7 @@ class ChannelCommand(command.Command):
caller.msg("Say what?")
return
channel = Channel.objects.get_channel(channelkey)
if not channel:
caller.msg("Channel '%s' not found." % channelkey)
return
@ -93,8 +95,8 @@ class ChannelHandler(object):
def __str__(self):
return ", ".join(str(cmd) for cmd in self.cached_channel_cmds)
def reset(self):
def clear(self):
"""
Reset the cache storage.
"""

View file

@ -232,13 +232,7 @@ class ChannelManager(models.Manager):
from src.comms.channelhandler import CHANNELHANDLER
CHANNELHANDLER.update()
return None
def has_connection(self, player, channel):
"Check so the player is really listening to this channel."
ChannelConnection = ContentType.objects.get(app_label="comms",
model="channelconnection").model_class()
return ChannelConnection.objects.has_connection(player, channel)
def get_all_connections(self, channel):
"""
Return the connections of all players listening

View file

@ -474,7 +474,7 @@ class Channel(SharedMemoryModel):
Checks so this player is actually listening
to this channel.
"""
return Channel.objects.has_connection(player, self)
return ChannelConnection.objects.has_connection(player, self)
def msg(self, msgobj, from_obj=None):
"""

View file

@ -34,7 +34,7 @@ class ExitHandler(object):
"Setup cache storage"
self.cached_exit_cmds = {}
def reset(self, exitcmd=None):
def clear(self, exitcmd=None):
"""
Reset cache storage. If obj is given, only remove
that object from cache.

View file

@ -13,10 +13,7 @@ Attributes are separate objects that store values persistently onto
the database object. Like everything else, they can be accessed
transparently through the decorating TypeClass.
"""
try:
import cPickle as pickle
except ImportError:
import pickle
from django.db import models
from django.conf import settings
@ -74,6 +71,39 @@ class Alias(SharedMemoryModel):
verbose_name = "Object alias"
verbose_name_plural = "Object aliases"
#------------------------------------------------------------
#
# Nick
#
#------------------------------------------------------------
class Nick(SharedMemoryModel):
"""
This model holds whichever alternate names this object
has for OTHER objects, but also for arbitrary strings,
channels, players etc. Setting a nick does not affect
the nicknamed object at all (as opposed to Aliases above),
and only this object will be able to refer to the nicknamed
object by the given nick.
The default nick types used by Evennia are:
inputline (default) - match against all input
player - match against player searches
obj - match against object searches
channel - used to store own names for channels
"""
db_nick = models.CharField(max_length=255, db_index=True) # the nick
db_real = models.TextField() # the aliased string
db_type = models.CharField(default="inputline", max_length=16, null=True, blank=True) # the type of nick
db_obj = models.ForeignKey("ObjectDB")
class Meta:
"Define Django meta options"
verbose_name = "Nickname"
verbose_name_plural = "Nicknames"
unique_together = ("db_nick", "db_type", "db_obj")
#------------------------------------------------------------
#
# ObjectDB
@ -140,7 +170,7 @@ class ObjectDB(TypedObject):
blank=True, null=True)
# pickled dictionary storing the object's assigned nicknames
# (use the 'nicks' property to access)
db_nicks = models.TextField(null=True, blank=True)
db_nicks = models.ForeignKey(Nick, blank=True, null=True, db_index=True)
# Database manager
objects = ObjectManager()
@ -157,7 +187,7 @@ class ObjectDB(TypedObject):
#@property
def aliases_get(self):
"Getter. Allows for value = self.aliases"
return [alias.db_key for alias in Alias.objects.filter(db_obj=self)]
return list(Alias.objects.filter(db_obj=self))
#@aliases.setter
def aliases_set(self, aliases):
"Setter. Allows for self.aliases = value"
@ -277,30 +307,17 @@ class ObjectDB(TypedObject):
# nicks property (wraps db_nicks)
#@property
def nicks_get(self):
"""
Getter. Allows for value = self.nicks.
This unpickles the nick dictionary.
"""
if self.db_nicks:
return pickle.loads(str(self.db_nicks))
return {}
#@nicks.setter
def nicks_set(self, nick_dict):
"""
Setter. Allows for self.nicks = nick_dict.
This re-pickles the nick dictionary.
"""
if type(nick_dict) == dict:
# only allow storing dicts.
self.db_nicks = pickle.dumps(nick_dict)
self.save()
#@nicks.deleter
"Getter. Allows for value = self.aliases"
return list(Nick.objects.filter(db_obj=self))
#@nick.setter
def nicks_set(self, nicks):
"""Setter is disabled. Use the nickhandler instead."""
logger.log_errmsg("Nicks (%s) cannot be set through obj.nicks. Use obj.nickhandler instead." % nicks)
#@nick.deleter
def nicks_del(self):
"""
Deleter. Allows for del self.nicks.
Don't delete nicks, set to empty dict
"""
self.db_nicks = {}
"Deleter. Allows for del self.aliases"
for nick in Nick.objects.filter(db_obj=self):
nick.delete()
nicks = property(nicks_get, nicks_set, nicks_del)
@ -361,66 +378,55 @@ class ObjectDB(TypedObject):
return [exi for exi in self.contents
if exi.has_attribute('_destination')]
exits = property(exits_get)
#
# Nicks - custom nicknames
#
#
# nicks - the object can with this create
# personalized aliases for in-game words. Essentially
# anything can be re-mapped, it's up to the implementation
# as to how often the nick is checked and converted
# to its real counterpart before entering into the system.
#
# Some system defaults:
# {"nick":"cmdname", # re-maps command names(also channels)
# "_player:nick":"player_name", # re-maps player names
# "_obj:nick":"realname"} # re-maps object names
#
# Example: a nick 'obj:red' mapped to the word "big red man" would
# allow you to search for the big red man with just 'red' (note
# that it's dumb substitution though; red will always translate
# to big red man when searching, regardless of if there is such
# a man or not. Such logics need to implemented for your particular
# game).
#
def set_nick(self, nick, realname=None):
def nickhandler(self, nick, realname=None, nick_type="inputline", startswith=False, delete=False):
"""
This is a central method for getting and setting nicks
- mappings of nicks to strings, objects etc. This is the main
access method, use it in preference over the 'nicks' property.
Map a nick to a realname. Be careful if mapping an
existing realname into a nick - you could make that
realname inaccessible until you deleted the alias.
Don't set realname to delete a previously set nick.
To delete - don't set realname.
returns a string with the old realname that this alias
used to map (now overwritten), in case the
nickname was already defined before.
"""
if not nick:
return
if not realname:
nicks = self.nicks
delnick = "Old alias not found!"
if nick in nicks:
# delete the nick
delnick = nicks[nick]
del nicks[nick]
self.nicks = nicks
return delnick
nick = nick.strip()
realname = realname.strip()
if nick == realname:
return
# set the new alias
retval = None
nicks = self.nicks
if nick in nicks:
retval = nicks[nick]
nicks[nick] = realname
self.nicks = nicks
return retval
nick_types can be defined freely depending on implementation.
The default nick_types used in Evennia are:
inputline (default) - match nick against all input
player - match nick against player searches
obj - match nick against object searches
channel - match nick when checking for channel aliases
the delete keyword will delete the given nick.
"""
if not nick or not nick.strip():
return
nick = nick.strip()
query = Nick.objects.filter(db_obj=self, db_nick__iexact=nick)
if nick_type:
query = query.filter(db_type__iexact=nick_type)
if delete:
# remove the found nick(s)
query.delete()
elif realname == None:
# we want to get the real name for the nick. If none is
# found, we return the nick again
query = query.values_list("db_real", flat=True)
if query:
return query[0]
else:
return nick
else:
# we want to assign a new nick
real = realname.strip()
if query:
old_nick = query[0]
old_nick.db_real = real
old_nick.save()
else:
new_nick = Nick(db_nick=nick, db_real=real, db_type=nick_type, db_obj=self)
new_nick.save()
#
# Main Search method
#
@ -460,20 +466,10 @@ class ObjectDB(TypedObject):
if use_nicks:
if ostring.startswith('*'):
# player nick replace
for nick, real in ((nick.lstrip('_player:').strip(), real)
for nick, real in self.nicks.items()
if nick.strip().startswith('_player:')):
if ostring.lstrip('*').lower() == nick.lower():
ostring = "*%s" % real
break
ostring = "*%s" % self.nickhandler(ostring.lstrip('*'), nick_type="player")
else:
# object nick replace
for nick, real in ((nick.lstrip('_obj:').strip(), real)
for nick, real in self.nicks.items()
if nick.strip().startswith('_obj:')):
if ostring.lower() == nick.lower():
ostring = real
break
ostring = self.nickhandler(ostring, nick_type="object")
results = ObjectDB.objects.object_search(self, ostring,
global_search=global_search,
@ -512,11 +508,13 @@ class ObjectDB(TypedObject):
lets its typeclass execute the command.
raw_string - raw command input coming from the command line.
"""
# nick replacement
for nick, real in self.nicks.items():
if raw_string.startswith(nick):
raw_string = raw_string.replace(nick, real, 1)
break
# nick replacement - we require full-word matching.
raw_list = raw_string.split(None)
raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]]
for nick in Nick.objects.filter(db_obj=self, db_type__in=("inputline","channel")):
if nick.db_nick in raw_list:
raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1)
break
cmdhandler.cmdhandler(self.typeclass(self), raw_string)
def msg(self, message, from_obj=None, data=None):
@ -532,7 +530,7 @@ class ObjectDB(TypedObject):
# we use a different __getattribute__ to avoid recursive loops.
if object.__getattribute__(self, 'player'):
object.__getattribute__(self, 'player').msg(message, data)
object.__getattribute__(self, 'player').msg(message, from_obj, data)
def emit_to(self, message, from_obj=None, data=None):
"Deprecated. Alias for msg"

View file

@ -374,5 +374,5 @@ class Exit(Object):
out of sync with the cache. You should do this also if
overloading this function in a child class.
"""
EXITHANDLER.reset(self.dbobj)
EXITHANDLER.clear(self.dbobj)
return True

View file

@ -18,7 +18,6 @@ if os.name == 'nt':
from twisted.application import internet, service
from twisted.internet import protocol, reactor, defer
from twisted.web import server, static
from twisted.python import threadpool
from django.db import connection
from django.conf import settings
from src.utils import reloads
@ -203,7 +202,8 @@ if WEBSERVER_ENABLED:
# a django-compatible webserver.
from src.server.webserver import DjangoWebRoot, WSGIWebServer#DjangoWebRoot
from twisted.python import threadpool
from src.server.webserver import DjangoWebRoot, WSGIWebServer
# start a thread pool and define the root url (/) as a wsgi resource
# recognized by Django
@ -221,7 +221,6 @@ if WEBSERVER_ENABLED:
for port in WEBSERVER_PORTS:
# create the webserver
webserver = WSGIWebServer(threads, port, web_site)
#webserver = internet.TCPServer(port, web_site)
#webserver = internet.SSLServer(port, web_site)
webserver.setName('EvenniaWebServer%s' % port)
EVENNIA.services.addService(webserver)

View file

@ -4,8 +4,8 @@ Web client server resource.
The Evennia web client consists of two components running
on twisted and django. They are both a part of the Evennia
website url tree (so the testing website might be located
on http://localhost:8020/, whereas the webclient can be
found on http://localhost:8020/webclient.)
on http://localhost:8000/, whereas the webclient can be
found on http://localhost:8000/webclient.)
/webclient - this url is handled through django's template
system and serves the html page for the client

View file

@ -44,6 +44,9 @@ class DjangoWebRoot(resource.Resource):
path0 = request.prepath.pop(0)
request.postpath.insert(0, path0)
return self.wsgi_resource
#
# Threaded Webserver
#
class WSGIWebServer(internet.TCPServer):
"""

View file

@ -261,7 +261,7 @@ CHANNEL_PUBLIC = ("Public", 'ooc', 'Public discussion',
CHANNEL_MUDINFO = ("MUDinfo", '', 'Informative messages',
'''chan_admin:has_id(1),
chan_listen:Immortals,
chan_send:Immportals''')
chan_send:Immortals''')
# Channel showing when new people connecting
CHANNEL_CONNECTINFO = ("MUDconnections", ('connections, mud_conns'),
'Connection log',

View file

@ -331,7 +331,7 @@ def create_message(senderobj, message, channels=None,
new_message.save()
return new_message
def create_channel(key, aliases=None, description=None,
def create_channel(key, aliases=None, desc=None,
permissions=None, keep_log=True):
"""
Create A communication Channel. A Channel serves as a central
@ -356,7 +356,7 @@ def create_channel(key, aliases=None, description=None,
if not is_iter(aliases):
aliases = [aliases]
new_channel.aliases = ",".join([str(alias) for alias in aliases])
new_channel.description = description
new_channel.desc = desc
new_channel.keep_log = keep_log
except IntegrityError:
string = "Could not add channel: key '%s' already exists." % key

View file

@ -94,8 +94,8 @@ def reload_modules():
# clean out cache dictionary of typeclasses, exits and channe
typeclassmodels.reset()
exithandler.EXITHANDLER.reset()
channelhandler.CHANNELHANDLER.reset()
exithandler.EXITHANDLER.clear()
channelhandler.CHANNELHANDLER.update()
def reload_scripts(scripts=None, obj=None, key=None,
dbref=None, init_mode=False):
@ -129,14 +129,17 @@ def cemit_info(message):
Sends the info to a pre-set channel. This channel is
set by CHANNEL_MUDINFO in settings.
"""
logger.log_infomsg(message)
try:
infochan = settings.CHANNEL_MUDINFO
infochan = Channel.objects.get_channel(infochan[0])
except Exception:
return
pass
if infochan:
cname = infochan.key
cmessage = "\n".join(["[%s]: %s" % (cname, line) for line in message.split('\n')])
infochan.msg(cmessage)
else:
cmessage = "\n".join(["[NO MUDINFO CHANNEL]: %s" % line for line in message.split('\n')])
logger.log_infomsg(cmessage)