Run Migrations! Added a is_connected field to Players to be able to more conveniently access online status from out-of-process (resolves issue 251). Also cleaned up and added features to the default website.

This commit is contained in:
Griatch 2012-09-17 19:19:20 +02:00
parent c53a9b5770
commit 21137cc830
10 changed files with 189 additions and 75 deletions

View file

@ -96,7 +96,7 @@ class PlayerManager(TypedObjectManager):
""" """
Returns a list of player objects with currently connected users/players. Returns a list of player objects with currently connected users/players.
""" """
return [player for player in self.all() if player.sessions] return self.filter(db_is_connected=True)
@returns_typeclass_list @returns_typeclass_list
@returns_player_list @returns_player_list
@ -116,6 +116,8 @@ class PlayerManager(TypedObjectManager):
""" """
Returns a QuerySet containing the player User accounts that have been Returns a QuerySet containing the player User accounts that have been
connected within the last <days> days. connected within the last <days> days.
days - number of days backwards to check
""" """
end_date = datetime.datetime.now() end_date = datetime.datetime.now()
tdelta = datetime.timedelta(days) tdelta = datetime.timedelta(days)
@ -166,7 +168,6 @@ class PlayerManager(TypedObjectManager):
return matches return matches
return self.filter(user__username__iexact=ostring) return self.filter(user__username__iexact=ostring)
def swap_character(self, player, new_character, delete_old_character=False): def swap_character(self, player, new_character, delete_old_character=False):
""" """
This disconnects a player from the current character (if any) and connects This disconnects a player from the current character (if any) and connects

View file

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'PlayerDB.db_is_connected'
db.add_column('players_playerdb', 'db_is_connected',
self.gf('django.db.models.fields.BooleanField')(default=False),
keep_default=False)
def backwards(self, orm):
# Deleting field 'PlayerDB.db_is_connected'
db.delete_column('players_playerdb', 'db_is_connected')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'objects.objectdb': {
'Meta': {'object_name': 'ObjectDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'players.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'players.playernick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['players']

View file

@ -161,7 +161,9 @@ class PlayerDB(TypedObject):
# Use the property 'obj' to access. # Use the property 'obj' to access.
db_obj = models.ForeignKey("objects.ObjectDB", null=True, blank=True, db_obj = models.ForeignKey("objects.ObjectDB", null=True, blank=True,
verbose_name="character", help_text='In-game object.') verbose_name="character", help_text='In-game object.')
# store a connected flag here too, not just in sessionhandler.
# This makes it easier to track from various out-of-process locations
db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not")
# database storage of persistant cmdsets. # database storage of persistant cmdsets.
db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True, db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True,
help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_DEFAULT.") help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_DEFAULT.")
@ -251,6 +253,21 @@ class PlayerDB(TypedObject):
self.save() self.save()
cmdset_storage = property(cmdset_storage_get, cmdset_storage_set, cmdset_storage_del) cmdset_storage = property(cmdset_storage_get, cmdset_storage_set, cmdset_storage_del)
#@property
def is_connected_get(self):
"Getter. Allows for value = self.is_connected"
return _get_cache(self, "is_connected")
#@is_connected.setter
def is_connected_set(self, value):
"Setter. Allows for self.is_connected = value"
print "set_is_connected:", self, value
_set_cache(self, "is_connected", value)
#@is_connected.deleter
def is_connected_del(self):
"Deleter. Allows for del is_connected"
_set_cache(self, "is_connected", False)
is_connected = property(is_connected_get, is_connected_set, is_connected_del)
class Meta: class Meta:
"Define Django meta options" "Define Django meta options"
verbose_name = "Player" verbose_name = "Player"

View file

@ -21,6 +21,7 @@ import django
from django.db import connection from django.db import connection
from django.conf import settings from django.conf import settings
from src.players.models import PlayerDB
from src.scripts.models import ScriptDB from src.scripts.models import ScriptDB
from src.server.models import ServerConfig from src.server.models import ServerConfig
from src.server import initial_setup from src.server import initial_setup
@ -29,6 +30,8 @@ from src.utils.utils import get_evennia_version, mod_import
from src.comms import channelhandler from src.comms import channelhandler
from src.server.sessionhandler import SESSIONS from src.server.sessionhandler import SESSIONS
_SA = object.__setattr__
if os.name == 'nt': if os.name == 'nt':
# For Windows we need to handle pid files manually. # For Windows we need to handle pid files manually.
SERVER_PIDFILE = os.path.join(settings.GAME_DIR, 'server.pid') SERVER_PIDFILE = os.path.join(settings.GAME_DIR, 'server.pid')
@ -285,6 +288,7 @@ class Evennia(object):
# don't call disconnect hooks on reset # don't call disconnect hooks on reset
yield [(o.typeclass, o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()] yield [(o.typeclass, o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()]
else: # shutdown else: # shutdown
yield [_SA(p, "is_connected", False) for p in PlayerDB.get_all_cached_instances()]
yield [(o.typeclass, o.at_disconnect(), o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()] yield [(o.typeclass, o.at_disconnect(), o.at_server_shutdown()) for o in ObjectDB.get_all_cached_instances()]
yield [(p.typeclass, p.at_server_shutdown()) for p in PlayerDB.get_all_cached_instances()] yield [(p.typeclass, p.at_server_shutdown()) for p in PlayerDB.get_all_cached_instances()]

View file

@ -71,6 +71,12 @@ class ServerSession(Session):
player - the connected player player - the connected player
""" """
# we have to check this first before uid has been assigned
# this session.
if not self.sessionhandler.sessions_from_player(player):
player.is_connected = True
# actually do the login by assigning session data # actually do the login by assigning session data
self.player = player self.player = player
@ -134,6 +140,8 @@ class ServerSession(Session):
uaccount.save() uaccount.save()
self.logged_in = False self.logged_in = False
self.sessionhandler.disconnect(self) self.sessionhandler.disconnect(self)
if not self.sessionhandler.sessions_from_player(player):
player.is_connected = False
def get_player(self): def get_player(self):
""" """

View file

@ -16,7 +16,7 @@ import time
from django.conf import settings from django.conf import settings
from src.commands.cmdhandler import CMD_LOGINSTART from src.commands.cmdhandler import CMD_LOGINSTART
_ServerConfig = None _PLAYERDB = None
# AMP signals # AMP signals
PCONN = chr(1) # portal session connect PCONN = chr(1) # portal session connect
@ -153,8 +153,6 @@ class ServerSessionHandler(SessionHandler):
self.server.amp_protocol.call_remote_PortalAdmin(sessid, self.server.amp_protocol.call_remote_PortalAdmin(sessid,
operation=SDISCONN, operation=SDISCONN,
data=reason) data=reason)
self.session_count(-1)
def login(self, session): def login(self, session):
""" """
@ -168,7 +166,6 @@ class ServerSessionHandler(SessionHandler):
# disconnect previous sessions. # disconnect previous sessions.
self.disconnect_duplicate_sessions(session) self.disconnect_duplicate_sessions(session)
session.logged_in = True session.logged_in = True
self.session_count(1)
# sync the portal to this session # sync the portal to this session
sessdata = session.get_sync_data() sessdata = session.get_sync_data()
self.server.amp_protocol.call_remote_PortalAdmin(session.sessid, self.server.amp_protocol.call_remote_PortalAdmin(session.sessid,
@ -193,7 +190,6 @@ class ServerSessionHandler(SessionHandler):
for session in self.sessions: for session in self.sessions:
del session del session
self.session_count(0)
# tell portal to disconnect all sessions # tell portal to disconnect all sessions
self.server.amp_protocol.call_remote_PortalAdmin(0, self.server.amp_protocol.call_remote_PortalAdmin(0,
operation=SDISCONNALL, operation=SDISCONNALL,
@ -204,14 +200,12 @@ class ServerSessionHandler(SessionHandler):
Disconnects any existing sessions with the same game object. Disconnects any existing sessions with the same game object.
""" """
curr_char = curr_session.get_character() curr_char = curr_session.get_character()
doublet_sessions = [sess for sess in self.sessions doublet_sessions = [sess for sess in self.sessions.values()
if sess.logged_in if sess.logged_in
and sess.get_character() == curr_char and sess.get_character() == curr_char
and sess != curr_session] and sess != curr_session]
for session in doublet_sessions: for session in doublet_sessions:
self.disconnect(session, reason) self.disconnect(session, reason)
self.session_count(-1)
def validate_sessions(self): def validate_sessions(self):
""" """
@ -224,31 +218,6 @@ class ServerSessionHandler(SessionHandler):
if session.logged_in and IDLE_TIMEOUT > 0 if session.logged_in and IDLE_TIMEOUT > 0
and (tcurr - session.cmd_last) > IDLE_TIMEOUT): and (tcurr - session.cmd_last) > IDLE_TIMEOUT):
self.disconnect(session, reason=reason) self.disconnect(session, reason=reason)
self.session_count(-1)
def session_count(self, num=None):
"""
Count up/down the number of connected, authenticated users.
If num is None, the current number of sessions is returned.
num can be a positive or negative value to be added to the current count.
If 0, the counter will be reset to 0.
"""
global _ServerConfig
if not _ServerConfig:
from src.server.models import ServerConfig as _ServerConfig
if num == None:
# show the current value. This also syncs it.
return int(_ServerConfig.objects.conf('nr_sessions', default=0))
elif num == 0:
# reset value to 0
_ServerConfig.objects.conf('nr_sessions', 0)
else:
# add/remove session count from value
add = int(_ServerConfig.objects.conf('nr_sessions', default=0))
num = max(0, num + add)
_ServerConfig.objects.conf('nr_sessions', str(num))
def player_count(self): def player_count(self):
""" """
@ -274,7 +243,6 @@ class ServerSessionHandler(SessionHandler):
return self.sessions_from_player(player) return self.sessions_from_player(player)
return None return None
def announce_all(self, message): def announce_all(self, message):
""" """
Send message to all connected sessions Send message to all connected sessions

View file

@ -64,7 +64,7 @@ SSL_INTERFACES = ['0.0.0.0']
# All feedback from the game will be echoed to all sessions. # All feedback from the game will be echoed to all sessions.
# If false, only one session is allowed, all other are logged off # If false, only one session is allowed, all other are logged off
# when a new connects. # when a new connects.
ALLOW_MULTISESSION = True ALLOW_MULTISESSION = False
# The path that contains this settings.py file (no trailing slash). # The path that contains this settings.py file (no trailing slash).
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Path to the src directory containing the bulk of the codebase's code. # Path to the src directory containing the bulk of the codebase's code.

View file

@ -8,10 +8,11 @@
{% block content %} {% block content %}
<div class="rowOfBoxes"> <div class="rowOfBoxes">
<div class="twoThirds noBorderOnLeft"> <!--div class="twoThirds noBorderOnLeft"-->
<div class="noBorderOnLeft">
<h1>Welcome!</h1> <h1>Welcome!</h1>
<p>Welcome to your new installation of <a href="http://evennia.com">Evennia</a>, your friendly <p>Welcome to your new installation of <a href="http://evennia.com">Evennia</a>, your friendly
neighborhood next-generation MUD server. You are looking at Evennia's web neighborhood next-generation MUD development system and server. You are looking at Evennia's web
presence, which can be expanded to a full-fledged site as presence, which can be expanded to a full-fledged site as
needed. Through the <a href="/admin">admin interface</a> you can view and edit the needed. Through the <a href="/admin">admin interface</a> you can view and edit the
database without logging into the game. database without logging into the game.
@ -23,13 +24,14 @@
peruse our extensive online <a href="http://code.google.com/p/evennia/wiki/Index">documentation</a>. peruse our extensive online <a href="http://code.google.com/p/evennia/wiki/Index">documentation</a>.
<p> <p>
Should you have any questions, concerns, bug reports, or Should you have any questions, concerns, bug reports, or
if you want to help out, don't hesitate to come join the if you want to help out, don't hesitate to join the Evennia community to make your voice heard! Drop a mail to the
<a href="http://evennia.com/discussions">Evennia community</a> and get <a href="http://evennia.com/discussions">mailing list</a> or to come say hi in the <a href="http://webchat.freenode.net/?channels=evennia">developer chatroom</a>. If you find bugs, please report them to our <a href="http://code.google.com/p/evennia/issues/list">Issue tracker</a>.
your voice heard!
</p> </p>
</div> </div>
<div class="oneThird"> <!-- news app commented out since there are no news in the database originally -->
<!--div class="oneThird">
<h1>Latest News</h1> <h1>Latest News</h1>
{% for entry in news_entries %} {% for entry in news_entries %}
<a href="/news/show/{{entry.id}}" class="newsHeading">{{entry.topic.name}}: {{entry.title}}</a> <a href="/news/show/{{entry.id}}" class="newsHeading">{{entry.topic.name}}: {{entry.title}}</a>
@ -39,8 +41,8 @@
<div class="more"><a href="/news/archive">More News &raquo;</a></div> <div class="more"><a href="/news/archive">More News &raquo;</a></div>
<p class="filler"><!-- Filler para to extend left vertical line --></p> <p class="filler"><!-- Filler para to extend left vertical line--></p>
</div> </div-->
</div> </div>
<div class="rowOfBoxes dividingBorderAbove"> <div class="rowOfBoxes dividingBorderAbove">
@ -48,8 +50,7 @@
<div class="quarter noBorderOnLeft"> <div class="quarter noBorderOnLeft">
<h1>Players</h1> <h1>Players</h1>
<p> <p>
There are currently <strong>{{num_players_connected}}</strong> connected, There's currently <strong>{{num_players_connected}}</strong> connected out of a total of <strong>{{num_players_registered}}</strong> players registered. Of these, <strong>{{num_players_registered_recent}}</strong> were created this week, and <strong>{{num_players_connected_recent}}</strong> have connected within the last seven days.
and a total of <strong>{{num_players_registered}}</strong> registered. Of these, <strong>{{num_players_registered_recent}}</strong> were created this week, and <strong>{{num_players_connected_recent}}</strong> have connected within the last seven days.
</p> </p>
</div> </div>
@ -66,15 +67,16 @@
<div class="quarter"> <div class="quarter">
<h1>Database Stats</h1> <h1>Database Stats</h1>
<ul> <ul>
<li>{{num_players_registered}} players</li> <li>{{num_players_registered}} players (+ {{num_characters}} characters)</li>
<li>{{num_rooms}} rooms ({{num_exits}} exits) </li> <li>{{num_rooms}} rooms (+ {{num_exits}} exits)</li>
<li>{{num_objects}} objects total</li> <li>{{num_others}} other objects</li>
</ul> </ul>
</div> </div>
<div class="quarter"> <div class="quarter">
<h1>Evennia</h1> <h1>Evennia</h1>
<p><a href="http://evennia.com">Evennia</a> is MUD server built in <p><a href="http://evennia.com">Evennia</a> is an open-source MUD server built in
<a href="http://python.org">Python</a>, on top of the <a href="http://python.org">Python</a>, on top of the
<a href="http://twistedmatrix.com">Twisted</a> and <a href="http://twistedmatrix.com">Twisted</a> and
<a href="http://djangoproject.com">Django</a> frameworks. This <a href="http://djangoproject.com">Django</a> frameworks. This

View file

@ -5,18 +5,18 @@ the other applications. Views are django's way of processing e.g. html
templates on the fly. templates on the fly.
""" """
from django.shortcuts import render_to_response
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from django.contrib.auth.models import User #from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from src.server.models import ServerConfig
from src.objects.models import ObjectDB from src.objects.models import ObjectDB
from src.typeclasses.models import TypedObject #from src.typeclasses.models import TypedObject
from src.players.models import PlayerDB from src.players.models import PlayerDB
from src.web.news.models import NewsEntry from src.web.news.models import NewsEntry
_BASE_CHAR_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
def page_index(request): def page_index(request):
""" """
Main root page. Main root page.
@ -30,21 +30,30 @@ def page_index(request):
news_entries = NewsEntry.objects.all().order_by('-date_posted')[:fpage_news_entries] news_entries = NewsEntry.objects.all().order_by('-date_posted')[:fpage_news_entries]
# A QuerySet of the most recently connected players. # A QuerySet of the most recently connected players.
recent_users = PlayerDB.objects.get_recently_connected_players()[:fpage_player_limit] recent_users = PlayerDB.objects.get_recently_connected_players()[:fpage_player_limit]
nplyrs_conn_recent = len(recent_users) or "none"
nplyrs = PlayerDB.objects.num_total_players() or "none"
nplyrs_reg_recent = len(PlayerDB.objects.get_recently_created_players()) or "none"
nsess = len(PlayerDB.objects.get_connected_players()) or "noone"
exits = ObjectDB.objects.filter(db_destination__isnull=False) nobjs = ObjectDB.objects.all().count()
rooms = [room for room in ObjectDB.objects.filter(db_home__isnull=True) if room not in exits] nrooms = ObjectDB.objects.filter(db_location__isnull=True).exclude(db_typeclass_path=_BASE_CHAR_TYPECLASS).count()
nexits = ObjectDB.objects.filter(db_location__isnull=False, db_destination__isnull=False).count()
nchars = ObjectDB.objects.filter(db_typeclass_path=_BASE_CHAR_TYPECLASS).count()
nothers = nobjs - nrooms - nchars - nexits
pagevars = { pagevars = {
"page_title": "Front Page", "page_title": "Front Page",
"news_entries": news_entries, "news_entries": news_entries,
"players_connected_recent": recent_users, "players_connected_recent": recent_users,
"num_players_connected": ServerConfig.objects.conf('nr_sessions'),#len(PlayerDB.objects.get_connected_players()), "num_players_connected": nsess or "noone",
"num_players_registered": PlayerDB.objects.num_total_players(), "num_players_registered": nplyrs or "no",
"num_players_connected_recent": len(PlayerDB.objects.get_recently_connected_players()), "num_players_connected_recent": nplyrs_conn_recent or "no",
"num_players_registered_recent": len(PlayerDB.objects.get_recently_created_players()), "num_players_registered_recent": nplyrs_reg_recent or "noone",
"num_rooms": len(rooms), "num_rooms": nrooms or "none",
"num_exits": len(exits), "num_exits": nexits or "no",
"num_objects" : ObjectDB.objects.all().count() "num_objects" : nobjs or "none",
"num_characters": nchars or "no",
"num_others": nothers or "no"
} }
context_instance = RequestContext(request) context_instance = RequestContext(request)