diff --git a/evennia/ABOUT b/evennia/ABOUT new file mode 100755 index 0000000000..5f980a783f --- /dev/null +++ b/evennia/ABOUT @@ -0,0 +1,74 @@ +Evennia Proof-of-Concept +------------------------ +Evennia is a proof-of-concept MUD server written entirely in Python, backed +by SQL. The project rises from a general dissatisfaction with the limitations +of softcode in MUX and MUSH, and the generally inflexible Diku-derivatives and +relatives. + +Evennia represents a combination of several technologies, and most importantly +of all, my first venture into codebase design. You may find things within +the source that look strange to you, perhaps not ideally designed. I'm open +to suggestions, but this really is largely an experiment and a learning +experience. + +Design Objectives +----------------- +1) To create a MU* server that serves as a great foundation for capable admins +to craft into their respective games. It is not my intention to provide a +full-fledged, ready-to-run base, I'm releasing the means to make such games. + +2) Development of games on Evennia must be easy for anyone with some degree +of Python experience. Building needs to be easy, and per-room, per-object, +and environmental customizations need to be simple to do. + +3) The server must utilize SQL as a storage back-end to allow for web->game +integration. See the details on Django later on in the document for more +details. + +4) Any and all game-specific configuration must reside in SQL, not +external configuration files. The only exception is the settings.py file +containing the SQL information. + +How it all Works +---------------- +Python (Including the SQL driver of your choice) + |-asynchat (included with Python2) + |-SQL (MySQL, SQLite, Postgresql) + |-Django (http://djangoproject.com) + +Evennia is built on top of asynchat, an asynchronous TCP conversation/chat +library. This makes the actual socket/connection handling an absolute +no-brainer. + +Serving as our storage medium, SQL is one of the more important and unique +features of the codebase. It allows for very simple code in many cases, and +can lead to a game being a lot more scalable due to the inherent speed of +most modern SQL servers. Another extremely important benefit is that by +storing everything in SQL, we make the entire game accessible from other +means, such as a website. Which leads us to the next component. + +Django is perhaps one of the most interesting introductions to the codebase, +since I'm not aware of any other server using it to run MU*'s. Django is +technically a Python web framework, but it also includes a great data modeling +and database abstraction module. This means that things like Players or +Objects can be represented by a very short class, then related to one another. +This allows us to add, remove, delete, and manipulate things in our database +very easily. Another huge benefit is the admin interface that Django more +or less automatically generates for us. Instead of a bunch of clunky admin +commands, you can fire up your web browser and administer pretty much +everything from there, although equivalent in-game commands may be offered. +The possibilities for developing your game's website are nearly endless with +this tandem of MU* server, SQL, and Django. + +Support +------- +At this time, I am offering no formal support for Evennia. It is not ready for +use and is subject to change in a major way from week to week. I can't hope +to support such a young product. However, if you have questions or ideas, +please direct them to squishywaffle@gmail.com. + +Reporting Bugs +-------------- +Feel free to contact me by email at squishywaffle@gmail.com with as much +details on the bug that you can find. Copy/pasting server logs is generally +a good idea. diff --git a/evennia/README b/evennia/README new file mode 100755 index 0000000000..cda28f7992 --- /dev/null +++ b/evennia/README @@ -0,0 +1,16 @@ +Starting the Server +------------------- +Prior to starting up Evennia, you'll need the following environmental variable +set. + +export DJANGO_SETTINGS_MODULE="settings" + +You may wish to put this in your .bashrc file, or you can simple copy/paste +it before each startup. I'll fix this later so you don't have to, but it'll +do for now. + +Once you've got the evar set, simply enter the following: + +python server.py + +The default port is 4000. diff --git a/evennia/__init__.py b/evennia/__init__.py new file mode 100755 index 0000000000..e69de29bb2 diff --git a/evennia/__init__.pyc b/evennia/__init__.pyc new file mode 100755 index 0000000000..16a63f6823 Binary files /dev/null and b/evennia/__init__.pyc differ diff --git a/evennia/ansi.py b/evennia/ansi.py new file mode 100755 index 0000000000..9f9840bd46 --- /dev/null +++ b/evennia/ansi.py @@ -0,0 +1,36 @@ +""" +ANSI related stuff. +""" +ansi = {} +ansi["beep"] = "\07" +ansi["escape"] = "\033" +ansi["normal"] = "\033[0m" + +ansi["underline"] = "\033[4m" +ansi["hilite"] = "\033[1m" +ansi["blink"] = "\033[5m" +ansi["inverse"] = "\033[7m" +ansi["inv_hilite"] = "\033[1;7m" +ansi["inv_blink"] = "\033[7;5m" +ansi["blink_hilite"] = "\033[1;5m" +ansi["inv_blink_hilite"] = "\033[1;5;7m" + +# Foreground colors +ansi["black"] = "\033[30m" +ansi["red"] = "\033[31m" +ansi["green"] = "\033[32m" +ansi["yellow"] = "\033[33m" +ansi["blue"] = "\033[34m" +ansi["magenta"] = "\033[35m" +ansi["cyan"] = "\033[36m" +ansi["white"] = "\033[37m" + +# Background colors +ansi["back_black"] = "\033[40m" +ansi["back_red"] = "\033[41m" +ansi["back_green"] = "\033[42m" +ansi["back_yellow"] = "\033[43m" +ansi["back_blue"] = "\033[44m" +ansi["back_magenta"] = "\033[45m" +ansi["back_cyan"] = "\033[46m" +ansi["back_white"] = "\033[47m" diff --git a/evennia/ansi.pyc b/evennia/ansi.pyc new file mode 100755 index 0000000000..b0be437eac Binary files /dev/null and b/evennia/ansi.pyc differ diff --git a/evennia/apps/__init__.py b/evennia/apps/__init__.py new file mode 100755 index 0000000000..e69de29bb2 diff --git a/evennia/apps/__init__.pyc b/evennia/apps/__init__.pyc new file mode 100755 index 0000000000..448c3507d2 Binary files /dev/null and b/evennia/apps/__init__.pyc differ diff --git a/evennia/apps/config/__init__.py b/evennia/apps/config/__init__.py new file mode 100755 index 0000000000..e69de29bb2 diff --git a/evennia/apps/config/__init__.pyc b/evennia/apps/config/__init__.pyc new file mode 100755 index 0000000000..dd805c3d3f Binary files /dev/null and b/evennia/apps/config/__init__.pyc differ diff --git a/evennia/apps/config/models.py b/evennia/apps/config/models.py new file mode 100755 index 0000000000..464437ce5b --- /dev/null +++ b/evennia/apps/config/models.py @@ -0,0 +1,27 @@ +from django.db import models + +class CommandAlias(models.Model): + """ + Command aliases. + """ + user_input = models.CharField(maxlength=50) + equiv_command = models.CharField(maxlength=50) + + class Admin: + list_display = ('user_input', 'equiv_command',) + +class Config(models.Model): + """ + Although we technically have the ability to create more than one Config + object via the admin interface, we only really need one. This also leaves + the possibility for multiple games hosted on the same codebase or database + in the future, although this is not a priority. In any case, this model + contains most of the game-specific configuration. + """ + site_name = models.CharField(maxlength=100) + site_description = models.TextField(blank=True) + site_website = models.URLField(blank=True) + player_start_dbnum = models.IntegerField() + + class Admin: + list_display = ('site_name', 'site_website',) diff --git a/evennia/apps/config/models.pyc b/evennia/apps/config/models.pyc new file mode 100755 index 0000000000..09311ec112 Binary files /dev/null and b/evennia/apps/config/models.pyc differ diff --git a/evennia/apps/config/views.py b/evennia/apps/config/views.py new file mode 100755 index 0000000000..60f00ef0ef --- /dev/null +++ b/evennia/apps/config/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/evennia/apps/objects/__init__.py b/evennia/apps/objects/__init__.py new file mode 100755 index 0000000000..e69de29bb2 diff --git a/evennia/apps/objects/__init__.pyc b/evennia/apps/objects/__init__.pyc new file mode 100755 index 0000000000..8776a7bd01 Binary files /dev/null and b/evennia/apps/objects/__init__.pyc differ diff --git a/evennia/apps/objects/models.py b/evennia/apps/objects/models.py new file mode 100755 index 0000000000..f1913ad301 --- /dev/null +++ b/evennia/apps/objects/models.py @@ -0,0 +1,92 @@ +from django.db import models +from django.contrib.auth.models import User + +class ObjectClass(models.Model): + """ + Each object class can have different behaviors to apply to it. + """ + name = models.CharField(maxlength=255) + description = models.TextField() + + def __str__(self): + return "%s(%d)" % (self.name, self.id,) + + class Admin: + list_display = ('name', 'description',) + +class Attribute(models.Model): + """ + Attributes are things that are specific to different types of objects. For + example, a drink container needs to store its fill level, whereas an exit + needs to store its open/closed/locked/unlocked state. These are done via + attributes, rather than making different classes for each object type and + storing them directly. The added benefit is that we can add/remove attributes + on the fly as we like. + """ + name = models.CharField(maxlength=255) + value = models.CharField(maxlength=255) + object = models.ForeignKey("Object") + + def __str__(self): + return "%s(%d)" % (self.name, self.id,) + + class Admin: + list_display = ('name', 'value',) + +class Object(models.Model): + """ + The Object class is very generic. We put all of our common attributes + here and anything very particular into the attribute field. Notice the otype + field. The different otypes denote an object's behaviors. + """ + + # Do not mess with the default types (0-4). + OBJECT_TYPES = ( + (0, 'NOTHING'), + (1, 'PLAYER'), + (2, 'ROOM'), + (3, 'THING'), + (4, 'EXIT'), + ) + + name = models.CharField(maxlength=255) + type = models.SmallIntegerField(choices=OBJECT_TYPES) + description = models.TextField(blank=True) + location = models.ForeignKey('self', related_name="olocation", blank=True, null=True) + contents = models.ManyToManyField("Object", related_name="object", blank=True, null=True) + attributes = models.ManyToManyField(Attribute, related_name="attributes", blank=True, null=True) + + def __str__(self): + return "%s(%d)" % (self.name, self.id,) + + def is_type(self, typename): + """ + Do a string comparison of user's input and the object's type class object's + name. + """ + return self.type.name == typename + + def set_type(self, typename): + """ + Sets a object's type. + """ + pass + + class Admin: + list_display = ('name',) +""" +class Player(models.Model): +# +# Model representation of our players. +# + # Link back to our Django User class for password, username, email, etc. + account = models.ForeignKey(User) + location = models.ForeignKey(Object, related_name="plocation") + is_connected = models.BooleanField() + last_connected = models.DateTimeField() + contents = models.ManyToManyField(Object) + attributes = models.ManyToManyField(Attribute) + + def __str__(self): + return "%s(%d)" % (self.name, self.id,) +""" diff --git a/evennia/apps/objects/models.pyc b/evennia/apps/objects/models.pyc new file mode 100755 index 0000000000..6eb2ee7a18 Binary files /dev/null and b/evennia/apps/objects/models.pyc differ diff --git a/evennia/apps/objects/views.py b/evennia/apps/objects/views.py new file mode 100755 index 0000000000..60f00ef0ef --- /dev/null +++ b/evennia/apps/objects/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/evennia/cmdhandler.py b/evennia/cmdhandler.py new file mode 100755 index 0000000000..c4c7ec5235 --- /dev/null +++ b/evennia/cmdhandler.py @@ -0,0 +1,207 @@ +from django.contrib.auth.models import User +from apps.objects.models import Object +import settings +import string +from ansi import * +""" +This is the command processing module. It is instanced once in the main +server module and the handle() function is hit every time a player sends +something. +""" + +class GenCommands: + """ + Generic command class. Pretty much every command should go here for + now. + """ + def __init__(self): pass + + def do_look(self, cdat): + """ + Handle looking at objects. + """ + session = cdat['session'] + server = session.server + player_loc = session.player_loc + player_loc_obj = Object.objects.filter(id=player_loc)[0] + + retval = "%s%s%s%s\n\r%s\n\r" % ( + ansi["normal"], + ansi["hilite"], + player_loc_obj.name, + ansi["normal"], + player_loc_obj.description, + ) + session.push(retval) + + def do_quit(self, cdat): + """ + Gracefully disconnect the user as per his own request. + """ + session = cdat['session'] + session.push("Quitting!\n\r") + session.handle_close() + + def do_who(self, cdat): + """ + Generic WHO command. + """ + session_list = cdat['server'].session_list + session = cdat['session'] + + retval = "Player Name\n\r" + for player in session_list: + retval += '%s\n\r' % (player,) + retval += '%d Players logged in.\n\r' % (len(session_list),) + + session.push(retval) + + def do_say(self, cdat): + """ + Room-based speech command. + """ + session_list = cdat['server'].session_list + session = cdat['session'] + speech = cdat['uinput'][1:] + players_present = [player for player in session_list if player.player_loc == session.player_loc and player != session] + + retval = "You say, '%s'\n\r" % (''.join(speech),) + for player in players_present: + player.push("%s says, '%s'\n\r" % (session.name, speech,)) + + session.push(retval) + + def do_sa(self, cdat): + """ + Temporary alias until we come up with a command alias system. + """ + self.do_say(cdat) + + def do_version(self, cdat): + """ + Version info command. + """ + session = cdat['session'] + retval = "-"*50 +"\n\r" + retval += "Evennia %s\n\r" % (settings.EVENNIA_VERSION,) + retval += "-"*50 +"\n\r" + session.push(retval) + +class StaffCommands: + """ + Restricted staff commands. + """ + def do_dig(self, cdat): + """ + Digs a new room out. + """ + session = cdat['session'] + uinput= cdat['uinput'] + roomname = ''.join(uinput[1:]) + + if roomname == '': + session.push("You must supply a room name!") + else: + newroom = Object() + newroom.name = roomname + newroom.type = "Room" + + def do_nextfree(self, cdat): + """ + Returns the next free object number. + """ + session = cdat['session'] + server = cdat['server'] + + nextfree = server.nextfree_objnum() + retval = "Next free object number: %d" % (nextfree,) + + session.push(retval) + +class UnLoggedInCommands: + """ + Commands that are available from the connect screen. + """ + def __init__(self): pass + def do_connect(self, cdat): + """ + This is the connect command at the connection screen. Fairly simple, + uses the Django database API and User model to make it extremely simple. + """ + session = cdat['session'] + uname = cdat['uinput'][1] + password = cdat['uinput'][2] + + account = User.objects.filter(username=uname) + user = account[0] + + autherror = "Invalid username or password!\n\r" + if account.count() == 0: + session.push(autherror) + if not user.check_password(password): + session.push(autherror) + else: + uname = user.username + session.login(user) + + def do_create(self, cdat): + """ + Handle the creation of new accounts. + """ + session = cdat['session'] + uname = cdat['uinput'][1] + email = cdat['uinput'][2] + password = cdat['uinput'][3] + account = User.objects.filter(username=uname) + + if not account.count() == 0: + session.push("There is already a player with that name!") + elif len(password) < 3: + session.push("Your password must be 3 characters or longer.") + else: + session.create_user(uname, email, password) + + def do_quit(self, cdat): + """ + We're going to maintain a different version of the quit command + here for unconnected users for the sake of simplicity. The logged in + version will be a bit more complicated. + """ + session = cdat['session'] + session.push("Disconnecting...\n\r") + session.handle_close() + +# We'll use this for our getattr() in the Handler class. +gencommands = GenCommands() +staffcommands = StaffCommands() +unloggedincommands = UnLoggedInCommands() + +class Handler: + def __init__(self): pass + def handle(self, cdat): + """ + Use the spliced (list) uinput variable to retrieve the correct + command, or return an invalid command error. + + We're basically grabbing the player's command by tacking + their input on to 'do_' and looking it up in the GenCommands + class. + """ + session = cdat['session'] + uinput = cdat['uinput'] + + if session.logged_in: + # If it's prefixed by an '@', it's a staff command. + if uinput[0].find('@') == -1: + cmdtable = gencommands + else: + cmdtable = staffcommands + else: + cmdtable = unloggedincommands + cmd = getattr(cmdtable, 'do_' + uinput[0].lower(), None) + + if callable(cmd): + cmd(cdat) + else: + session.push("Unknown command.\n\r") + diff --git a/evennia/cmdhandler.pyc b/evennia/cmdhandler.pyc new file mode 100755 index 0000000000..dc065d1469 Binary files /dev/null and b/evennia/cmdhandler.pyc differ diff --git a/evennia/commonfuncs.py b/evennia/commonfuncs.py new file mode 100755 index 0000000000..e69de29bb2 diff --git a/evennia/manage.py b/evennia/manage.py new file mode 100755 index 0000000000..5e78ea979e --- /dev/null +++ b/evennia/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/evennia/prepenv.sh b/evennia/prepenv.sh new file mode 100755 index 0000000000..18f1b7fd2f --- /dev/null +++ b/evennia/prepenv.sh @@ -0,0 +1,3 @@ +#!/bin/bash +export DJANGO_SETTINGS_MODULE="settings" +python server.py diff --git a/evennia/server.py b/evennia/server.py new file mode 100755 index 0000000000..ac112dfe72 --- /dev/null +++ b/evennia/server.py @@ -0,0 +1,94 @@ +from asyncore import dispatcher +from asynchat import async_chat +import socket, asyncore, time, sys +from sessions import PlayerSession +from django.db import models +from apps.config.models import Config +from apps.objects.models import Object + +# +## Begin: Time Functions +# + +schedule = {'heal':100.0} +lastrun = {} + +def heal(): + pass + +# The timer loop +def Timer(timer): + + sched = schedule.iteritems() + for i in sched: + try: lastrun[i[0]] + except: lastrun[i[0]] = time.time() + + diff = timer - lastrun[i[0]] + + # Every 100 seconds, run heal(), defined above. + if diff >= schedule['heal']: + heal() + lastrun['heal'] = time.time() + +# +## End: Time Functions +# + +class Server(dispatcher): + """ + The main server class from which everything branches. + """ + def __init__(self, port): + dispatcher.__init__(self) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + self.bind(('', port)) + self.listen(100) + self.session_list = [] + self.object_list = {} + self.game_running = True + print '-'*50 + self.load_config() + self.load_objects() + print ' Server started on port %i.' % (port,) + print '-'*50 + + def load_config(self): + """ + Loads our site's configuration up for easy access. + """ + self.config = Config.objects.all()[0] + print ' Configuration Loaded.' + + def load_objects(self): + """ + Load all of our objects into memory. + """ + object_list = Object.objects.all() + for object in object_list: + dbnum = object.id + self.object_list[dbnum] = object + print ' Objects Loaded: %i' % (len(self.object_list),) + + def handle_accept(self): + """ + What to do when we get a connection. + """ + conn, addr = self.accept() + session = PlayerSession(self, conn, addr) + session.game_connect_screen(session) + print 'Connection:', str(session) + self.session_list.append(session) + print 'Sessions active:', len(self.session_list) + +if __name__ == '__main__': + server = Server(4000) + + try: + while server.game_running: + asyncore.loop(timeout=5, count=1) # Timer() called every 5 seconds. + Timer(time.time()) + + except KeyboardInterrupt: + print 'Interrupted' diff --git a/evennia/server.pyc b/evennia/server.pyc new file mode 100755 index 0000000000..2de910e811 Binary files /dev/null and b/evennia/server.pyc differ diff --git a/evennia/sessions.py b/evennia/sessions.py new file mode 100755 index 0000000000..51dc40735f --- /dev/null +++ b/evennia/sessions.py @@ -0,0 +1,117 @@ +from asyncore import dispatcher +from asynchat import async_chat +import socket, asyncore, time, sys +from cmdhandler import * + +chandler = Handler() + +class PlayerSession(async_chat): + """ + This class represents a player's sesssion. From here we branch down into + other various classes, please try to keep this one tidy! + """ + def __init__(self, server, sock, addr): + async_chat.__init__(self, sock) + self.server = server + self.address = addr + self.set_terminator("\n") + self.name = None + self.data = [] + self.sock = sock + self.logged_in = False + self.user = None + # The time the user last issued a command. + self.cmd_last = time.time() + # Total number of commands issued. + self.cmd_total = 0 + # The time when the user connected. + self.conn_time = time.time() + # Player's room location. Move this to a player sub-class. + self.player_loc = 4 + + def collect_incoming_data(self, data): + """ + Stuff any incoming data into our buffer, self.data + """ + self.data.append(data) + + def found_terminator(self): + """ + Any line return indicates a command for the purpose of a MUD. So we take + the user input, split it up by spaces into a list, and pass it to our + command handler. + """ + line = (''.join(self.data)) + line = line.strip('\r') + uinput = line.split(' ') + self.data = [] + + # Increment our user's command counter. + self.cmd_total += 1 + # Store the timestamp of the user's last command. + self.cmd_last = time.time() + # Stuff anything we need to pass in this dictionary. + cdat = {"server": self.server, "uinput": uinput, "session": self} + chandler.handle(cdat) + + def handle_close(self): + """ + Break the connection and do some accounting. + """ + async_chat.handle_close(self) + self.logged_in = False + self.server.session_list.remove(self) + print 'Sessions active:', len(self.server.session_list) + + def game_connect_screen(self, session): + """ + Show our banner screen. + """ + buffer = '-'*50 + buffer += ' \n\rWelcome to Evennia!\n\r' + buffer += '-'*50 + '\n\r' + buffer += """Please type one of the following to begin:\n\r + connect \n\r + create \n\r""" + buffer += '-'*50 + '\n\r' + session.push(buffer) + + def login(self, user): + """ + After the user has authenticated, handle logging him in. + """ + self.user = user + self.name = user.username + self.logged_in = True + self.conn_time = time.time() + self.push("Logging in as %s.\n\r" % (self.name,)) + print "Login: %s" % (self,) + + def create_user(self, uname, email, password): + """ + Handles the creation of new users. + """ + # print uname, email, password + user = User.objects.create_user(uname, email, password) + self.login(user) + print 'Registration: %s' % (self,) + self.push("Welcome to the game, %s.\n\r" % (self.name,)) + + def nextfree_objnum(self): + """ + Returns the next free object number. + """ + + def __str__(self): + """ + String representation of the user session class. We use + this a lot in the server logs and stuff. + """ + if self.logged_in: + symbol = '#' + else: + symbol = '?' + return "<%s> %s@%s" % (symbol, self.name, self.address,) + +# def handle_error(self): +# self.handle_close() diff --git a/evennia/sessions.pyc b/evennia/sessions.pyc new file mode 100755 index 0000000000..fdc3392524 Binary files /dev/null and b/evennia/sessions.pyc differ diff --git a/evennia/settings.py b/evennia/settings.py new file mode 100755 index 0000000000..c033e6e3c0 --- /dev/null +++ b/evennia/settings.py @@ -0,0 +1,85 @@ +# Django settings for evennia project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASE_ENGINE = 'mysql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. +DATABASE_NAME = 'evennia' # Or path to database file if using sqlite3. +DATABASE_USER = 'evennia' # Not used with sqlite3. +DATABASE_PASSWORD = 'CvAPpy:FFRTmTMHf' # Not used with sqlite3. +DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. All choices can be found here: +# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE +TIME_ZONE = 'America/New_York' + +# Language code for this installation. All choices can be found here: +# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes +# http://blogs.law.harvard.edu/tech/stories/storyReader$15 +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = False + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '/home/gtaylor/dev/evennia/media' + +# URL that handles the media served from MEDIA_ROOT. +# Example: "http://media.lawrence.com" +MEDIA_URL = '/media/' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/amedia/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'fsd&lkj^LKJ8398200(@)(38919#23892(*$*#(981' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.load_template_source', + 'django.template.loaders.app_directories.load_template_source', +# 'django.template.loaders.eggs.load_template_source', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.doc.XViewMiddleware', +) + +ROOT_URLCONF = 'evennia.urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.admin', + 'evennia.apps.config', + 'evennia.apps.objects', +# 'django.contrib.sites', +) + +# +## Evennia Config +# +EVENNIA_VERSION = 'Pre-Alpha 0.0' diff --git a/evennia/settings.pyc b/evennia/settings.pyc new file mode 100755 index 0000000000..4a6fbbe5bc Binary files /dev/null and b/evennia/settings.pyc differ diff --git a/evennia/urls.py b/evennia/urls.py new file mode 100755 index 0000000000..4811fa01bf --- /dev/null +++ b/evennia/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', + # Example: + # (r'^evennia/', include('evennia.apps.foo.urls.foo')), + + # Uncomment this for admin: + (r'^admin/', include('django.contrib.admin.urls')), +)