mirror of
https://github.com/evennia/evennia.git
synced 2026-03-24 16:56:32 +01:00
This is a rather big update, encompassing quite a few areas that will lead to what I hope will be a very easy to modify yet flexible codebase. New stuff includes:
* A simple command parser that supports MUX/MUSH-style switches. * Global command alias support. Aliases can be edited via web interface or SQL. * A new SQL-based configuration system that can be edited directly or via a Django web interface. * The listen port is now configurable via aforementioned config system instead of hard-wired as it was previously. Yick :)
This commit is contained in:
parent
fa21a35fe4
commit
aabce6e7e3
4 changed files with 82 additions and 45 deletions
|
|
@ -10,18 +10,12 @@ class CommandAlias(models.Model):
|
|||
class Admin:
|
||||
list_display = ('user_input', 'equiv_command',)
|
||||
|
||||
class Config(models.Model):
|
||||
class ConfigValue(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.
|
||||
Experimental new config model.
|
||||
"""
|
||||
site_name = models.CharField(maxlength=100)
|
||||
site_description = models.TextField(blank=True)
|
||||
site_website = models.URLField(blank=True)
|
||||
player_start_dbnum = models.IntegerField()
|
||||
|
||||
conf_key = models.CharField(maxlength=100)
|
||||
conf_value = models.CharField(maxlength=255 )
|
||||
|
||||
class Admin:
|
||||
list_display = ('site_name', 'site_website',)
|
||||
list_display = ('conf_key', 'conf_value',)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class GenCommands:
|
|||
session = cdat['session']
|
||||
server = session.server
|
||||
player_loc = session.player_loc
|
||||
player_loc_obj = Object.objects.filter(id=player_loc)[0]
|
||||
player_loc_obj = server.object_list[player_loc]
|
||||
|
||||
retval = "%s%s%s%s\n\r%s\n\r" % (
|
||||
ansi["normal"],
|
||||
|
|
@ -62,7 +62,7 @@ class GenCommands:
|
|||
"""
|
||||
session_list = cdat['server'].session_list
|
||||
session = cdat['session']
|
||||
speech = cdat['uinput'][1:]
|
||||
speech = cdat['uinput']['splitted'][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),)
|
||||
|
|
@ -71,12 +71,6 @@ class GenCommands:
|
|||
|
||||
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.
|
||||
|
|
@ -129,8 +123,8 @@ class UnLoggedInCommands:
|
|||
uses the Django database API and User model to make it extremely simple.
|
||||
"""
|
||||
session = cdat['session']
|
||||
uname = cdat['uinput'][1]
|
||||
password = cdat['uinput'][2]
|
||||
uname = cdat['uinput']['splitted'][1]
|
||||
password = cdat['uinput']['splitted'][2]
|
||||
|
||||
account = User.objects.filter(username=uname)
|
||||
user = account[0]
|
||||
|
|
@ -149,9 +143,9 @@ class UnLoggedInCommands:
|
|||
Handle the creation of new accounts.
|
||||
"""
|
||||
session = cdat['session']
|
||||
uname = cdat['uinput'][1]
|
||||
email = cdat['uinput'][2]
|
||||
password = cdat['uinput'][3]
|
||||
uname = cdat['uinput']['splitted'][1]
|
||||
email = cdat['uinput']['splitted'][2]
|
||||
password = cdat['uinput']['splitted'][3]
|
||||
account = User.objects.filter(username=uname)
|
||||
|
||||
if not account.count() == 0:
|
||||
|
|
@ -188,19 +182,40 @@ class Handler:
|
|||
class.
|
||||
"""
|
||||
session = cdat['session']
|
||||
uinput = cdat['uinput']
|
||||
server = cdat['server']
|
||||
uinput = cdat['uinput'].split()
|
||||
|
||||
parsed_input = {}
|
||||
|
||||
# First we split the input up by spaces.
|
||||
parsed_input['splitted'] = uinput
|
||||
# Now we find the root command chunk (with switches attached).
|
||||
parsed_input['root_chunk'] = parsed_input['splitted'][0].split('/')
|
||||
# And now for the actual root command. It's the first entry in root_chunk.
|
||||
parsed_input['root_cmd'] = parsed_input['root_chunk'][0].lower()
|
||||
|
||||
# Now we'll see if the user is using an alias. We do a dictionary lookup,
|
||||
# if the key (the player's root command) doesn't exist on the dict, we
|
||||
# don't replace the existing root_cmd. If the key exists, its value
|
||||
# replaces the previously splitted root_cmd. For example, sa -> say.
|
||||
alias_list = server.cmd_alias_list
|
||||
parsed_input['root_cmd'] = alias_list.get(parsed_input['root_cmd'],parsed_input['root_cmd'])
|
||||
|
||||
if session.logged_in:
|
||||
# If it's prefixed by an '@', it's a staff command.
|
||||
if uinput[0].find('@') == -1:
|
||||
if parsed_input['root_cmd'][0] != '@':
|
||||
cmdtable = gencommands
|
||||
else:
|
||||
cmdtable = staffcommands
|
||||
else:
|
||||
cmdtable = unloggedincommands
|
||||
cmd = getattr(cmdtable, 'do_' + uinput[0].lower(), None)
|
||||
|
||||
# cmdtable now equals the command table we need to use. Do a command
|
||||
# lookup for a particular function based on the user's input.
|
||||
cmd = getattr(cmdtable, 'do_' + parsed_input['root_cmd'], None )
|
||||
|
||||
if callable(cmd):
|
||||
cdat['uinput'] = parsed_input
|
||||
cmd(cdat)
|
||||
else:
|
||||
session.push("Unknown command.\n\r")
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ 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.config.models import ConfigValue, CommandAlias
|
||||
from apps.objects.models import Object
|
||||
|
||||
#
|
||||
|
|
@ -39,26 +39,45 @@ class Server(dispatcher):
|
|||
"""
|
||||
The main server class from which everything branches.
|
||||
"""
|
||||
def __init__(self, port):
|
||||
def __init__(self):
|
||||
self.session_list = []
|
||||
self.object_list = {}
|
||||
self.cmd_alias_list = {}
|
||||
self.configvalue = {}
|
||||
self.game_running = True
|
||||
print '-'*50
|
||||
self.load_configvalues()
|
||||
self.load_objects()
|
||||
self.load_cmd_aliases()
|
||||
dispatcher.__init__(self)
|
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.set_reuse_addr()
|
||||
self.bind(('', port))
|
||||
self.bind(('', int(self.configvalue['site_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 ' %s started on port %s.' % (self.configvalue['site_name'], self.configvalue['site_port'],)
|
||||
print '-'*50
|
||||
|
||||
def announce_all(self, message, with_ann_prefix=True):
|
||||
"""
|
||||
Announces something to all connected players.
|
||||
"""
|
||||
if with_ann_prefix:
|
||||
prefix = 'Announcement:'
|
||||
else:
|
||||
prefix = ''
|
||||
|
||||
for session in self.session_list:
|
||||
session.push('%s %s' % (prefix, message,))
|
||||
|
||||
def load_config(self):
|
||||
def load_configvalues(self):
|
||||
"""
|
||||
Loads our site's configuration up for easy access.
|
||||
"""
|
||||
self.config = Config.objects.all()[0]
|
||||
configs = ConfigValue.objects.all()
|
||||
|
||||
for conf in configs:
|
||||
self.configvalue[conf.conf_key] = conf.conf_value
|
||||
|
||||
print ' Configuration Loaded.'
|
||||
|
||||
def load_objects(self):
|
||||
|
|
@ -71,6 +90,15 @@ class Server(dispatcher):
|
|||
self.object_list[dbnum] = object
|
||||
print ' Objects Loaded: %i' % (len(self.object_list),)
|
||||
|
||||
def load_cmd_aliases(self):
|
||||
"""
|
||||
Load up our command aliases.
|
||||
"""
|
||||
alias_list = CommandAlias.objects.all()
|
||||
for alias in alias_list:
|
||||
self.cmd_alias_list[alias.user_input] = alias.equiv_command
|
||||
print ' Aliases Loaded: %i' % (len(self.cmd_alias_list),)
|
||||
|
||||
def handle_accept(self):
|
||||
"""
|
||||
What to do when we get a connection.
|
||||
|
|
@ -83,7 +111,7 @@ class Server(dispatcher):
|
|||
print 'Sessions active:', len(self.session_list)
|
||||
|
||||
if __name__ == '__main__':
|
||||
server = Server(4000)
|
||||
server = Server()
|
||||
|
||||
try:
|
||||
while server.game_running:
|
||||
|
|
@ -91,4 +119,5 @@ if __name__ == '__main__':
|
|||
Timer(time.time())
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print 'Interrupted'
|
||||
server.announce_all('The server has been shutdown. Please check back soon.')
|
||||
print '--> Server killed by keystroke.'
|
||||
|
|
|
|||
|
|
@ -38,12 +38,11 @@ class PlayerSession(async_chat):
|
|||
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.
|
||||
the user input and pass it to our command handler.
|
||||
"""
|
||||
line = (''.join(self.data))
|
||||
line = line.strip('\r')
|
||||
uinput = line.split(' ')
|
||||
uinput = line
|
||||
self.data = []
|
||||
|
||||
# Increment our user's command counter.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue