Configuration of the GCP is done in a XML file. It contains 2 sections:
1. all databusses
2. the logging configuration

For logging the log4j package is used, so one should look at www.log4j.org. The
default config don't need to be changed (except for the location of the log file).

Configuration of a databus looks like follows:
    <databus name="bus1"> 
		<component class="CLASSNAME" id="ID">
		.
		.
		.
        </component>
        
		<component class="CLASSNAME" id="OTHERID">
		.
		.
		.
        </component>
    </databus>
    
A databus can contains as many components as you want (or until you don't 
have enough memory :). The only requirement is that every compoent has a 
unique ID. If the file changes on disc, it is reloaded. All components then
get notified about the new configuration. Components which are not in the file
(this is detected by the ID) are removed from the databus.

The XML data int the <component> elements depend on the component. All components which
are currently available are described in this document.

Components are typed: producers and listeners (or both). A producer can be generic
or not. Generic producers create events, which are not based on other events. The
program finishes if there are no more generic producers available and there are 
no more events on the bus.

there are some sample configuration files:
q3a.xml - starts a Q3A server under windows
lin_q3a.xml: starts 2 Q3A servers under linux
kicker.xml: shows the configuration for the 2 types of auto kickers

---------------------------------------------------------------------------------
AutoKicker 
function: automagically kicks player according to specific rules
requires: a handler for GameControlEvents
output: -
class: de.hendriklipka.gcp.module.kicker.AutoKicker
config format: see file cfg/kicker.xml

---------------------------------------------------------------------------------
GameEventWriter 
function: writes game events
          is able to do a logfile rotation (with different modes)
requires: a source for GameEvents (e.g. a LineFilter)
output: none
class: de.hendriklipka.gcp.module.output.GameEventWriter
config format:
            <filename>log/gamelog_%n.log</filename> <!-- %n is replaced with the string generated for the naming mode (see below) -->
            <rotatemode>NONE</rotatemode> <!-- one of NONE, TIME, SIZE, LINES -->
            <namingmode></namingmode> <!-- one of NONE, RANDOM, NUMBER, TIME -->
            <changelines>1000</changelines> <!-- after how many lines to start a new file (rotatemode=LINES) -->
            <changesize>10000</changesize> <!-- after which size to start a new file (in bytes)-->
            <changetime>100000</changetime> <!-- after which time to start a new file (in milliseconds) -->

---------------------------------------------------------------------------------
IdentKicker 
function: kicks player, if they have a registered name and cannot authenticate with password
requires: GameEvents, RConUserCommandEvents
output: -
class: de.hendriklipka.gcp.module.processing.IdentKicker
config format: see cfg/kicker.xml

---------------------------------------------------------------------------------
InputEventWriter 
function: writes input events
          is able to do a logfile rotation (with different modes)
requires: a source for InputEvents (e.g. a QRunnerInputFilter)
output: none
class: de.hendriklipka.gcp.module.output.InputEventWriter
config format:
            <filename>log/inputlog_%n.log</filename> <!-- %n is replaced with the string generated for the naming mode (see below) -->
            <rotatemode>NONE</rotatemode> <!-- one of NONE, TIME, SIZE, LINES -->
            <namingmode></namingmode> <!-- one of NONE, RANDOM, NUMBER, TIME -->
            <changelines>1000</changelines> <!-- after how many lines to start a new file (rotatemode=LINES) -->
            <changesize>10000</changesize> <!-- after which size to start a new file (in bytes)-->
            <changetime>100000</changetime> <!-- after which time to start a new file (in milliseconds) -->

---------------------------------------------------------------------------------
LineFilter 
function: filters InputEvents after given rules and creates standardized GameEvents 
requires: a source for InputEvents
output:  GameEvent
class: de.hendriklipka.gcp.module.processing.LineFilter
config format: see cfg/kicker.xml

---------------------------------------------------------------------------------
LogFileInputFilter 
function: reads the input from a logfile, which is concurrently written by a program
          thus module is for getting the output from a Q3A server under windows, because this
          server does not print to StdOut
          the server should be set to write a log file and to flush after each line
          this can be done with:
          logfile 2 // will create baseq3/qconsole.log, which is flushed after every line
          or
          g_log "games.log" // which creates baseq3/games.log
          g_logsync 2 // which is then flushed after every line
          the given file is periodically checked for net content
requires: -
output: InputEvent, ProcessGameEvent
class: de.hendriklipka.gcp.module.input.LogFileInputFilter
config format:
        <inputfile>log.log</inputfile> <!-- the logfile where to read the input from -->
        <detect_hang time=30"/> <!-- if for this time (in seconds) no input was received, a running process 
                                     (see QRunnerInputFilter) will be killed (and eventually restarted) -->
        
---------------------------------------------------------------------------------
MapLogWriter 
function: writes InputEvents to a logfile, per map
requires: sources for InputEvents and GameEvents (to detect a map change)
output: -
class: de.hendriklipka.gcp.module.output.MapLogWriter
config format:
            <outfile>log/maplog_%m_%t.log</outfile> <!-- name of the logfile %m is replaced with the map name, %t with the time -->
            <mapstarttype>startmap</mapstarttype> <!-- event type (GameEvent) for start of a map -->
            <mapparam>mapname</mapparam> <!-- where to find the map name in this event -->
            <program>cp %n %m</program> <!-- execute this program before a mapchange. %n is the old logfile, %m the old map name -->

---------------------------------------------------------------------------------
NetworkControlHandler 
function: allows remote administration of a running game server
          users can connect to the server
          after a login they are bound to a role, which then is bound to specific commands
          for this role
          commands are executed by command handlers
requires: a GameCommandHandler
output: GameControlEvents
class: de.hendriklipka.gcp.module.input.network.NetworkControlHandler
config format:

		    <port> <!-- port where to listen -->
		        26000
		    </port>
		    <logfile> <!-- logfile -->
		        log/nch.log
		    </logfile>
		    <loglevel> <!-- what to log -->
		        ALL <!-- NONE ERROR LOGIN COMMAND RESULT DEBUG -->
		    </loglevel>
		    <users> <!-- users, their passwords and roles -->
		        <user login="admin1" role="admin" password="admin1"/>
		        <user login="admin2" role="admin" password="admin2"/>
		        <user login="sysop1" role="sysop" password="sysop1"/>
		        <user login="sysop2" role="sysop" password="sysop2"/>
		        <user login="user1" role="user" password="user1"/>
		        <user login="nextmap" role="nextmap" password="nextmap"/>
		    </users>
		    <tries> <!-- tries for login, after that the connection is closed -->
		        2
		    </tries>
		    <timeout> <!-- for the server socket, in seconds -->
		        1
		    </timeout>
		    <banner> <!-- banner to print after a connect -->
		        welcome to this server
		    </banner>
		    <linefeed> <!-- which caracters to send for a linefeed -->
		        CRLF
		    </linefeed>
		    <commandprefix>/</commandprefix> <!-- prefix for commands -->
		    <!-- these roles can see the game output -->
		    <roles-for-output>admin;sysop</roles-for-output>
		    <roles-for-direct-commands>admin</roles-for-direct-commands>
		    <!-- 
		        define the command handlers
		        every handler has a list of roles, which then can use the commands of this handler
		     -->
		     <!-- also see below -->
		    <handlers>
		        <handler class="de.hendriklipka.gcp.module.input.network.AdminCommandHandler" role="admin"/>
		        <handler class="de.hendriklipka.gcp.module.input.network.StdCommandHandler" role="admin;user;sysop"/>
		    </handlers>

AdminCommandHandler 
class: de.hendriklipka.gcp.module.input.network.AdminCommandHandler
StdCommandHandler 
class: de.hendriklipka.gcp.module.input.network.StdCommandHandler
DynamicCommandHandler 
class: de.hendriklipka.gcp.module.input.network.DynamicCommandHandler
for every defined command the specified code is executed dynamically (via an interpreter)
config format:
                    <!-- there can be an unlimited number of commands -->
                    <!-- known variables: result and handler -->
		            <command name="nextmap"> <!-- how the comand is named -->
		                result=handler.sendCommand("vstr nextmap"); <!-- what to execute for this command -->
		            </command>

---------------------------------------------------------------------------------
Q2ProtocolHandler 
function: see QWProtocolHandler
class: de.hendriklipka.gcp.module.control.Q3AProtocolHandler

---------------------------------------------------------------------------------
Q3AProtocolHandler 
function: see QWProtocolHandler
class: de.hendriklipka.gcp.module.control.Q2ProtocolHandler

---------------------------------------------------------------------------------
QWProtocolHandler 
function: sends requests to a running Quakeworld server via UDP.
requires: a source for GameControlEvents
output: -
class: de.hendriklipka.gcp.module.control.QWProtocolHandler
config format:
            <address ip="127.0.0.1" port="27960"/> <!-- address and port of the game server -->
            <password>hli</password> <!-- rcon password -->
            <timeout>5</timeout> <!-- how long to wait for a response -->

---------------------------------------------------------------------------------
QControlFileInputFilter 
function: reads a logfile created from QWControl
requires: -
output: InputEvent
class: de.hendriklipka.gcp.module.input.QControlFileInputFilter
config format: none
        the inputfile is specified via "inputfile=name" on the command line

---------------------------------------------------------------------------------
QRunnerInputFilter 
function: start a external program and captures the output send to StdOut / StdErr
          the output is send as InputEvents to the bus
          the program is restarted after it has been exited (this must be configured)
          NOTE: the start directory for this application is the directopry from where you started GCP.
          so for Q3A you want to use "+set fs_basepath c:\somewhere" in the command line to set the starting 
          directory. For QuakeWorld, use "-basedir c:\somewhere"
requires: nothing
output: InputEvent
input: ProcessGameEvent
class: de.hendriklipka.gcp.module.input.QRunnerInputFilter
config format:
		    <command> <!-- command to start the server -->
		        /opt/q3a/q3ded +set dedicated 1 +exec server.cfg
		    </command>
		    <priority> <!-- priority of the thread which handles StdOut -->
		        +1
		    </priority>
		    <restart time="30"/> <!-- in seconds, -1 for no restart -->
            <detect_hang time=30"/> <!-- if for this time (in seconds) no input was received, the running process will be killed 
                                         (and eventually restarted) --> 


---------------------------------------------------------------------------------
RConUserCommandFilter 
function: filters InputEvents for commands given with RCon commands with wrong password
          this is for implementing a command system for all users, not only admins, without touching the game
          such a command looks like:
          rcon $password $command $the_command $params
          the detection of the rcon command is done in the linefilter. this module generates
          specific messages for bad rcon commands (rcon commands with wrong passwords)
          - first, a message that there was a wrong rcon command
          - second, the wrong command itself
    
          $password and $command are configurable
          a new event with $the_command and $params is then created
          
          currently only tested with QW TF
requires: GameEvent
output: RConUserCommandEvent
class: de.hendriklipka.gcp.module.processing.RConUserCommandFilter
config format:
                <badrcon_msgtype> <!-- event type (GameEvent) for the message "bad rcon command from xxx" -->
                    badrcon
                </badrcon_msgtype>
                <badrcon_property_ip> <!-- where to find the IP in this message -->
                    address
                </badrcon_property_ip>
                <rconcommand_msgtype> <!-- event type (GameEvent) for a rcon command -->
                    rconcommand
                </rconcommand_msgtype>
                <rconcommand_property_password> <!-- where to find the password for the rcon command in the event -->
                    password
                </rconcommand_property_password>
                <rconcommand_property_command> <!-- where to find the command from the rcon command in the event -->
                    command
                </rconcommand_property_command>
                <command_prefix> <!-- command prefix for rcon commands -->
                    cmd
                </command_prefix>

---------------------------------------------------------------------------------
ProgramOnEventHandler
function: executes external program when a specific GameEvent occurs
requires: source for GameEvents
output: -
class: de.hendriklipka.gcp.module.output.ProgramOnEventHandler
config format:
            <program>echo map_%mapname%_map</program> <!-- commandline for the program %...% is replaced with the corresponding replacement string from the event -->
            <eventtype>startmap</eventtype> <!-- the type of event when a program to execute -->

---------------------------------------------------------------------------------
