Index: code/branches/network/CMakeLists.txt
===================================================================
--- code/branches/network/CMakeLists.txt	(revision 1445)
+++ code/branches/network/CMakeLists.txt	(revision 1446)
@@ -68,4 +68,5 @@
 FIND_PACKAGE(ENet)
 FIND_PACKAGE(Boost REQUIRED thread)
+FIND_PACKAGE(Boost REQUIRED filesystem)
 FIND_PACKAGE(OpenAL)
 FIND_PACKAGE(ALUT)
Index: code/branches/network/bin/disco.txt
===================================================================
--- code/branches/network/bin/disco.txt	(revision 1445)
+++ code/branches/network/bin/disco.txt	(revision 1446)
@@ -2,3 +2,3 @@
 delay 0.2 Ambient setAmbientLightTest 0,1,0,1
 delay 0.4 Ambient setAmbientLightTest 0,0,1,1
-delay 0.6 exec disco.txt
+delay 0.6 source disco.txt
Index: code/branches/network/bin/irc.tcl
===================================================================
--- code/branches/network/bin/irc.tcl	(revision 1446)
+++ code/branches/network/bin/irc.tcl	(revision 1446)
@@ -0,0 +1,6 @@
+proc every {ms body} { eval $body; after $ms [list every $ms $body] }
+package require irk
+set conn [irk::connect datacore $nickname]
+irk::join $conn #orxonox
+every 25 {}
+vwait termination
Index: code/branches/network/bin/remote.tcl
===================================================================
--- code/branches/network/bin/remote.tcl	(revision 1446)
+++ code/branches/network/bin/remote.tcl	(revision 1446)
@@ -0,0 +1,2 @@
+set telnetserverthreadid [TclThreadManager create]
+TclThreadManager execute $telnetserverthreadid source telnet_server.tcl
Index: code/branches/network/bin/telnet_server.tcl
===================================================================
--- code/branches/network/bin/telnet_server.tcl	(revision 1446)
+++ code/branches/network/bin/telnet_server.tcl	(revision 1446)
@@ -0,0 +1,209 @@
+ #!/usr/bin/env tclsh
+ # Pseudo-telnet server.  Includes basic auth, but no separate identities
+ # or proper multi-threaded operation, so whoever runs this had better
+ # trust those he gives identities/passwords to and they had better trust
+ # each other too.  Note this script does not support command-line arguments.
+
+ ## The names of this array are IP addresses of hosts that are not permitted
+ ## to connect to any of our services.  Admin account(s) can change this
+ ## at run-time, though this info is not maintained across whole-server shutdowns.
+ array set denyHosts {}
+
+ ## Keep the Tcl-thread busy
+ proc every {ms body} { eval $body; after $ms [list every $ms $body] }
+ every 200 {}
+
+ ## Create a server on the given port with the given name/password map
+ ## and the given core interaction handler.
+ proc telnetServer {port {passmap} {handlerCmd remoteCommand}} {
+     if {$port == 0} {
+         return -code error "Only non-zero port numbers are supported"
+     }
+     set server [socket -server [list connect $port $handlerCmd] $port]
+     global passwords services
+     foreach {id pass} $passmap {set passwords($port,$id) $pass}
+     set services($server) $handlerCmd
+     return $server
+ }
+
+ ## Removes the server on the given port, cleaning up the extra state too.
+ proc closedownServer {server} {
+     global services passwords connections auth
+     set port [lindex [fconfigure $server -sockname] 2]
+     catch {close $server}
+     unset services($server)
+     foreach passmap [array names passwords $port,*] {
+         unset passwords($passmap)
+     }
+     # Hmph!  Have to remove unauthorized connections too, though any
+     # connection which has been authorized can continue safely.
+     foreach {client data} [array get connections] {
+         if {$port == [lindex $data 0] && !$auth($client)} {
+             disconnect $client
+         }
+     }
+ }
+
+ ## Handle an incoming connection to the given server
+ proc connect {serverport handlerCmd client clienthost clientport} {
+     global auth cmd denyHosts connections
+     if {[info exist denyHosts($clienthost)]} {
+         puts stdout "${clienthost}:${clientport} attempted connection"
+         catch {puts $client "Connection denied"}
+         catch {close $client}
+         return
+     }
+     puts stdout "${clienthost}:${clientport} connected on $client"
+     fileevent $client readable "handle $serverport $client"
+     set auth($client) 0
+     set cmd($client) $handlerCmd
+     set connections($client) [list $serverport $clienthost $clientport]
+     fconfigure $client -buffering none
+     catch {puts -nonewline $client "Login: "}
+ }
+
+ ## Disconnect the given client, cleaning up any connection-specific data
+ proc disconnect {client} {
+     catch {close $client}
+     global auth cmd connections
+     unset auth($client)
+     unset cmd($client)
+     unset connections($client)
+     puts stdout "$client disconnected"
+ }
+
+ ## Handle data sent from the client.  Log-in is handled directly by this
+ ## procedure, and requires the name and password on the same line
+ proc handle {serverport client} {
+     global passwords auth cmd
+     if {[gets $client line] < 0} {
+         disconnect $client
+         return
+     }
+     if {[string equal $line "quit"] || [string equal $line "exit"]} {
+         disconnect $client
+         return
+     }
+     if {$auth($client)} {
+         eval $cmd($client) [list $client $line 0]
+         eval $cmd($client) [list $client $line 1]
+         return
+     }
+     foreach {id pass} [split $line] {break}
+     if {![info exist pass]} {
+         catch {puts -nonewline $client "Login: "}
+         return
+     }
+     if {
+         [info exist passwords($serverport,$id)] &&
+         [string equal $passwords($serverport,$id) $pass]
+     } then {
+         set auth($client) 1
+         puts stdout "$id logged in on $client"
+         catch {puts $client "Welcome, $id!"}
+         eval $cmd($client) [list $client $line 1]
+         return
+     }
+     puts stdout "AUTH FAILURE ON $client"
+     catch {puts $client "Unknown name or password"}
+     disconnect $client
+ }
+
+ ## Standard handler for logged-in conversations and prompt-generation.
+ proc execCommand {client line prompt} {
+     global tcl_platform
+     if {$prompt} {
+         catch {puts -nonewline $client "\$ "}
+         return
+     }
+     switch $tcl_platform(platform) {
+         unix {
+             catch {exec sh -c $line <@$client >@$client 2>@$client}
+         }
+         default {
+             catch {exec $line} data
+             puts $client $data
+         }
+     }
+ }
+
+ ## Administration service handler.  Chains to the normal handler for
+ ## everything it doesn't recognise itself.
+ proc admin {client line prompt} {
+     if {$prompt} {
+         catch {puts -nonewline $client "# "}
+         return
+     }
+     set cmd [split $line]
+     global denyHosts connections services
+     if {[string equal $line "shutdown"]} {
+         set ::termination 1
+         puts stdout "Shutdown requested on $client"
+         catch {puts $client "System will shut down as soon as possible"}
+         return -code return "SHUTTING DOWN"
+     } elseif {[string equal [lindex $cmd 0] "deny"]} {
+         set denyHosts([lindex $cmd 1]) 1
+     } elseif {[string equal [lindex $cmd 0] "allow"]} {
+         catch {unset denyHosts([lindex $cmd 1])}
+     } elseif {[string equal $line "denied"]} {
+         foreach host [array names denyHosts] {
+             catch {puts $client $host}
+         }
+     } elseif {[string equal $line "connections"]} {
+         set len 0
+         foreach conn [array names connections] {
+             if {$len < [string length $conn]} {
+                 set len [string length $conn]
+             }
+         }
+         foreach {conn details} [array get connections] {
+             catch {puts $client [format "%-*s = %s" $len $conn $details]}
+         }
+     } elseif {[string equal [lindex $cmd 0] "close"]} {
+         set sock [lindex $cmd 1]
+         if {[info exist connections($sock)]} {
+             disconnect $sock
+         }
+     } elseif {[string equal $line "services"]} {
+         set len 0
+         foreach serv [array names services] {
+             if {$len < [string length $serv]} {
+                 set len [string length $serv]
+             }
+         }
+         foreach {serv handler} [array get services] {
+             set port [lindex [fconfigure $serv -sockname] 2]
+             catch {puts $client [format "%-*s (port %d) = handler %s" $len $serv $port $handler]}
+         }
+     } elseif {[string equal [lindex $cmd 0] "addService"]} {
+         set service [eval telnetServer [lrange $cmd 1 end]]
+         catch {puts $client "Created service as $service"}
+     } elseif {[string equal [lindex $cmd 0] "removeService"]} {
+         set service [lindex $cmd 1]
+         if {[info exist services($service)]} {
+             closedownServer $service
+         }
+     } else {
+         # CHAIN TO DEFAULT
+         execCommand $client $line 0
+     }
+ }
+ 
+ ## Executes a given command
+ proc remoteCommand {client line prompt} {
+     global tcl_platform
+     if {$prompt} {
+         catch {puts -nonewline $client "\$ "}
+         return
+     }
+     catch {eval $line} data
+     puts $client $data
+ }
+
+ telnetServer 2560 {orxonox rocks} remoteCommand
+ telnetServer 2561 {orxadmin *****} admin
+
+ puts stdout "Ready for service"
+
+ vwait termination
+ execute exit
Index: code/branches/network/cmake/FindBoost.cmake
===================================================================
--- code/branches/network/cmake/FindBoost.cmake	(revision 1445)
+++ code/branches/network/cmake/FindBoost.cmake	(revision 1446)
@@ -102,4 +102,6 @@
 SET(SUFFIX_FOR_PATH
  boost
+ boost-1_35_0
+ boost-1_35
  boost-1_34_1
  boost-1_34_0
@@ -113,5 +115,9 @@
 #
 IF(WIN32)
-  SET(Boost_INCLUDE_DIR ../libs/boost_1_33_1)
+  SET(Boost_INCLUDE_DIR
+#    ../libs/boost_1_33_1
+    ../libs/boost_1_34_1
+#    ../libs/boost_1_35_0
+  )
 ELSE(WIN32)
   FIND_PATH(Boost_INCLUDE_DIR NAMES boost/config.hpp PATH_SUFFIXES ${SUFFIX_FOR_PATH} PATHS
@@ -188,4 +194,6 @@
   gcc-1_33_1
   gcc-mt-1_33_1
+  mgw34-mt-1_34_1
+  mgw34-mt-1_35
 )
 
Index: code/branches/network/src/audio/AudioStream.cc
===================================================================
--- code/branches/network/src/audio/AudioStream.cc	(revision 1445)
+++ code/branches/network/src/audio/AudioStream.cc	(revision 1446)
@@ -117,5 +117,7 @@
 
 	    for(int i = 0; i < vorbisComment->comments; i++)
+	    {
 	        COUT(3) << "   " << vorbisComment->user_comments[i] << std::endl;
+	    }
 
 	    COUT(3) << std::endl;
Index: code/branches/network/src/core/ArgumentCompleter.h
===================================================================
--- code/branches/network/src/core/ArgumentCompleter.h	(revision 1446)
+++ code/branches/network/src/core/ArgumentCompleter.h	(revision 1446)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ArgumentCompleter_H__
+#define _ArgumentCompleter_H__
+
+#include "CorePrereqs.h"
+#include "ArgumentCompletionListElement.h"
+
+namespace orxonox
+{
+    class _CoreExport ArgumentCompleter
+    {
+        public:
+            ArgumentCompleter(ArgumentCompletionList (*function) (void)) : paramCount_(0), function_0_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1)) : paramCount_(1), function_1_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2)) : paramCount_(2), function_2_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3)) : paramCount_(3), function_3_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4)) : paramCount_(4), function_4_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)) : paramCount_(5), function_5_(function) {}
+
+            ArgumentCompletionList operator()(const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "")
+            {
+                switch (this->paramCount_)
+                {
+                    case 0:
+                        return (*this->function_0_)();
+                    case 1:
+                        return (*this->function_1_)(param1);
+                    case 2:
+                        return (*this->function_2_)(param1, param2);
+                    case 3:
+                        return (*this->function_3_)(param1, param2, param3);
+                    case 4:
+                        return (*this->function_4_)(param1, param2, param3, param4);
+                    case 5:
+                        return (*this->function_5_)(param1, param2, param3, param4, param5);
+                    default:
+                        return ArgumentCompletionList();
+                }
+            }
+
+        private:
+            unsigned char paramCount_;
+            ArgumentCompletionList (*function_0_) (void);
+            ArgumentCompletionList (*function_1_) (const std::string& param1);
+            ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2);
+            ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3);
+            ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4);
+            ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5);
+    };
+}
+
+#endif /* _ArgumentCompleter_H__ */
Index: code/branches/network/src/core/ArgumentCompletionFunctions.cc
===================================================================
--- code/branches/network/src/core/ArgumentCompletionFunctions.cc	(revision 1446)
+++ code/branches/network/src/core/ArgumentCompletionFunctions.cc	(revision 1446)
@@ -0,0 +1,144 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <iostream>
+#include <map>
+
+#include "boost/filesystem.hpp"
+
+#include "ArgumentCompletionFunctions.h"
+#include "CoreIncludes.h"
+#include "Identifier.h"
+#include "ConfigValueContainer.h"
+#include "TclThreadManager.h"
+#include "util/Convert.h"
+#include "util/String.h"
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
+        {
+            return ArgumentCompletionList();
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
+        {
+            ArgumentCompletionList dirlist;
+            ArgumentCompletionList filelist;
+
+            try
+            {
+                boost::filesystem::path input(fragment);
+                boost::filesystem::path startdirectory(input.branch_path());
+
+                if (!boost::filesystem::exists(startdirectory))
+                {
+                    startdirectory = ".";
+                }
+#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
+                else
+                {
+                    std::string dir = startdirectory.string();
+                    if (dir.size() > 0 && dir[dir.size() - 1] == ':')
+                        startdirectory = dir + "/";
+                }
+#endif
+
+                boost::filesystem::directory_iterator file(startdirectory);
+                boost::filesystem::directory_iterator end;
+
+                while (file != end)
+                {
+                    if (boost::filesystem::is_directory(*file))
+                        dirlist.push_back(ArgumentCompletionListElement((*file).string() + "/", getLowercase((*file).string()) + "/", (*file).leaf() + "/"));
+                    else
+                        filelist.push_back(ArgumentCompletionListElement((*file).string(), getLowercase((*file).string()), (*file).leaf()));
+                    ++file;
+                }
+            }
+            catch (...) {}
+
+            filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
+            return filelist;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(configvalueclasses)()
+        {
+            ArgumentCompletionList classlist;
+
+            for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getIdentifierMapBegin(); it != Identifier::getIdentifierMapEnd(); ++it)
+                if ((*it).second->hasConfigValues())
+                    classlist.push_back(ArgumentCompletionListElement((*it).second->getName(), getLowercase((*it).first)));
+
+            return classlist;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(configvalues)(const std::string& fragment, const std::string& classname)
+        {
+            ArgumentCompletionList configvalues;
+            std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getIdentifierMap().find(classname);
+
+            if (identifier != Identifier::getIdentifierMapEnd() && (*identifier).second->hasConfigValues())
+            {
+                for (std::map<std::string, ConfigValueContainer*>::const_iterator it = (*identifier).second->getConfigValueMapBegin(); it != (*identifier).second->getConfigValueMapEnd(); ++it)
+                    configvalues.push_back(ArgumentCompletionListElement((*it).second->getName(), getLowercase((*it).first)));
+            }
+
+            return configvalues;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(configvalue)(const std::string& fragment, const std::string& varname, const std::string& classname)
+        {
+            ArgumentCompletionList oldvalue;
+            std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getLowercaseIdentifierMap().find(getLowercase(classname));
+            if (identifier != Identifier::getLowercaseIdentifierMapEnd())
+            {
+                std::map<std::string, ConfigValueContainer*>::const_iterator variable = (*identifier).second->getLowercaseConfigValueMap().find(getLowercase(varname));
+                if (variable != (*identifier).second->getLowercaseConfigValueMapEnd())
+                {
+                    std::string valuestring = (*variable).second->toString();
+                    oldvalue.push_back(ArgumentCompletionListElement(valuestring, getLowercase(valuestring), "Old value: " + valuestring));
+                }
+            }
+            return oldvalue;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
+        {
+            std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
+            ArgumentCompletionList threads;
+
+            for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
+                threads.push_back(ArgumentCompletionListElement(getConvertedValue<unsigned int, std::string>(*it)));
+
+            return threads;
+        }
+    }
+}
Index: code/branches/network/src/core/ArgumentCompletionFunctions.h
===================================================================
--- code/branches/network/src/core/ArgumentCompletionFunctions.h	(revision 1446)
+++ code/branches/network/src/core/ArgumentCompletionFunctions.h	(revision 1446)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ArgumentCompletionFunctions_H__
+#define _ArgumentCompletionFunctions_H__
+
+#include "CorePrereqs.h"
+#include "ArgumentCompleter.h"
+
+
+#define ARGUMENT_COMPLETION_FUNCTION_DECLARATION(functionname) \
+    ArgumentCompleter* functionname(); \
+    _CoreExport ArgumentCompletionList acf_##functionname
+
+#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(functionname) \
+    ArgumentCompleter* functionname() \
+    { \
+        static ArgumentCompleter completer = ArgumentCompleter(&acf_##functionname); \
+        return &completer; \
+    } \
+    \
+    ArgumentCompletionList acf_##functionname
+
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(fallback)();
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(files)(const std::string& fragment);
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(configvalueclasses)();
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(configvalues)(const std::string& fragment, const std::string& classname);
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(configvalue)(const std::string& fragment, const std::string& varname, const std::string& classname);
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(tclthreads)();
+    }
+}
+
+#endif /* _ArgumentCompletionFunctions_H__ */
Index: code/branches/network/src/core/ArgumentCompletionListElement.h
===================================================================
--- code/branches/network/src/core/ArgumentCompletionListElement.h	(revision 1446)
+++ code/branches/network/src/core/ArgumentCompletionListElement.h	(revision 1446)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ArgumentCompletionListElement_H__
+#define _ArgumentCompletionListElement_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <list>
+
+#define ACL_MODE_NORMAL    1
+#define ACL_MODE_LOWERCASE 2
+#define ACL_MODE_DISPLAY   4
+
+namespace orxonox
+{
+    typedef std::list<ArgumentCompletionListElement> ArgumentCompletionList;
+
+    class _CoreExport ArgumentCompletionListElement
+    {
+        public:
+            ArgumentCompletionListElement(const std::string& normalcase) : mode_(ACL_MODE_NORMAL), normalCase_(normalcase) {}
+            ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE), normalCase_(normalcase), lowerCase_(lowercase) {}
+            ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase, const std::string& display) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE | ACL_MODE_DISPLAY), normalCase_(normalcase), lowerCase_(lowercase), display_(display) {}
+
+            const std::string& getString() const
+                { return this->normalCase_; }
+            const std::string& getComparable() const
+                { if (this->mode_ & ACL_MODE_LOWERCASE) { return this->lowerCase_; } else { return this->normalCase_; } }
+            const std::string& getDisplay() const
+                { if (this->mode_ & ACL_MODE_DISPLAY) { return this->display_; } else { return this->normalCase_; } }
+
+            bool lowercaseComparison() const
+                { return (this->mode_ & ACL_MODE_LOWERCASE); }
+
+            bool operator<(const ArgumentCompletionListElement& other) const
+                { return (this->getComparable() < other.getComparable()); }
+
+        private:
+            unsigned char mode_;
+            std::string normalCase_;
+            std::string lowerCase_;
+            std::string display_;
+    };
+}
+
+#endif /* _ArgumentCompletionListElement_H__ */
Index: code/branches/network/src/core/CMakeLists.txt
===================================================================
--- code/branches/network/src/core/CMakeLists.txt	(revision 1445)
+++ code/branches/network/src/core/CMakeLists.txt	(revision 1446)
@@ -2,5 +2,4 @@
   BaseObject.cc
   ClassTreeMask.cc
-  CommandExecutor.cc
   ConfigFileManager.cc
   ConfigValueContainer.cc
@@ -11,7 +10,14 @@
   Identifier.cc
   IdentifierDistributor.cc
-  InputBuffer.cc
   InputManager.cc
   KeyBinder.cc
+  OutputBuffer.cc
+  InputBuffer.cc
+  Shell.cc
+  CommandExecutor.cc
+  CommandEvaluation.cc
+  ConsoleCommand.cc
+  ArgumentCompletionFunctions.cc
+  ConsoleCommandCompilation.cc
   Language.cc
   Loader.cc
@@ -26,4 +32,6 @@
   Tickable.cc
   XMLPort.cc
+  TclThreadManager.cc
+  IRC.cc
   tolua/tolua_bind.cc
 )
@@ -37,5 +45,9 @@
 )
 
-ADD_LIBRARY(core SHARED ${CORE_SRC_FILES})
+IF(WIN32)
+  ADD_LIBRARY(core ${CORE_SRC_FILES})
+ELSE(WIN32)
+  ADD_LIBRARY(core SHARED ${CORE_SRC_FILES})
+ENDIF(WIN32)
 
 TARGET_LINK_LIBRARIES(core
@@ -47,3 +59,5 @@
   ois
   util
+  ${Boost_thread_LIBRARIES}
+  ${Boost_filesystem_LIBRARIES}
 )
Index: code/branches/network/src/core/ClassManager.h
===================================================================
--- code/branches/network/src/core/ClassManager.h	(revision 1445)
+++ code/branches/network/src/core/ClassManager.h	(revision 1446)
@@ -49,4 +49,5 @@
 #include "Identifier.h"
 #include "IdentifierDistributor.h"
+#include "Debug.h"
 
 namespace orxonox
Index: code/branches/network/src/core/CommandEvaluation.cc
===================================================================
--- code/branches/network/src/core/CommandEvaluation.cc	(revision 1446)
+++ code/branches/network/src/core/CommandEvaluation.cc	(revision 1446)
@@ -0,0 +1,311 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CommandEvaluation.h"
+#include "ConsoleCommand.h"
+#include "Debug.h"
+#include "util/String.h"
+
+namespace orxonox
+{
+    CommandEvaluation::CommandEvaluation()
+    {
+        this->initialize("");
+        this->state_ = CS_Uninitialized;
+    }
+
+    void CommandEvaluation::initialize(const std::string& command)
+    {
+        this->bNewCommand_ = true;
+        this->bCommandChanged_ = false;
+        this->originalCommand_ = command;
+        this->command_ = command;
+        this->commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
+
+        this->additionalParameter_ = "";
+
+        this->bEvaluatedParams_ = false;
+
+        this->listOfPossibleIdentifiers_.clear();
+        this->listOfPossibleFunctions_.clear();
+        this->listOfPossibleArguments_.clear();
+
+        this->functionclass_ = 0;
+        this->function_ = 0;
+        this->possibleArgument_ = "";
+        this->argument_ = "";
+
+        this->errorMessage_ = "";
+        this->state_ = CS_Empty;
+    }
+
+    bool CommandEvaluation::isValid() const
+    {
+        return (this->function_);
+    }
+
+    bool CommandEvaluation::execute() const
+    {
+        if (!this->isValid())
+            return false;
+
+        if (this->bEvaluatedParams_ && this->function_)
+        {
+            COUT(4) << "CE_execute (evaluation): " << this->function_->getName() << " " << this->param_[0] << " " << this->param_[1] << " " << this->param_[2] << " " << this->param_[3] << " " << this->param_[4] << std::endl;
+            (*this->function_)(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
+            return true;
+        }
+
+        if (!this->bCommandChanged_ || removeTrailingWhitespaces(this->command_) == removeTrailingWhitespaces(this->originalCommand_))
+        {
+            COUT(4) << "CE_execute: " << this->command_ << "\n";
+
+            unsigned int startindex = this->getStartindex();
+            if (this->commandTokens_.size() > startindex)
+                return this->function_->parse(removeSlashes(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter()));
+            else
+                return this->function_->parse(removeSlashes(this->additionalParameter_));
+        }
+
+        return false;
+    }
+
+    std::string CommandEvaluation::complete()
+    {
+        if (!this->bNewCommand_)
+        {
+            switch (this->state_)
+            {
+                case CS_Uninitialized:
+                    break;
+                case CS_Empty:
+                    break;
+                case CS_ShortcutOrIdentifier:
+                    if (this->function_)
+                    {
+                        if (this->function_->getParamCount() == 0)
+                            return (this->command_ = this->function_->getName());
+                        else
+                            return (this->command_ = this->function_->getName() + " ");
+                    }
+                    else if (this->functionclass_)
+                        return (this->command_ = this->functionclass_->getName() + " ");
+                    break;
+                case CS_Function:
+                    if (this->function_)
+                    {
+                        if (this->function_->getParamCount() == 0)
+                            return (this->command_ = this->functionclass_->getName() + " " + this->function_->getName());
+                        else
+                            return (this->command_ = this->functionclass_->getName() + " " + this->function_->getName() + " ");
+                    }
+                    break;
+                case CS_ParamPreparation:
+                case CS_Params:
+                {
+                    if (this->argument_ == "" && this->possibleArgument_ == "")
+                        break;
+
+                    unsigned int maxIndex = this->commandTokens_.size();
+                    if (this->command_[this->command_.size() - 1] != ' ')
+                        maxIndex -= 1;
+                    std::string whitespace = "";
+
+                    if (this->possibleArgument_ != "")
+                    {
+                        this->argument_ = this->possibleArgument_;
+                        if (this->function_->getParamCount() > (maxIndex + 1 - this->getStartindex()))
+                            whitespace = " ";
+                    }
+
+                    return (this->command_ = this->commandTokens_.subSet(0, maxIndex).join() + " " + this->argument_ + whitespace);
+                    break;
+                }
+                case CS_Finished:
+                    break;
+                case CS_Error:
+                    break;
+            }
+        }
+        this->bNewCommand_ = false;
+        return this->command_;
+    }
+
+    std::string CommandEvaluation::hint() const
+    {
+        switch (this->state_)
+        {
+            case CS_Uninitialized:
+                break;
+            case CS_Empty:
+            case CS_ShortcutOrIdentifier:
+                if (this->listOfPossibleFunctions_.size() == 0)
+                    return CommandEvaluation::dump(this->listOfPossibleIdentifiers_);
+                else if (this->listOfPossibleIdentifiers_.size() == 0)
+                    return CommandEvaluation::dump(this->listOfPossibleFunctions_);
+                else
+                    return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandEvaluation::dump(this->listOfPossibleIdentifiers_));
+                break;
+            case CS_Function:
+                return CommandEvaluation::dump(this->listOfPossibleFunctions_);
+                break;
+            case CS_ParamPreparation:
+            case CS_Params:
+                if (this->listOfPossibleArguments_.size() > 0)
+                    return CommandEvaluation::dump(this->listOfPossibleArguments_);
+                else
+                    return CommandEvaluation::dump(this->function_);
+            case CS_Finished:
+                if (this->function_)
+                    return CommandEvaluation::dump(this->function_);
+                break;
+            case CS_Error:
+                return this->errorMessage_;
+                break;
+        }
+
+        return "";
+    }
+
+    void CommandEvaluation::evaluateParams()
+    {
+        this->bEvaluatedParams_ = false;
+
+        for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
+            this->param_[i] = MT_null;
+
+        if (!this->isValid())
+            return;
+
+        unsigned int startindex = this->getStartindex();
+
+        if (this->commandTokens_.size() <= startindex)
+        {
+            if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
+                this->bEvaluatedParams_ = true;
+        }
+        else if (this->commandTokens_.size() > startindex)
+        {
+            if (this->function_->evaluate(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter(), this->param_, " "))
+                this->bEvaluatedParams_ = true;
+        }
+    }
+
+    void CommandEvaluation::setEvaluatedParameter(unsigned int index, MultiTypeMath param)
+    {
+        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
+            this->param_[index] = param;
+    }
+
+    MultiTypeMath CommandEvaluation::getEvaluatedParameter(unsigned int index) const
+    {
+        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
+            return this->param_[index];
+
+        return MT_null;
+    }
+
+    bool CommandEvaluation::hasReturnvalue() const
+    {
+        if (this->function_)
+            return this->function_->hasReturnvalue();
+
+        return MT_null;
+    }
+
+    MultiTypeMath CommandEvaluation::getReturnvalue() const
+    {
+        if (this->function_)
+            return this->function_->getReturnvalue();
+
+        return MultiTypeMath();
+    }
+
+
+    unsigned int CommandEvaluation::getStartindex() const
+    {
+        if (this->functionclass_ && this->function_)
+            return 2;
+        else if (this->function_)
+            return 1;
+        else
+            return 0;
+    }
+
+    std::string CommandEvaluation::dump(const std::list<std::pair<const std::string*, const std::string*> >& list)
+    {
+        std::string output = "";
+        for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                output += " ";
+
+            output += *(*it).second;
+        }
+        return output;
+    }
+
+    std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
+    {
+        std::string output = "";
+        for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                output += " ";
+
+            output += (*it).getDisplay();
+        }
+        return output;
+    }
+
+    std::string CommandEvaluation::dump(const ConsoleCommand* command)
+    {
+        std::string output = command->getName();
+        if (command->getParamCount() > 0)
+            output += ": ";
+
+        for (unsigned int i = 0; i < command->getParamCount(); i++)
+        {
+            if (i != 0)
+                output += " ";
+
+            if (command->defaultValueSet(i))
+                output += "[";
+            else
+                output += "{";
+
+            output += command->getTypenameParam(i);
+
+            if (command->defaultValueSet(i))
+                output += "=" + command->getDefaultValue(i).toString() + "]";
+            else
+                output += "}";
+        }
+        return output;
+    }
+}
Index: code/branches/network/src/core/CommandEvaluation.h
===================================================================
--- code/branches/network/src/core/CommandEvaluation.h	(revision 1446)
+++ code/branches/network/src/core/CommandEvaluation.h	(revision 1446)
@@ -0,0 +1,121 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _CommandEvaluation_H__
+#define _CommandEvaluation_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <list>
+
+#include "ArgumentCompletionListElement.h"
+#include "util/SubString.h"
+#include "util/MultiTypeMath.h"
+
+namespace orxonox
+{
+    enum CommandState
+    {
+        CS_Uninitialized,
+        CS_Empty,
+        CS_ShortcutOrIdentifier,
+        CS_Function,
+        CS_ParamPreparation,
+        CS_Params,
+        CS_Finished,
+        CS_Error
+    };
+
+    class _CoreExport CommandEvaluation
+    {
+        friend class CommandExecutor;
+
+        public:
+            CommandEvaluation();
+
+            void initialize(const std::string& command);
+
+            bool execute() const;
+            std::string complete();
+            std::string hint() const;
+            void evaluateParams();
+
+            bool isValid() const;
+
+            inline ConsoleCommand* getConsoleCommand() const
+                { return this->function_; }
+            inline const std::string& getOriginalCommand() const
+                { return this->originalCommand_; }
+            inline const std::string& getCommand() const
+                { return this->command_; }
+
+            inline void setAdditionalParameter(const std::string& param)
+                { this->additionalParameter_ = param; this->bEvaluatedParams_ = false; }
+            inline std::string getAdditionalParameter() const
+                { return (this->additionalParameter_ != "") ? (" " + this->additionalParameter_) : ""; }
+
+            void setEvaluatedParameter(unsigned int index, MultiTypeMath param);
+            MultiTypeMath getEvaluatedParameter(unsigned int index) const;
+
+            bool hasReturnvalue() const;
+            MultiTypeMath getReturnvalue() const;
+
+        private:
+            unsigned int getStartindex() const;
+            static std::string dump(const std::list<std::pair<const std::string*, const std::string*> >& list);
+            static std::string dump(const ArgumentCompletionList& list);
+            static std::string dump(const ConsoleCommand* command);
+
+
+            bool bNewCommand_;
+            bool bCommandChanged_;
+
+            std::string originalCommand_;
+            std::string command_;
+            SubString commandTokens_;
+            std::string additionalParameter_;
+
+            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleIdentifiers_;
+            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
+            ArgumentCompletionList listOfPossibleArguments_;
+
+            Identifier* functionclass_;
+            ConsoleCommand* function_;
+            std::string possibleArgument_;
+            std::string argument_;
+
+            std::string errorMessage_;
+            CommandState state_;
+
+            bool bEvaluatedParams_;
+            MultiTypeMath param_[5];
+    };
+}
+
+#endif /* _CommandEvaluation_H__ */
Index: code/branches/network/src/core/CommandExecutor.cc
===================================================================
--- code/branches/network/src/core/CommandExecutor.cc	(revision 1445)
+++ code/branches/network/src/core/CommandExecutor.cc	(revision 1446)
@@ -31,303 +31,11 @@
 #include "util/String.h"
 #include "util/Convert.h"
-#include "util/SubString.h"
 #include "Identifier.h"
 #include "Language.h"
 #include "Debug.h"
-#include "Executor.h"
-#include "ConfigValueContainer.h"
 #include "TclBind.h"
-
-#define COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE "set"
-#define COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY "tset"
-#define COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND "bind"
 
 namespace orxonox
 {
-    ConsoleCommandShortcutGeneric(keyword1, createExecutor((FunctorStatic*)0, "set", AccessLevel::User));
-    ConsoleCommandShortcutGeneric(keyword2, createExecutor((FunctorStatic*)0, "tset", AccessLevel::User));
-    ConsoleCommandShortcutGeneric(keyword3, createExecutor((FunctorStatic*)0, "bind", AccessLevel::User));
-
-    ConsoleCommandShortcutExtern(exec, AccessLevel::None);
-    ConsoleCommandShortcutExtern(echo, AccessLevel::None);
-
-    ConsoleCommandShortcutExtern(read, AccessLevel::None);
-    ConsoleCommandShortcutExtern(append, AccessLevel::None);
-    ConsoleCommandShortcutExtern(write, AccessLevel::None);
-
-    void exec(const std::string& filename)
-    {
-        static std::set<std::string> executingFiles;
-
-        std::set<std::string>::const_iterator it = executingFiles.find(filename);
-        if (it != executingFiles.end())
-        {
-            COUT(1) << "Error: Recurring exec command in \"" << filename << "\". Stopped execution." << std::endl;
-            return;
-        }
-
-        // Open the file
-        std::ifstream file;
-        file.open(filename.c_str(), std::fstream::in);
-
-        if (!file.is_open())
-        {
-            COUT(1) << "Error: Couldn't execute file \"" << filename << "\"." << std::endl;
-            return;
-        }
-
-        executingFiles.insert(filename);
-
-        // Iterate through the file and put the lines into the CommandExecutor
-        char line[1024];
-        while (file.good() && !file.eof())
-        {
-            file.getline(line, 1024);
-            CommandExecutor::execute(line);
-        }
-
-        executingFiles.erase(filename);
-        file.close();
-    }
-
-    std::string echo(const std::string& text)
-    {
-        return text;
-    }
-
-    void write(const std::string& filename, const std::string& text)
-    {
-        std::ofstream file;
-        file.open(filename.c_str(), std::fstream::out);
-
-        if (!file.is_open())
-        {
-            COUT(1) << "Error: Couldn't write to file \"" << filename << "\"." << std::endl;
-            return;
-        }
-
-        file << text << std::endl;
-        file.close();
-    }
-
-    void append(const std::string& filename, const std::string& text)
-    {
-        std::ofstream file;
-        file.open(filename.c_str(), std::fstream::app);
-
-        if (!file.is_open())
-        {
-            COUT(1) << "Error: Couldn't append to file \"" << filename << "\"." << std::endl;
-            return;
-        }
-
-        file << text << std::endl;
-        file.close();
-    }
-
-    std::string read(const std::string& filename)
-    {
-        std::ifstream file;
-        file.open(filename.c_str(), std::fstream::in);
-
-        if (!file.is_open())
-        {
-            COUT(1) << "Error: Couldn't read from file \"" << filename << "\"." << std::endl;
-            return "";
-        }
-
-        std::string output = "";
-        char line[1024];
-        while (file.good() && !file.eof())
-        {
-            file.getline(line, 1024);
-            output += line;
-            output += "\n";
-        }
-
-        file.close();
-
-        return output;
-    }
-
-
-    ///////////////////////
-    // CommandEvaluation //
-    ///////////////////////
-    CommandEvaluation::CommandEvaluation()
-    {
-        this->processedCommand_ = "";
-        this->additionalParameter_ = "";
-
-        this->functionclass_ = 0;
-        this->configvalueclass_ = 0;
-        this->shortcut_ = 0;
-        this->function_ = 0;
-        this->configvalue_ = 0;
-        this->key_ = 0;
-
-        this->errorMessage_ = "";
-        this->state_ = CS_Uninitialized;
-
-        this->bEvaluatedParams_ = false;
-        this->evaluatedExecutor_ = 0;
-    }
-
-    KeybindMode::Enum CommandEvaluation::getKeybindMode()
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-//            if (this->shortcut_ != 0)
-//                return this->shortcut_->getKeybindMode();
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-//            if (this->function_ != 0)
-//                return this->function_->getKeybindMode();
-        }
-        else if (this->state_ == CS_ConfigValueType || this->state_ == CS_ConfigValueFinished)
-        {
-//            return KeybindMode::onPress;
-        }
-        else if (this->state_ == CS_KeybindCommand || this->state_ == CS_KeybindFinished)
-        {
-//            return KeybindMode::onPress;
-        }
-        else
-        {
-//            return KeybindMode::onPress;
-        }
-        // FIXME: Had to insert a return statement
-        return (KeybindMode::Enum)0;
-    }
-
-    bool CommandEvaluation::isValid() const
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            return this->shortcut_;
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            return (this->functionclass_ && this->function_);
-        }
-        else if (this->state_ == CS_ConfigValueType || this->state_ == CS_ConfigValueFinished)
-        {
-            return (this->configvalueclass_ && this->configvalue_);
-        }
-        else if (this->state_ == CS_KeybindCommand || this->state_ == CS_KeybindFinished)
-        {
-            return this->key_;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    void CommandEvaluation::evaluateParams()
-    {
-        this->bEvaluatedParams_ = false;
-        this->evaluatedExecutor_ = 0;
-
-        for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
-            this->param_[i] = MT_null;
-
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            if (this->shortcut_)
-            {
-                if (this->tokens_.size() <= 1)
-                {
-                    if (this->shortcut_->evaluate(this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->shortcut_;
-                    }
-                }
-                else if (this->tokens_.size() > 1)
-                {
-                    if (this->shortcut_->evaluate(this->tokens_.subSet(1).join() + this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->shortcut_;
-                    }
-                }
-            }
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            if (this->function_)
-            {
-                if (this->tokens_.size() <= 2)
-                {
-                    if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->function_;
-                    }
-                }
-                else if (this->tokens_.size() > 2)
-                {
-                    if (this->function_->evaluate(this->tokens_.subSet(2).join() + this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->function_;
-                    }
-                }
-            }
-        }
-    }
-
-    void CommandEvaluation::setEvaluatedParameter(unsigned int index, MultiTypeMath param)
-    {
-        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
-            this->param_[index] = param;
-    }
-
-    MultiTypeMath CommandEvaluation::getEvaluatedParameter(unsigned int index) const
-    {
-        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
-            return this->param_[index];
-
-        return MT_null;
-    }
-
-    bool CommandEvaluation::hasReturnvalue() const
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            if (this->shortcut_)
-                return this->shortcut_->hasReturnvalue();
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            if (this->function_)
-                return this->function_->hasReturnvalue();
-        }
-
-        return MT_null;
-    }
-
-    MultiTypeMath CommandEvaluation::getReturnvalue() const
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            if (this->shortcut_)
-                return this->shortcut_->getReturnvalue();
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            if (this->function_)
-                return this->function_->getReturnvalue();
-        }
-
-        return MT_null;
-    }
-
-
-    /////////////////////
-    // CommandExecutor //
-    /////////////////////
     CommandExecutor& CommandExecutor::getInstance()
     {
@@ -346,9 +54,16 @@
     }
 
-    Executor& CommandExecutor::addConsoleCommandShortcut(ExecutorStatic* executor)
-    {
-        CommandExecutor::getInstance().consoleCommandShortcuts_[executor->getName()] = executor;
-        CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(executor->getName())] = executor;
-        return (*executor);
+    ConsoleCommand& CommandExecutor::addConsoleCommandShortcut(ConsoleCommand* command)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(command->getName());
+        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
+        {
+            COUT(2) << "Warning: Overwriting console-command shortcut with name " << command->getName() << "." << std::endl;
+        }
+
+
+        CommandExecutor::getInstance().consoleCommandShortcuts_[command->getName()] = command;
+        CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(command->getName())] = command;
+        return (*command);
     }
 
@@ -358,7 +73,7 @@
         @return The executor of the requested console command shortcut
     */
-    ExecutorStatic* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
+    ConsoleCommand* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
         if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
             return (*it).second;
@@ -372,7 +87,7 @@
         @return The executor of the requested console command shortcut
     */
-    ExecutorStatic* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
+    ConsoleCommand* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
         if (it != CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end())
             return (*it).second;
@@ -384,866 +99,407 @@
     {
         if (useTcl)
-        {
             return TclBind::eval(command);
-        }
-        else
-        {
-            if ((CommandExecutor::getEvaluation().processedCommand_ != command) || (CommandExecutor::getEvaluation().state_ == CS_Uninitialized))
-                CommandExecutor::parse(command);
-
-            return CommandExecutor::execute(CommandExecutor::getEvaluation());
-        }
-    }
-
-
-    bool CommandExecutor::execute(const CommandEvaluation& evaluation)
-    {
-        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
-        if (evaluation.bEvaluatedParams_ && evaluation.evaluatedExecutor_)
-        {
-//std::cout << "CE_execute (evaluation): " << evaluation.evaluatedExecutor_->getName() << " " << evaluation.param_[0] << " " << evaluation.param_[1] << " " << evaluation.param_[2] << " " << evaluation.param_[3] << " " << evaluation.param_[4] << std::endl;
-            (*evaluation.evaluatedExecutor_)(evaluation.param_[0], evaluation.param_[1], evaluation.param_[2], evaluation.param_[3], evaluation.param_[4]);
-            return true;
-        }
-
-//std::cout << "CE_execute: " << evaluation.processedCommand_ << "\n";
-        switch (evaluation.state_)
-        {
-            case CS_Uninitialized:
-                break;
-            case CS_Empty:
-                break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                break;
-            case CS_Shortcut_Params:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_Shortcut_Finished:
-                // call the shortcut
-                if (evaluation.shortcut_)
-                {
-                    if (tokens.size() >= 2)
-                        return evaluation.shortcut_->parse(removeSlashes(tokens.subSet(1).join() + evaluation.getAdditionalParameter()));
-                    else
-                        return evaluation.shortcut_->parse(removeSlashes(evaluation.additionalParameter_));
-                }
-                break;
-            case CS_Function:
-                break;
-            case CS_Function_Params:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_Function_Finished:
-                // call the shortcut
-                if (evaluation.function_)
-                {
-                    if (tokens.size() >= 3)
-                        return evaluation.function_->parse(removeSlashes(tokens.subSet(2).join() + evaluation.getAdditionalParameter()));
-                    else
-                        return evaluation.function_->parse(removeSlashes(evaluation.additionalParameter_));
-                }
-                break;
-            case CS_ConfigValueClass:
-                break;
-            case CS_ConfigValue:
-                break;
-            case CS_ConfigValueType:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_ConfigValueFinished:
-                // set the config value
-                if (evaluation.configvalue_)
-                {
-                    if ((tokens.size() >= 1) && (tokens[0] == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE))
-                    {
-                        if (tokens.size() >= 4)
-                            return evaluation.configvalue_->set(removeSlashes(tokens.subSet(3).join() + evaluation.getAdditionalParameter()));
-                        else
-                            return evaluation.configvalue_->set(removeSlashes(evaluation.additionalParameter_));
-                    }
-                    else if ((tokens.size() >= 1) && (tokens[0] == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
-                    {
-                        if (tokens.size() >= 4)
-                            return evaluation.configvalue_->tset(removeSlashes(tokens.subSet(3).join() + evaluation.getAdditionalParameter()));
-                        else
-                            return evaluation.configvalue_->tset(removeSlashes(evaluation.additionalParameter_));
-                    }
-                }
-                break;
-            case CS_KeybindKey:
-                break;
-            case CS_KeybindCommand:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_KeybindFinished:
-                // set the keybind
-                // ...todo
-                break;
-            case CS_Error:
-                break;
-        }
-
-        return false;
+
+        CommandExecutor::parseIfNeeded(command);
+        return CommandExecutor::getEvaluation().execute();
     }
 
     std::string CommandExecutor::complete(const std::string& command)
     {
-        if ((CommandExecutor::getEvaluation().processedCommand_ != command) || (CommandExecutor::getEvaluation().state_ == CS_Uninitialized))
-            CommandExecutor::parse(command);
-
-        return CommandExecutor::complete(CommandExecutor::getEvaluation());
-    }
-
-    std::string CommandExecutor::complete(const CommandEvaluation& evaluation)
-    {
-        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
-        std::list<std::pair<const std::string*, const std::string*> > temp;
-        if (evaluation.state_ == CS_Empty)
-        {
-            temp.insert(temp.end(), evaluation.listOfPossibleShortcuts_.begin(), evaluation.listOfPossibleShortcuts_.end());
-            temp.insert(temp.end(), evaluation.listOfPossibleFunctionClasses_.begin(), evaluation.listOfPossibleFunctionClasses_.end());
-        }
-
-        switch (evaluation.state_)
-        {
-            case CS_Uninitialized:
-                break;
-            case CS_Empty:
-                return (CommandExecutor::getCommonBegin(temp));
-                break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                break;
-            case CS_Shortcut_Params:
-                if (evaluation.shortcut_)
-                    return (evaluation.shortcut_->getName() + " ");
-                break;
-            case CS_Shortcut_Finished:
-                if (evaluation.shortcut_)
-                {
-                    if (evaluation.shortcut_->getParamCount() == 0)
-                        return (evaluation.shortcut_->getName());
-                    else if (tokens.size() >= 2)
-                        return (evaluation.shortcut_->getName() + " " + tokens.subSet(1).join());
-                }
-                break;
-            case CS_Function:
-                if (evaluation.functionclass_)
-                    return (evaluation.functionclass_->getName() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleFunctions_));
-                break;
-            case CS_Function_Params:
-                if (evaluation.functionclass_ && evaluation.function_)
-                    return (evaluation.functionclass_->getName() + " " + evaluation.function_->getName() + " ");
-                break;
-            case CS_Function_Finished:
-                if (evaluation.functionclass_ && evaluation.function_)
-                {
-                    if (evaluation.function_->getParamCount() == 0)
-                        return (evaluation.functionclass_->getName() + " " + evaluation.function_->getName());
-                    else if (tokens.size() >= 3)
-                        return (evaluation.functionclass_->getName() + " " + evaluation.function_->getName() + " " + tokens.subSet(2).join());
-                }
-                break;
-            case CS_ConfigValueClass:
-                if (tokens.size() >= 1)
-                    return (tokens[0] + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleConfigValueClasses_));
-                break;
-            case CS_ConfigValue:
-                if ((tokens.size() >= 1) && evaluation.configvalueclass_)
-                    return (tokens[0] + " " + evaluation.configvalueclass_->getName() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleConfigValues_));
-                break;
-            case CS_ConfigValueType:
-                if ((tokens.size() >= 1) && evaluation.configvalueclass_ && evaluation.configvalue_)
-                    return (tokens[0] + " " + evaluation.configvalueclass_->getName() + " " + evaluation.configvalue_->getName() + " ");
-                break;
-            case CS_ConfigValueFinished:
-                if ((tokens.size() >= 1) && evaluation.configvalueclass_ && evaluation.configvalue_ && (tokens.size() >= 4))
-                    return (tokens[0] + " " + evaluation.configvalueclass_->getName() + " " + evaluation.configvalue_->getName() + " " + tokens.subSet(3).join());
-                break;
-            case CS_KeybindKey:
-                if (tokens.size() >= 1)
-                    return (tokens[0] + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleKeys_));
-                break;
-            case CS_KeybindCommand:
-                if ((evaluation.processedCommand_.size() >= 1) && (evaluation.processedCommand_[evaluation.processedCommand_.size() - 1] != ' '))
-                    return (evaluation.processedCommand_ + " ");
-                break;
-            case CS_KeybindFinished:
-                break;
-            case CS_Error:
-                break;
-        }
-
-        return evaluation.processedCommand_;
+        CommandExecutor::parseIfNeeded(command);
+        return CommandExecutor::getEvaluation().complete();
     }
 
     std::string CommandExecutor::hint(const std::string& command)
     {
-        if ((CommandExecutor::getEvaluation().processedCommand_ != command) || (CommandExecutor::getEvaluation().state_ == CS_Uninitialized))
-            CommandExecutor::parse(command);
-
-        return CommandExecutor::hint(CommandExecutor::getEvaluation());
-    }
-
-    std::string CommandExecutor::hint(const CommandEvaluation& evaluation)
-    {
-        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
-        switch (evaluation.state_)
-        {
-            case CS_Uninitialized:
-                break;
-            case CS_Empty:
-                return (CommandExecutor::dump(evaluation.listOfPossibleShortcuts_) + "\n" + CommandExecutor::dump(evaluation.listOfPossibleFunctionClasses_));
-                break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                break;
-            case CS_Shortcut_Params:
-                if (evaluation.shortcut_)
-                    return CommandExecutor::dump(evaluation.shortcut_);
-                break;
-            case CS_Shortcut_Finished:
-                if (evaluation.shortcut_)
-                    return CommandExecutor::dump(evaluation.shortcut_);
-                break;
-            case CS_Function:
-                return CommandExecutor::dump(evaluation.listOfPossibleFunctions_);
-                break;
-            case CS_Function_Params:
-                if (evaluation.function_)
-                    return CommandExecutor::dump(evaluation.function_);
-                break;
-            case CS_Function_Finished:
-                if (evaluation.function_)
-                    return CommandExecutor::dump(evaluation.function_);
-                break;
-            case CS_ConfigValueClass:
-                return CommandExecutor::dump(evaluation.listOfPossibleConfigValueClasses_);
-                break;
-            case CS_ConfigValue:
-                return CommandExecutor::dump(evaluation.listOfPossibleConfigValues_);
-                break;
-            case CS_ConfigValueType:
-                if (evaluation.configvalue_)
-                    return CommandExecutor::dump(evaluation.configvalue_);
-                break;
-            case CS_ConfigValueFinished:
-                if (evaluation.configvalue_)
-                    return CommandExecutor::dump(evaluation.configvalue_);
-                break;
-            case CS_KeybindKey:
-                return CommandExecutor::dump(evaluation.listOfPossibleKeys_);
-                break;
-            case CS_KeybindCommand:
-                if (evaluation.key_)
-                    return CommandExecutor::dump(evaluation.key_);
-                break;
-            case CS_KeybindFinished:
-                if (evaluation.key_)
-                    return CommandExecutor::dump(evaluation.key_);
-                break;
-            case CS_Error:
-                return CommandExecutor::getEvaluation().errorMessage_;
-                break;
-        }
-
-        return "";
+        CommandExecutor::parseIfNeeded(command);
+        return CommandExecutor::getEvaluation().hint();
     }
 
     CommandEvaluation CommandExecutor::evaluate(const std::string& command)
     {
-        CommandExecutor::parse(command, true);
-
-        if (CommandExecutor::getEvaluation().tokens_.size() > 0)
-        {
-            std::string lastToken;
-            lastToken = CommandExecutor::getEvaluation().tokens_[CommandExecutor::getEvaluation().tokens_.size() - 1];
-            lastToken = lastToken.substr(0, lastToken.size() - 1);
-            CommandExecutor::getEvaluation().tokens_.pop_back();
-            CommandExecutor::getEvaluation().tokens_.append(SubString(lastToken, " ", "", true, '\0', false, '\0', false, '\0', '\0', false, '\0'));
-        }
-
+        CommandExecutor::parse(command);
         CommandExecutor::getEvaluation().evaluateParams();
         return CommandExecutor::getEvaluation();
     }
 
+    void CommandExecutor::parseIfNeeded(const std::string& command)
+    {
+        if (CommandExecutor::getEvaluation().state_ == CS_Uninitialized)
+        {
+            CommandExecutor::parse(command);
+        }
+        else if (CommandExecutor::getEvaluation().originalCommand_ != command)
+        {
+            if (CommandExecutor::getEvaluation().command_ == command)
+            {
+                CommandExecutor::parse(command);
+                CommandExecutor::getEvaluation().bNewCommand_ = false;
+            }
+            else
+            {
+                CommandExecutor::parse(command);
+            }
+        }
+    }
+
     void CommandExecutor::parse(const std::string& command, bool bInitialize)
     {
-        CommandExecutor::getEvaluation().tokens_.split((command + COMMAND_EXECUTOR_CURSOR), " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-        CommandExecutor::getEvaluation().processedCommand_ = command;
-
         if (bInitialize)
-            CommandExecutor::initialize(command);
+            CommandExecutor::getEvaluation().initialize(command);
+
+        CommandExecutor::getEvaluation().commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
+        CommandExecutor::getEvaluation().command_ = command;
 
         switch (CommandExecutor::getEvaluation().state_)
         {
             case CS_Uninitialized:
+            {
                 // Impossible
                 break;
+            }
             case CS_Empty:
+            {
                 if (CommandExecutor::argumentsGiven() == 0)
                 {
-                    // We want a hint for the first token
-                    // Check if there is already a perfect match
-                    CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(CommandExecutor::getToken(0));
-                    CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(CommandExecutor::getToken(0));
-
-                    if ((CommandExecutor::getEvaluation().functionclass_) || (CommandExecutor::getEvaluation().shortcut_))
-                    {
-                        // Yes, there is a class or a shortcut with the searched name
-                        // Add a whitespace and continue parsing
-                        CommandExecutor::getEvaluation().state_ = CS_FunctionClass_Or_Shortcut_Or_Keyword;
-                        CommandExecutor::parse(command + " ", false);
+                    CommandExecutor::createListOfPossibleFunctions("");
+                    CommandExecutor::createListOfPossibleIdentifiers("");
+                    break;
+                }
+                else
+                {
+                    CommandExecutor::getEvaluation().state_ = CS_ShortcutOrIdentifier;
+                    // Move on to next case
+                }
+            }
+            case CS_ShortcutOrIdentifier:
+            {
+                if (CommandExecutor::argumentsGiven() > 1)
+                {
+                    // There's a finished first argument - check if it's a shortcut or a classname
+                    CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
+                    CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
+
+                    if (CommandExecutor::getEvaluation().function_)
+                    {
+                        // It's a shortcut
+                        CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                        CommandExecutor::getEvaluation().functionclass_ = 0;
+                        // Move on to next case
+                    }
+                    else if (CommandExecutor::getEvaluation().functionclass_)
+                    {
+                        // It's a functionname
+                        CommandExecutor::getEvaluation().state_ = CS_Function;
+                        CommandExecutor::getEvaluation().function_ = 0;
+                        // Move on to next case
+                    }
+                    else
+                    {
+                        // The first argument is bad
+                        CommandExecutor::getEvaluation().state_ = CS_Error;
+                        AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
+                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(0) + " " + GetLocalisation("commandexecutorunknownfirstargument") + ".";
                         return;
                     }
-
-                    // No perfect match: Create the lists of all possible classes and shortcuts and return
-                    CommandExecutor::createListOfPossibleFunctionClasses(CommandExecutor::getToken(0));
-                    CommandExecutor::createListOfPossibleShortcuts(CommandExecutor::getToken(0));
-
-                    // Check if there's only one possiblility
-                    if ((CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.size() == 1) && (CommandExecutor::getEvaluation().listOfPossibleShortcuts_.size() == 0))
-                    {
-                        // There's only one possible class
+                }
+                else
+                {
+                    // There's no finished first argument - search possible shortcuts or classnames
+                    CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0));
+                    CommandExecutor::createListOfPossibleIdentifiers(CommandExecutor::getArgument(0));
+
+                    unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
+                    unsigned int num_identifiers = CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.size();
+
+                    if (num_functions == 1 && num_identifiers == 0)
+                    {
+                        // It's a shortcut
+                        std::string functionname = *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first;
+                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname);
+                        if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(0)))
+                        {
+                            // Unfinished shortcut
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                        }
+                        CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                        CommandExecutor::getEvaluation().functionclass_ = 0;
+                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().function_->getName();
+                        if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
+                        {
+                            CommandExecutor::getEvaluation().command_ += " ";
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                        }
+                        // Move on to next case
+                    }
+                    else if (num_identifiers == 1 && num_functions == 0)
+                    {
+                        // It's a classname
+                        std::string classname = *(*CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin()).first;
+                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(classname);
+                        if (getLowercase(classname) != getLowercase(CommandExecutor::getArgument(0)))
+                        {
+                            // Unfinished classname
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                        }
                         CommandExecutor::getEvaluation().state_ = CS_Function;
-                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(*(*CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.begin()).first);
-                        CommandExecutor::parse(*(*CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.begin()).first + " ", false);
+                        CommandExecutor::getEvaluation().function_ = 0;
+                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " ";
+                        // Move on to next case
+                    }
+                    else if (num_identifiers == 0 && num_functions == 0)
+                    {
+                        // No possibilities
+                        CommandExecutor::getEvaluation().state_ = CS_Error;
+                        AddLanguageEntry("commandexecutorunknownfirstargumentstart", "There is no command or classname starting with");
+                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + GetLocalisation("commandexecutorunknownfirstargumentstart") + " " + CommandExecutor::getArgument(0) + ".";
                         return;
                     }
-                    else if ((CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.size() == 0) && (CommandExecutor::getEvaluation().listOfPossibleShortcuts_.size() == 1))
-                    {
-                        if ((*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE)
-                         && (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)
-                         && (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND))
-                        {
-                            // There's only one possible shortcut
-                            CommandExecutor::getEvaluation().state_ = CS_Shortcut_Params;
-                            CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first);
-                        }
-                        else if ((*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE)
-                              || (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
-                        {
-                            // It's the 'set' or 'tset' keyword
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueClass;
-                        }
-                        else if (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND)
-                        {
-                            // It's the 'bind' keyword
-                            CommandExecutor::getEvaluation().state_ = CS_KeybindKey;
-                        }
-
-                        CommandExecutor::parse(*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first + " ", false);
+                    else
+                    {
+                        // There are several possiblilities
+                        std::list<std::pair<const std::string*, const std::string*> > temp;
+                        temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.end());
+                        temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.end());
+                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getCommonBegin(temp);
+                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
+                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
+                        CommandExecutor::getEvaluation().bCommandChanged_ = true;
                         return;
                     }
-
-                    // It's ambiguous
+                }
+            }
+            case CS_Function:
+            {
+                if (CommandExecutor::getEvaluation().functionclass_)
+                {
+                    // There is a classname - search for the commandname
+                    if (CommandExecutor::argumentsGiven() > 2)
+                    {
+                        // There is a finished second argument - check if it's a commandname
+                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+
+                        if (CommandExecutor::getEvaluation().function_)
+                        {
+                            // It's a function
+                            CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                            // Move on to next case
+                        }
+                        else
+                        {
+                            // The second argument is bad
+                            CommandExecutor::getEvaluation().state_ = CS_Error;
+                            AddLanguageEntry("commandexecutorunknownsecondargument", "is not a function of");
+                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknownsecondargument") + " " + CommandExecutor::getEvaluation().functionclass_->getName() + ".";
+                            return;
+                        }
+                    }
+                    else
+                    {
+                        // There is no finished second argument - search for possibilities
+                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+                        unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
+
+                        if (num_functions == 1)
+                        {
+                            // It's a function
+                            std::string functionname = *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first;
+                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname, CommandExecutor::getEvaluation().functionclass_);
+                            if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(1)))
+                            {
+                                // Unfinished function
+                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                            }
+                            CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getEvaluation().function_->getName();
+                            if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
+                            {
+                                CommandExecutor::getEvaluation().command_ += " ";
+                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                            }
+                            // Move on to next case
+                        }
+                        else if (num_functions == 0)
+                        {
+                            // No possibilities
+                            CommandExecutor::getEvaluation().state_ = CS_Error;
+                            AddLanguageEntry("commandexecutorunknownsecondargumentstart", "has no function starting with");
+                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getEvaluation().functionclass_->getName() + " " + GetLocalisation("commandexecutorunknownsecondargumentstart") + " " + CommandExecutor::getArgument(1) + ".";
+                            return;
+                        }
+                        else
+                        {
+                            // There are several possibilities
+                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleFunctions_);
+                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                            return;
+                        }
+                    }
+                }
+                else
+                {
+                    // There is no classname - move on to CS_ParamPreparation
+                }
+            }
+            case CS_ParamPreparation:
+            {
+                if (CommandExecutor::getEvaluation().function_->getParamCount() == 0 || CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().function_))
+                {
+                    CommandExecutor::getEvaluation().state_ = CS_Finished;
                     return;
                 }
                 else
                 {
-                    // There is at least one argument: Check if it's a shortcut, a classname or a special keyword
-                    CommandExecutor::getEvaluation().state_ = CS_FunctionClass_Or_Shortcut_Or_Keyword;
-                    CommandExecutor::parse(command, false);
+                    unsigned int argumentNumber = CommandExecutor::argumentsGiven() - 2;
+                    if (CommandExecutor::getEvaluation().functionclass_)
+                        argumentNumber -= 1;
+
+                    CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
+                    CommandExecutor::getEvaluation().state_ = CS_Params;
+
+                    if (CommandExecutor::getEvaluation().bCommandChanged_)
+                    {
+                        // Don't do more than one change
+                        return;
+                    }
+                }
+            }
+            case CS_Params:
+            {
+                if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 1)
+                {
+                    // There is exactly one possible argument
+                    CommandExecutor::getEvaluation().argument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
+                    CommandExecutor::getEvaluation().possibleArgument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
+                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
                     return;
                 }
+                else if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 0)
+                {
+                    // The user tries something new - we let him do
+                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getLastArgument();
+                    return;
+                }
+                else
+                {
+                    // There are several possibilities
+                    unsigned int argumentNumber = CommandExecutor::argumentsGiven();
+                    if (argumentNumber > 0)
+                        --argumentNumber;
+                    if (CommandExecutor::getEvaluation().functionclass_ && argumentNumber > 0)
+                        --argumentNumber;
+
+                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleArguments_);
+                    CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
+                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                    return;
+                }
+            }
+            case CS_Finished:
+            {
+                // Nothing more to do
                 break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                if (CommandExecutor::argumentsGiven() >= 1)
-                {
-                    if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
-                    {
-                        // We want to set a config value
-                        CommandExecutor::getEvaluation().state_ = CS_ConfigValueClass;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-                    else if (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND)
-                    {
-                        // We want to set a keybinding
-                        CommandExecutor::getEvaluation().state_ = CS_KeybindKey;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-
-                    if (!CommandExecutor::getEvaluation().functionclass_)
-                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(CommandExecutor::getToken(0));
-                    if (!CommandExecutor::getEvaluation().shortcut_)
-                        CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(CommandExecutor::getToken(0));
-
-                    if ((!CommandExecutor::getEvaluation().functionclass_) && (!CommandExecutor::getEvaluation().shortcut_))
-                    {
-                        // Argument 1 seems to be wrong
-                        AddLanguageEntry("CommandExecutor::NoSuchCommandOrClassName", "No such command or classname");
-                        CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(0) + ": " + GetLocalisation("CommandExecutor::NoSuchCommandOrClassName"));
-                        CommandExecutor::getEvaluation().state_ = CS_Error;
-                        return;
-                    }
-                    else if (CommandExecutor::getEvaluation().shortcut_)
-                    {
-                        // Argument 1 is a shortcut: Return the needed parameter types
-                        CommandExecutor::getEvaluation().state_ = CS_Shortcut_Params;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-                    else
-                    {
-                        // Argument 1 is a classname: Return the possible functions
-                        CommandExecutor::getEvaluation().state_ = CS_Function;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-                }
-                else
-                {
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
+            }
+            case CS_Error:
+            {
+                // Bad, very bad
                 break;
-            case CS_Shortcut_Params:
-                if (CommandExecutor::getEvaluation().shortcut_)
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if (CommandExecutor::enoughParametersGiven(1, CommandExecutor::getEvaluation().shortcut_))
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_Shortcut_Finished;
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_Function:
-                if (CommandExecutor::getEvaluation().functionclass_)
-                {
-                    // We have a valid classname
-                    // Check if there is a second argument
-                    if (CommandExecutor::argumentsGiven() >= 2)
-                    {
-                        // There is a second argument: Check if it's a valid functionname
-                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
-                        if (!CommandExecutor::getEvaluation().function_)
-                        {
-                            // Argument 2 seems to be wrong
-                            AddLanguageEntry("CommandExecutor::NoSuchFunctionnameIn", "No such functionname in");
-                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(1) + ": " + GetLocalisation("CommandExecutor::NoSuchFunctionnameIn") + " " + CommandExecutor::getEvaluation().functionclass_->getName());
-                            CommandExecutor::getEvaluation().state_ = CS_Error;
-                            return;
-                        }
-                        else
-                        {
-                            // Argument 2 seems to be a valid functionname: Get the parameters
-                            CommandExecutor::getEvaluation().state_ = CS_Function_Params;
-                            CommandExecutor::parse(command, false);
-                            return;
-                        }
-                    }
-                    else
-                    {
-                        // There is no finished second argument
-                        // Check if there's already a perfect match
-                        if (CommandExecutor::getEvaluation().tokens_.size() >= 2)
-                        {
-                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
-                            if (CommandExecutor::getEvaluation().function_)
-                            {
-                                // There is a perfect match: Add a whitespace and continue parsing
-                                CommandExecutor::getEvaluation().state_ = CS_Function_Params;
-                                CommandExecutor::parse(command + " ", false);
-                                return;
-                            }
-                        }
-
-                        // No perfect match: Create the list of all possible functions and return
-                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
-
-                        // Check if there's only one possiblility
-                        if (CommandExecutor::getEvaluation().listOfPossibleFunctions_.size() == 1)
-                        {
-                            // There's only one possible function
-                            CommandExecutor::getEvaluation().state_ = CS_Function_Params;
-                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(*(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first, CommandExecutor::getEvaluation().functionclass_);
-                            CommandExecutor::parse(CommandExecutor::getToken(0) + " " + *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first + " ", false);
-                            return;
-                        }
-
-                        // It's ambiguous
-                        return;
-                    }
-                }
-                else
-                {
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_Function_Params:
-                if (CommandExecutor::getEvaluation().functionclass_ && CommandExecutor::getEvaluation().function_)
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if (CommandExecutor::enoughParametersGiven(2, CommandExecutor::getEvaluation().function_))
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_Function_Finished;
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_ConfigValueClass:
-                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)))
-                {
-                    // We want to set a config value
-                    // Check if there is a second argument
-                    if (CommandExecutor::argumentsGiven() >= 2)
-                    {
-                        // There is a second argument: Check if it's a valid classname
-                        CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(CommandExecutor::getToken(1));
-                        if (!CommandExecutor::getEvaluation().configvalueclass_)
-                        {
-                            // Argument 2 seems to be wrong
-                            AddLanguageEntry("CommandExecutor::NoSuchClassWithConfigValues", "No such class with config values");
-                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(1) + ": " + GetLocalisation("CommandExecutor::NoSuchClassWithConfigValues"));
-                            CommandExecutor::getEvaluation().state_ = CS_Error;
-                            return;
-                        }
-                        else
-                        {
-                            // Argument 2 seems to be a valid classname: Search for possible config values
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
-                            CommandExecutor::parse(command, false);
-                            return;
-                        }
-                    }
-                    else
-                    {
-                        // There's no finished second argument
-                        // Check if there's already a perfect match
-                        if (CommandExecutor::getEvaluation().tokens_.size() >= 2)
-                        {
-                            CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(CommandExecutor::getToken(1));
-                            if (CommandExecutor::getEvaluation().configvalueclass_)
-                            {
-                                // There is a perfect match: Add a whitespace and continue parsing
-                                CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
-                                CommandExecutor::parse(command + " ", false);
-                                return;
-                            }
-                        }
-
-                        // No perfect match: Create the list of all possible classnames and return
-                        CommandExecutor::createListOfPossibleConfigValueClasses(CommandExecutor::getToken(1));
-
-                        // Check if there's only one possiblility
-                        if (CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.size() == 1)
-                        {
-                            // There's only one possible classname
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
-                            CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(*(*CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.begin()).first);
-                            CommandExecutor::parse(CommandExecutor::getToken(0) + " " + *(*CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.begin()).first + " ", false);
-                            return;
-                        }
-
-                        // It's ambiguous
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_ConfigValue:
-                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)) && (CommandExecutor::getEvaluation().configvalueclass_))
-                {
-                    // Check if there is a third argument
-                    if (CommandExecutor::argumentsGiven() >= 3)
-                    {
-                        // There is a third argument: Check if it's a valid config value
-                        CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
-                        if (!CommandExecutor::getEvaluation().configvalue_)
-                        {
-                            // Argument 3 seems to be wrong
-                            AddLanguageEntry("CommandExecutor::NoSuchConfigValueIn", "No such config value in");
-                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(2) + ": " + GetLocalisation("CommandExecutor::NoSuchConfigValueIn") + " " + CommandExecutor::getEvaluation().configvalueclass_->getName());
-                            CommandExecutor::getEvaluation().state_ = CS_Error;
-                            return;
-                        }
-                        else
-                        {
-                            // Argument 3 seems to be a valid config value: Get the type
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
-                            CommandExecutor::parse(command, false);
-                            return;
-                        }
-                    }
-                    else
-                    {
-                        // There is no finished third argument
-                        // Check if there's already a perfect match
-                        if (CommandExecutor::getEvaluation().tokens_.size() >= 3)
-                        {
-                            CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
-                            if (CommandExecutor::getEvaluation().configvalue_)
-                            {
-                                // There is a perfect match: Add a whitespace and continue parsing
-                                CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
-                                CommandExecutor::parse(command + " ", false);
-                                return;
-                            }
-                        }
-
-                        // No perfect match: Create the list of all possible config values
-                        CommandExecutor::createListOfPossibleConfigValues(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
-
-                        // Check if there's only one possiblility
-                        if (CommandExecutor::getEvaluation().listOfPossibleConfigValues_.size() == 1)
-                        {
-                            // There's only one possible config value
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
-                            CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(*(*CommandExecutor::getEvaluation().listOfPossibleConfigValues_.begin()).first, CommandExecutor::getEvaluation().configvalueclass_);
-                            CommandExecutor::parse(CommandExecutor::getToken(0) + " " + CommandExecutor::getToken(1) + " " + *(*CommandExecutor::getEvaluation().listOfPossibleConfigValues_.begin()).first + " ", false);
-                            return;
-                        }
-
-                        // It's ambiguous
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_ConfigValueType:
-                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)) && CommandExecutor::getEvaluation().configvalueclass_ && CommandExecutor::getEvaluation().configvalue_)
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if ((CommandExecutor::getEvaluation().tokens_.size() >= 4) && (CommandExecutor::getEvaluation().tokens_[3] != COMMAND_EXECUTOR_CURSOR))
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_ConfigValueFinished;
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_KeybindKey:
-                if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND))
-                {
-                    // todo
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_KeybindCommand:
-                if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND) && (false)) // todo
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if (CommandExecutor::getEvaluation().tokens_.size() >= 3)
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_KeybindFinished;
-                        return;
-                    }
-
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_Shortcut_Finished:
-                // Nothing to do
-                break;
-            case CS_Function_Finished:
-                // Nothing to do
-                break;
-            case CS_ConfigValueFinished:
-                // Nothing to do
-                break;
-            case CS_KeybindFinished:
-                // Nothing to do
-                break;
-            case CS_Error:
-                // This is bad
-                break;
-        }
-    }
-
-    void CommandExecutor::initialize(const std::string& command)
-    {
-        CommandExecutor::getEvaluation().processedCommand_ = command;
-        CommandExecutor::getEvaluation().additionalParameter_ = "";
-
-        CommandExecutor::getEvaluation().bEvaluatedParams_ = false;
-        CommandExecutor::getEvaluation().evaluatedExecutor_ = 0;
-
-        CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleShortcuts_.clear();
+            }
+        }
+    }
+
+    unsigned int CommandExecutor::argumentsFinished()
+    {
+        unsigned int argumentsGiven = CommandExecutor::argumentsGiven();
+        if (argumentsGiven > 0)
+            return argumentsGiven - 1;
+        else
+            return 0;
+    }
+
+    unsigned int CommandExecutor::argumentsGiven()
+    {
+        if (CommandExecutor::getEvaluation().command_.size() > 0 && CommandExecutor::getEvaluation().command_[CommandExecutor::getEvaluation().command_.size() - 1] == ' ')
+            return CommandExecutor::getEvaluation().commandTokens_.size() + 1;
+        else
+            return CommandExecutor::getEvaluation().commandTokens_.size();
+    }
+
+    bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command)
+    {
+        if (CommandExecutor::getEvaluation().functionclass_)
+            return (CommandExecutor::argumentsGiven() > (2 + command->getParamCount()));
+        else
+            return (CommandExecutor::argumentsGiven() > (1 + command->getParamCount()));
+    }
+
+    std::string CommandExecutor::getArgument(unsigned int index)
+    {
+        if (index < (CommandExecutor::getEvaluation().commandTokens_.size()))
+            return CommandExecutor::getEvaluation().commandTokens_[index];
+        else
+            return "";
+    }
+
+    std::string CommandExecutor::getLastArgument()
+    {
+        return CommandExecutor::getArgument(CommandExecutor::argumentsGiven() - 1);
+    }
+
+    void CommandExecutor::createListOfPossibleIdentifiers(const std::string& fragment)
+    {
+        CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.clear();
+        std::string lowercase = getLowercase(fragment);
+        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
+            if ((*it).second->hasConsoleCommands())
+                if ((*it).first.find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+    }
+
+    void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
+    {
         CommandExecutor::getEvaluation().listOfPossibleFunctions_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleConfigValues_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleKeys_.clear();
-
-        CommandExecutor::getEvaluation().functionclass_ = 0;
-        CommandExecutor::getEvaluation().configvalueclass_ = 0;
-        CommandExecutor::getEvaluation().shortcut_ = 0;
-        CommandExecutor::getEvaluation().function_ = 0;
-        CommandExecutor::getEvaluation().configvalue_ = 0;
-        CommandExecutor::getEvaluation().key_ = 0;
-
-        CommandExecutor::getEvaluation().errorMessage_ = "";
-        CommandExecutor::getEvaluation().state_ = CS_Empty;
-    }
-
-    bool CommandExecutor::argumentsGiven(unsigned int num)
-    {
-        // Because we added a cursor we have +1 arguments
-        // There are num arguments given if there are at least num arguments + one cursor
-        return (CommandExecutor::getEvaluation().tokens_.size() >= (num + 1));
-    }
-
-    unsigned int CommandExecutor::argumentsGiven()
-    {
-        // Because we added a cursor we have +1 arguments
-        if (CommandExecutor::getEvaluation().tokens_.size() >= 1)
-            return (CommandExecutor::getEvaluation().tokens_.size() - 1);
-        else
-            return 0;
-    }
-
-    std::string CommandExecutor::getToken(unsigned int index)
-    {
-        if ((index >= 0) && (index < (CommandExecutor::getEvaluation().tokens_.size() - 1)))
-            return CommandExecutor::getEvaluation().tokens_[index];
-        else if (index == (CommandExecutor::getEvaluation().tokens_.size() - 1))
-            return CommandExecutor::getEvaluation().tokens_[index].substr(0, CommandExecutor::getEvaluation().tokens_[index].size() - 1);
-        else
-            return "";
-    }
-
-    bool CommandExecutor::enoughParametersGiven(unsigned int head, Executor* executor)
-    {
-        unsigned int neededParams = head + executor->getParamCount();
-        /*
-        for (unsigned int i = executor->getParamCount() - 1; i >= 0; i--)
-        {
-            if (executor->defaultValueSet(i))
-                neededParams--;
+        std::string lowercase = getLowercase(fragment);
+        if (!identifier)
+        {
+            for (std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
+                if ((*it).first.find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+        }
+        else
+        {
+            for (std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
+                if ((*it).first.find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+        }
+    }
+
+    void CommandExecutor::createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param)
+    {
+        CommandExecutor::createArgumentCompletionList(command, param);
+
+        CommandExecutor::getEvaluation().listOfPossibleArguments_.clear();
+        std::string lowercase = getLowercase(fragment);
+        for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
+        {
+            if ((*it).lowercaseComparison())
+            {
+                if ((*it).getComparable().find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
+            }
             else
-                break;
-        }
-        */
-        return ((CommandExecutor::getEvaluation().tokens_.size() >= neededParams) && (CommandExecutor::getEvaluation().tokens_[neededParams - 1] != COMMAND_EXECUTOR_CURSOR));
-    }
-
-    void CommandExecutor::createListOfPossibleFunctionClasses(const std::string& fragment)
-    {
-        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
-        {
-            if ((*it).second->hasConsoleCommands())
-            {
-                if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-                {
-                    CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-                }
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleShortcuts(const std::string& fragment)
-    {
-        for (std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
-        {
-            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-            {
-                CommandExecutor::getEvaluation().listOfPossibleShortcuts_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleShortcuts_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
-    {
-        for (std::map<std::string, ExecutorStatic*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
-        {
-            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-            {
-                CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleFunctions_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleConfigValueClasses(const std::string& fragment)
-    {
-        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
-        {
-            if ((*it).second->hasConfigValues())
-            {
-                if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-                {
-                    CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-                }
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleConfigValues(const std::string& fragment, Identifier* identifier)
-    {
-        for (std::map<std::string, ConfigValueContainer*>::const_iterator it = identifier->getLowercaseConfigValueMapBegin(); it != identifier->getLowercaseConfigValueMapEnd(); ++it)
-        {
-            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-            {
-                CommandExecutor::getEvaluation().listOfPossibleConfigValues_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleConfigValues_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleKeys(const std::string& fragment)
-    {
-        // todo
-
-        CommandExecutor::getEvaluation().listOfPossibleKeys_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    bool CommandExecutor::compareStringsInList(const std::pair<const std::string*, const std::string*>& first, const std::pair<const std::string*, const std::string*>& second)
-    {
-        return ((*first.first) < (*second.first));
-    }
-
-    Identifier* CommandExecutor::getIdentifierOfPossibleFunctionClass(const std::string& name)
-    {
-        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(getLowercase(name));
+            {
+                if ((*it).getComparable().find(fragment) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
+            }
+        }
+    }
+
+    Identifier* CommandExecutor::getPossibleIdentifier(const std::string& name)
+    {
+        std::string lowercase = getLowercase(name);
+        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(lowercase);
         if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConsoleCommands())
             return (*it).second;
@@ -1252,92 +508,60 @@
     }
 
-    ExecutorStatic* CommandExecutor::getExecutorOfPossibleShortcut(const std::string& name)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(getLowercase(name));
-        if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
-            return (*it).second;
-
+    ConsoleCommand* CommandExecutor::getPossibleCommand(const std::string& name, Identifier* identifier)
+    {
+        std::string lowercase = getLowercase(name);
+        if (!identifier)
+        {
+            std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(lowercase);
+            if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
+                return (*it).second;
+        }
+        else
+        {
+            std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(lowercase);
+            if (it != identifier->getLowercaseConsoleCommandMapEnd())
+                return (*it).second;
+        }
         return 0;
     }
 
-    ExecutorStatic* CommandExecutor::getExecutorOfPossibleFunction(const std::string& name, Identifier* identifier)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(getLowercase(name));
-        if (it != identifier->getLowercaseConsoleCommandMapEnd())
-            return (*it).second;
-
-        return 0;
-    }
-
-    Identifier* CommandExecutor::getIdentifierOfPossibleConfigValueClass(const std::string& name)
-    {
-        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(getLowercase(name));
-        if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConfigValues())
-            return (*it).second;
-
-        return 0;
-    }
-
-    ConfigValueContainer* CommandExecutor::getContainerOfPossibleConfigValue(const std::string& name, Identifier* identifier)
-    {
-        std::map<std::string, ConfigValueContainer*>::const_iterator it = identifier->getLowercaseConfigValueMap().find(getLowercase(name));
-        if (it != identifier->getLowercaseConfigValueMapEnd())
-        {
-            return (*it).second;
-        }
-
-        return 0;
-    }
-
-    ConfigValueContainer* CommandExecutor::getContainerOfPossibleKey(const std::string& name)
-    {
-        // todo
-
-        return 0;
-    }
-
-    std::string CommandExecutor::dump(const std::list<std::pair<const std::string*, const std::string*> >& list)
-    {
-        std::string output = "";
-        for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
-        {
-            if (it != list.begin())
-                output += " ";
-
-            output += *(*it).second;
-        }
-        return output;
-    }
-
-    std::string CommandExecutor::dump(const ExecutorStatic* executor)
-    {
-        std::string output = "";
-        for (unsigned int i = 0; i < executor->getParamCount(); i++)
-        {
-            if (i != 0)
-                output += " ";
-
-            if (executor->defaultValueSet(i))
-                output += "[";
+    std::string CommandExecutor::getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param)
+    {
+        CommandExecutor::createArgumentCompletionList(command, param);
+
+        std::string lowercase = getLowercase(name);
+        for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
+        {
+            if ((*it).lowercaseComparison())
+            {
+                if ((*it).getComparable() == lowercase)
+                    return (*it).getString();
+            }
             else
-                output += "{";
-
-            output += executor->getTypenameParam(i);
-
-            if (executor->defaultValueSet(i))
-                output += "=" + executor->getDefaultValue(i).toString() + "]";
-            else
-                output += "}";
-        }
-        return output;
-    }
-
-    std::string CommandExecutor::dump(const ConfigValueContainer* container)
-    {
-        AddLanguageEntry("CommandExecutor::oldvalue", "old value");
-        if (!container->isVector())
-            return ("{" + container->getTypename() + "} (" + GetLocalisation("CommandExecutor::oldvalue") + ": " + container->toString() + ")");
-        else
-            return ("(vector<" + container->getTypename() + ">) (size: " + getConvertedValue<unsigned int, std::string>(container->getVectorSize()) + ")");
+            {
+                if ((*it).getComparable() == name)
+                    return (*it).getString();
+            }
+        }
+
+        return "";
+    }
+
+    void CommandExecutor::createArgumentCompletionList(ConsoleCommand* command, unsigned int param)
+    {
+        std::string params[5];
+
+        unsigned int index = 0;
+        unsigned int lowestIndex = 1 + (CommandExecutor::getEvaluation().functionclass_ != 0);
+
+        for (unsigned int i = CommandExecutor::argumentsGiven() - 1; i >= lowestIndex; --i)
+        {
+            params[index] = CommandExecutor::getArgument(i);
+            ++index;
+            if (index >= 5)
+                break;
+        }
+
+        command->createArgumentCompletionList(param, params[0], params[1], params[2], params[3], params[4]);
     }
 
@@ -1382,3 +606,45 @@
         }
     }
+
+    std::string CommandExecutor::getCommonBegin(const ArgumentCompletionList& list)
+    {
+        if (list.size() == 0)
+        {
+            return "";
+        }
+        else if (list.size() == 1)
+        {
+            return ((*list.begin()).getComparable() + " ");
+        }
+        else
+        {
+            std::string output = "";
+            for (unsigned int i = 0; true; i++)
+            {
+                char temp = 0;
+                for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
+                {
+                    std::string argument = (*it).getComparable();
+                    if (argument.size() > i)
+                    {
+                        if (it == list.begin())
+                        {
+                            temp = argument[i];
+                        }
+                        else
+                        {
+                            if (temp != argument[i])
+                                return output;
+                        }
+                    }
+                    else
+                    {
+                        return output;
+                    }
+                }
+                output += temp;
+            }
+            return output;
+        }
+    }
 }
Index: code/branches/network/src/core/CommandExecutor.h
===================================================================
--- code/branches/network/src/core/CommandExecutor.h	(revision 1445)
+++ code/branches/network/src/core/CommandExecutor.h	(revision 1446)
@@ -32,133 +32,37 @@
 #include "CorePrereqs.h"
 
-#include <string>
 #include <map>
-#include <list>
 
-#include "util/SubString.h"
-#include "util/MultiTypeMath.h"
-
-#define COMMAND_EXECUTOR_CURSOR "$"
+#include "CommandEvaluation.h"
 
 namespace orxonox
 {
-    enum CommandState
-    {
-        CS_Uninitialized,
-        CS_Empty,
-        CS_FunctionClass_Or_Shortcut_Or_Keyword,
-        CS_Shortcut_Params,
-        CS_Shortcut_Finished,
-        CS_Function,
-        CS_Function_Params,
-        CS_Function_Finished,
-        CS_ConfigValueClass,
-        CS_ConfigValue,
-        CS_ConfigValueType,
-        CS_ConfigValueFinished,
-        CS_KeybindKey,
-        CS_KeybindCommand,
-        CS_KeybindFinished,
-        CS_Error
-    };
-
-    void exec(const std::string& filename);
-    std::string echo(const std::string& text);
-
-    void write(const std::string& filename, const std::string& text);
-    void append(const std::string& filename, const std::string& text);
-    std::string read(const std::string& filename);
-
-    ///////////////////////
-    // CommandEvaluation //
-    ///////////////////////
-    class _CoreExport CommandEvaluation
-    {
-        friend class CommandExecutor;
-
-        public:
-            CommandEvaluation();
-
-            KeybindMode::Enum getKeybindMode();
-            bool isValid() const;
-
-            inline void setAdditionalParameter(const std::string& param)
-                { this->additionalParameter_ = param; this->bEvaluatedParams_ = false; }
-            inline std::string getAdditionalParameter() const
-                { return (this->additionalParameter_ != "") ? (" " + this->additionalParameter_) : ""; }
-            inline ExecutorStatic* getEvaluatedExecutor() { return evaluatedExecutor_; }
-            inline std::string getCommandString() { return this->processedCommand_; }
-
-            void setEvaluatedParameter(unsigned int index, MultiTypeMath param);
-            MultiTypeMath getEvaluatedParameter(unsigned int index) const;
-
-            void evaluateParams();
-
-            bool hasReturnvalue() const;
-            MultiTypeMath getReturnvalue() const;
-
-        private:
-            std::string processedCommand_;
-            SubString tokens_;
-            std::string additionalParameter_;
-
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctionClasses_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleShortcuts_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleConfigValueClasses_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleConfigValues_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleKeys_;
-
-            Identifier* functionclass_;
-            Identifier* configvalueclass_;
-            ExecutorStatic* shortcut_;
-            ExecutorStatic* function_;
-            ConfigValueContainer* configvalue_;
-            ConfigValueContainer* key_;
-
-            std::string errorMessage_;
-            CommandState state_;
-
-            bool bEvaluatedParams_;
-            MultiTypeMath param_[5];
-            ExecutorStatic* evaluatedExecutor_;
-    };
-
-    /////////////////////
-    // CommandExecutor //
-    /////////////////////
     class _CoreExport CommandExecutor
     {
         public:
             static bool execute(const std::string& command, bool useTcl = true);
-            static bool execute(const CommandEvaluation& evaluation);
-
             static std::string complete(const std::string& command);
-            static std::string complete(const CommandEvaluation& evaluation);
-
             static std::string hint(const std::string& command);
-            static std::string hint(const CommandEvaluation& evaluation);
 
             static CommandEvaluation evaluate(const std::string& command);
-
             static const CommandEvaluation& getLastEvaluation();
 
-            static Executor& addConsoleCommandShortcut(ExecutorStatic* executor);
-            static ExecutorStatic* getConsoleCommandShortcut(const std::string& name);
-            static ExecutorStatic* getLowercaseConsoleCommandShortcut(const std::string& name);
+            static ConsoleCommand& addConsoleCommandShortcut(ConsoleCommand* command);
+            static ConsoleCommand* getConsoleCommandShortcut(const std::string& name);
+            static ConsoleCommand* getLowercaseConsoleCommandShortcut(const std::string& name);
 
             /** @brief Returns the map that stores all console commands. @return The const_iterator */
-            static inline const std::map<std::string, ExecutorStatic*>& getConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_; }
+            static inline const std::map<std::string, ConsoleCommand*>& getConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_.begin(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_.end(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_.end(); }
 
             /** @brief Returns the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            static inline const std::map<std::string, ExecutorStatic*>& getLowercaseConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_; }
+            static inline const std::map<std::string, ConsoleCommand*>& getLowercaseConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.begin(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end(); }
 
         private:
@@ -170,40 +74,28 @@
             static CommandEvaluation& getEvaluation();
 
+            static void parseIfNeeded(const std::string& command);
             static void parse(const std::string& command, bool bInitialize = true);
-            static void initialize(const std::string& command);
 
-            static bool argumentsGiven(unsigned int num);
+            static unsigned int argumentsFinished();
             static unsigned int argumentsGiven();
+            static bool enoughArgumentsGiven(ConsoleCommand* command);
+            static std::string getArgument(unsigned int index);
+            static std::string getLastArgument();
 
-            static std::string getToken(unsigned int index);
+            static void createListOfPossibleIdentifiers(const std::string& fragment);
+            static void createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier = 0);
+            static void createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param);
 
-            static bool enoughParametersGiven(unsigned int head, Executor* executor);
+            static Identifier* getPossibleIdentifier(const std::string& name);
+            static ConsoleCommand* getPossibleCommand(const std::string& name, Identifier* identifier = 0);
+            static std::string getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param);
 
-            static void createListOfPossibleShortcuts(const std::string& fragment);
-            static void createListOfPossibleFunctionClasses(const std::string& fragment);
-            static void createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier);
-            static void createListOfPossibleConfigValueClasses(const std::string& fragment);
-            static void createListOfPossibleConfigValues(const std::string& fragment, Identifier* identifier);
-            static void createListOfPossibleKeys(const std::string& fragment);
-
-            static bool compareStringsInList(const std::pair<const std::string*, const std::string*>& first, const std::pair<const std::string*, const std::string*>& second);
-
-            static std::string dump(const std::list<std::pair<const std::string*, const std::string*> >& list);
-            static std::string dump(const ExecutorStatic* executor);
-            static std::string dump(const ConfigValueContainer* container);
-
+            static void createArgumentCompletionList(ConsoleCommand* command, unsigned int param);
             static std::string getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list);
-
-            static Identifier* getIdentifierOfPossibleFunctionClass(const std::string& name);
-            static ExecutorStatic* getExecutorOfPossibleShortcut(const std::string& name);
-            static ExecutorStatic* getExecutorOfPossibleFunction(const std::string& name, Identifier* identifier);
-            static Identifier* getIdentifierOfPossibleConfigValueClass(const std::string& name);
-            static ConfigValueContainer* getContainerOfPossibleConfigValue(const std::string& name, Identifier* identifier);
-            static ConfigValueContainer* getContainerOfPossibleKey(const std::string& name);
+            static std::string getCommonBegin(const ArgumentCompletionList& list);
 
             CommandEvaluation evaluation_;
-
-            std::map<std::string, ExecutorStatic*> consoleCommandShortcuts_;
-            std::map<std::string, ExecutorStatic*> consoleCommandShortcuts_LC_;
+            std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_;
+            std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_LC_;
     };
 }
Index: code/branches/network/src/core/ConfigFileManager.cc
===================================================================
--- code/branches/network/src/core/ConfigFileManager.cc	(revision 1445)
+++ code/branches/network/src/core/ConfigFileManager.cc	(revision 1446)
@@ -38,8 +38,34 @@
 namespace orxonox
 {
-    ConsoleCommandShortcutExtern(reloadConfig, AccessLevel::None);
-    ConsoleCommandShortcutExtern(cleanConfig, AccessLevel::None);
-    ConsoleCommandShortcutExtern(loadSettings, AccessLevel::None);
-    ConsoleCommandShortcutExtern(loadKeybindings, AccessLevel::None);
+    SetConsoleCommandShortcutExtern(config).setArgumentCompleter(0, autocompletion::configvalueclasses()).setArgumentCompleter(1, autocompletion::configvalues()).setArgumentCompleter(2, autocompletion::configvalue());
+    SetConsoleCommandShortcutExtern(tconfig).setArgumentCompleter(0, autocompletion::configvalueclasses()).setArgumentCompleter(1, autocompletion::configvalues()).setArgumentCompleter(2, autocompletion::configvalue());
+    SetConsoleCommandShortcutExtern(reloadConfig);
+    SetConsoleCommandShortcutExtern(cleanConfig);
+    SetConsoleCommandShortcutExtern(loadSettings).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(loadKeybindings).setArgumentCompleter(0, autocompletion::files());
+
+    bool config(const std::string& classname, const std::string& varname, const std::string& value)
+    {
+        std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getLowercaseIdentifierMap().find(getLowercase(classname));
+        if (identifier != Identifier::getLowercaseIdentifierMapEnd())
+        {
+            std::map<std::string, ConfigValueContainer*>::const_iterator variable = (*identifier).second->getLowercaseConfigValueMap().find(getLowercase(varname));
+            if (variable != (*identifier).second->getLowercaseConfigValueMapEnd())
+                return (*variable).second->set(value);
+        }
+        return false;
+    }
+
+    bool tconfig(const std::string& classname, const std::string& varname, const std::string& value)
+    {
+        std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getLowercaseIdentifierMap().find(getLowercase(classname));
+        if (identifier != Identifier::getLowercaseIdentifierMapEnd())
+        {
+            std::map<std::string, ConfigValueContainer*>::const_iterator variable = (*identifier).second->getLowercaseConfigValueMap().find(getLowercase(varname));
+            if (variable != (*identifier).second->getLowercaseConfigValueMapEnd())
+                return (*variable).second->tset(value);
+        }
+        return false;
+    }
 
     void reloadConfig()
Index: code/branches/network/src/core/ConfigFileManager.h
===================================================================
--- code/branches/network/src/core/ConfigFileManager.h	(revision 1445)
+++ code/branches/network/src/core/ConfigFileManager.h	(revision 1446)
@@ -50,4 +50,6 @@
 
 
+    bool config(const std::string& classname, const std::string& varname, const std::string& value);
+    bool tconfig(const std::string& classname, const std::string& varname, const std::string& value);
     void reloadConfig();
     void saveConfig();
Index: code/branches/network/src/core/ConfigValueContainer.cc
===================================================================
--- code/branches/network/src/core/ConfigValueContainer.cc	(revision 1445)
+++ code/branches/network/src/core/ConfigValueContainer.cc	(revision 1446)
@@ -87,13 +87,128 @@
 
         if (defvalue.size() > 0)
-            this->value_ = defvalue[0];
-
-        for (unsigned int i = 0; i < defvalue.size(); i++)
-            ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, defvalue[i].toString(), this->value_.isA(MT_string));
-
-        for (unsigned int i = 0; i < defvalue.size(); i++)
-            this->defvalueStringVector_.push_back(defvalue[i].toString());
-
-        this->update();
+        {
+                this->value_ = defvalue[0];
+
+            for (unsigned int i = 0; i < defvalue.size(); i++)
+            {
+                ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, defvalue[i].toString(), this->value_.isA(MT_string));
+                this->defvalueStringVector_.push_back(defvalue[i].toString());
+            }
+
+            this->update();
+        }
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
+        @param input The new value
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::set(const MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            return this->callFunctionWithIndex(&ConfigValueContainer::set, input.toString());
+        }
+        else
+        {
+            if (this->tset(input))
+            {
+                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, input.toString(), this->value_.isA(MT_string));
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
+        @param index The index in the vector
+        @param input The new value
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::set(unsigned int index, const MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            if (this->tset(index, input))
+            {
+                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, index, input.toString(), this->value_.isA(MT_string));
+                return true;
+            }
+        }
+        else
+        {
+            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
+        }
+        return false;
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
+        @param input The new value. If bIsVector_ then write "index value"
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::tset(const MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            return this->callFunctionWithIndex(&ConfigValueContainer::tset, input.toString());
+        }
+        else
+        {
+            MultiTypeMath temp = this->value_;
+            if (temp.assimilate(input))
+            {
+                this->value_ = temp;
+                if (this->identifier_)
+                    this->identifier_->updateConfigValues();
+
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
+        @param index The index in the vector
+        @param input The new value
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::tset(unsigned int index, const MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            if (index > MAX_VECTOR_INDEX)
+            {
+                COUT(1) << "Error: Index " << index << " is too large." << std::endl;
+                return false;
+            }
+
+            if (index >= this->valueVector_.size())
+            {
+                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
+                {
+                    this->valueVector_.push_back(MultiTypeMath());
+                }
+            }
+
+            MultiTypeMath temp = this->value_;
+            if (temp.assimilate(input))
+            {
+                this->valueVector_[index] = temp;
+
+                if (this->identifier_)
+                    this->identifier_->updateConfigValues();
+
+                return true;
+            }
+        }
+        else
+        {
+            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
+        }
+        return false;
     }
 
@@ -103,5 +218,5 @@
         @return True if the new entry was successfully added
     */
-    bool ConfigValueContainer::add(const std::string& input)
+    bool ConfigValueContainer::add(const MultiTypeMath& input)
     {
         if (this->bIsVector_)
@@ -123,4 +238,5 @@
             if (index < this->valueVector_.size())
             {
+                // Erase the entry from the vector, change (shift) all entries beginning with index in the config file, remove the last entry from the file
                 this->valueVector_.erase(this->valueVector_.begin() + index);
                 for (unsigned int i = index; i < this->valueVector_.size(); i++)
@@ -131,96 +247,4 @@
             }
             COUT(1) << "Error: Invalid vector-index." << std::endl;
-        }
-
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
-    }
-
-    /**
-        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
-        @param input The new value. If bIsVector_ then write "index value"
-        @return True if the new value was successfully assigned
-    */
-    bool ConfigValueContainer::set(const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            SubString token(input, " ", "", true, '"', false, '(', ')', false, '\0');
-            int index = -1;
-            bool success = false;
-
-            if (token.size() > 0)
-                success = ConvertValue(&index, token[0]);
-
-            if (!success || index < 0 || index > MAX_VECTOR_INDEX)
-            {
-                if (!success)
-                {
-                    COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
-                }
-                else
-                {
-                    COUT(1) << "Error: Invalid vector-index." << std::endl;
-                }
-                return false;
-            }
-
-            if (token.size() >= 2)
-                return this->set(index, token.subSet(1).join());
-            else
-                return this->set(index, "");
-        }
-
-        bool success = this->tset(input);
-        ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, input, this->value_.isA(MT_string));
-        return success;
-    }
-
-    /**
-        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
-        @param index The index in the vector
-        @param input The new value
-        @return True if the new value was successfully assigned
-    */
-    bool ConfigValueContainer::set(unsigned int index, const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            bool success = this->tset(index, input);
-            ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, index, input, this->value_.isA(MT_string));
-            return success;
-        }
-
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
-    }
-
-    /**
-        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
-        @param input The new value
-        @return True if the new value was successfully assigned
-    */
-    bool ConfigValueContainer::tset(const std::string& input)
-    {
-        bool success = this->parse(input);
-        if (this->identifier_)
-            this->identifier_->updateConfigValues();
-        return success;
-    }
-
-    /**
-        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
-        @param index The index in the vector
-        @param input The new value
-        @return True if the new value was successfully assigned
-    */
-    bool ConfigValueContainer::tset(unsigned int index, const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            bool success = this->parse(index, input);
-            if (this->identifier_)
-                this->identifier_->updateConfigValues();
-            return success;
         }
 
@@ -259,121 +283,50 @@
             for (unsigned int i = 0; i < ConfigFileManager::getSingleton()->getVectorSize(this->type_, this->sectionname_, this->varname_); i++)
             {
-                this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isA(MT_string)));
-                this->valueVector_.push_back(this->value_);
-            }
-        }
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param input The string to convert
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            SubString token(input, " ", "", true, '"', false, '(', ')', false, '\0');
-            int index = -1;
-            bool success = false;
-
-            if (token.size() > 0)
-                success = ConvertValue(&index, token[0]);
-
-            if (!success || index < 0 || index > MAX_VECTOR_INDEX)
-            {
-                if (!success)
+                if (i < this->defvalueStringVector_.size())
                 {
-                    COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
+                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isA(MT_string)));
                 }
                 else
                 {
-                    COUT(1) << "Error: Invalid vector-index." << std::endl;
+                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, MultiTypeMath(), this->value_.isA(MT_string)));
                 }
-                return false;
-            }
-
-            if (token.size() >= 2)
-                return this->parse(index, token.subSet(1).join());
+
+                this->valueVector_.push_back(this->value_);
+            }
+        }
+    }
+
+    /**
+        @brief Calls the given function with parsed index and the parsed argument from the input string.
+        @param function The function to call
+        @param input The input string
+        @return The returnvalue of the functioncall
+    */
+    bool ConfigValueContainer::callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiTypeMath&), const std::string& input)
+    {
+        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '(', ')', false, '\0');
+        int index = -1;
+        bool success = false;
+
+        if (token.size() > 0)
+            success = ConvertValue(&index, token[0]);
+
+        if (!success || index < 0 || index > MAX_VECTOR_INDEX)
+        {
+            if (!success)
+            {
+                COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
+            }
             else
-                return this->parse(index, "");
-        }
-
-        MultiTypeMath temp = this->value_;
-        if (temp.fromString(input))
-        {
-            this->value_ = temp;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param index The index in the vector
-        @param input The string to convert
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(unsigned int index, const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            if (index >= this->valueVector_.size())
-            {
-                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
-                {
-                    this->valueVector_.push_back(MultiTypeMath());
-                    ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isA(MT_string));
-                }
-            }
-
-            MultiTypeMath temp = this->value_;
-            if (temp.fromString(input))
-            {
-                this->valueVector_[index] = temp;
-                return true;
+            {
+                COUT(1) << "Error: Invalid vector-index." << std::endl;
             }
             return false;
         }
 
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param input The string to convert
-        @param defvalue The default value to assign if the parsing fails
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(const std::string& input, const MultiTypeMath& defvalue)
-    {
-        if (this->parse(input))
-            return true;
-
-        this->value_ = defvalue;
-        return false;
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param index The index in the vector
-        @param input The string to convert
-        @param defvalue The default value to assign if the parsing fails
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(unsigned int index, const std::string& input, const MultiTypeMath& defvalue)
-    {
-        if (this->bIsVector_)
-        {
-            if (this->parse(index, input))
-                return true;
-
-            this->valueVector_[index] = defvalue;
-            return false;
-        }
-
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
+        if (token.size() >= 2)
+            return (this->*function)(index, token.subSet(1).join());
+        else
+            return (this->*function)(index, "");
     }
 
Index: code/branches/network/src/core/ConfigValueContainer.h
===================================================================
--- code/branches/network/src/core/ConfigValueContainer.h	(revision 1445)
+++ code/branches/network/src/core/ConfigValueContainer.h	(revision 1446)
@@ -90,4 +90,11 @@
             }
 
+            template <typename T>
+            inline void setVectorType(const std::vector<T>& value)
+            {
+                this->value_ = T();
+                this->update();
+            }
+
             inline const std::string& getName() const
                 { return this->varname_; }
@@ -100,8 +107,12 @@
             const std::string& getDescription() const;
 
-            bool add(const std::string& input);
+            bool set(const MultiTypeMath& input);
+            bool tset(const MultiTypeMath& input);
+
+            bool set(unsigned int index, const MultiTypeMath& input);
+            bool tset(unsigned int index, const MultiTypeMath& input);
+            bool add(const MultiTypeMath& input);
             bool remove(unsigned int index);
-            bool set(const std::string& input);
-            bool tset(const std::string& input);
+
             bool reset();
             void update();
@@ -115,11 +126,5 @@
 
         private:
-            bool parse(const std::string& input);
-            bool parse(const std::string& input, const MultiTypeMath& defvalue);
-
-            bool set(unsigned int index, const std::string& input);
-            bool tset(unsigned int index, const std::string& input);
-            bool parse(unsigned int index, const std::string& input);
-            bool parse(unsigned int index, const std::string& input, const MultiTypeMath& defvalue);
+            bool callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiTypeMath&), const std::string& input);
 
             bool                       bIsVector_;                  //!< True if the container contains a std::vector
Index: code/branches/network/src/core/ConfigValueIncludes.h
===================================================================
--- code/branches/network/src/core/ConfigValueIncludes.h	(revision 1445)
+++ code/branches/network/src/core/ConfigValueIncludes.h	(revision 1446)
@@ -84,4 +84,5 @@
             temp.push_back(MultiTypeMath(defvalue[i])); \
         container##varname = new orxonox::ConfigValueContainer(CFT_Settings, this->getIdentifier(), #varname, temp); \
+        container##varname->setVectorType(varname); \
         this->getIdentifier()->addConfigValueContainer(#varname, container##varname); \
     } \
Index: code/branches/network/src/core/ConsoleCommand.cc
===================================================================
--- code/branches/network/src/core/ConsoleCommand.cc	(revision 1446)
+++ code/branches/network/src/core/ConsoleCommand.cc	(revision 1446)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ConsoleCommand.h"
+
+namespace orxonox
+{
+    ConsoleCommand::ConsoleCommand(FunctorStatic* functor, const std::string& name) : ExecutorStatic(functor, name)
+    {
+        this->accessLevel_ = AccessLevel::None;
+        this->argumentCompleter_[0] = 0;
+        this->argumentCompleter_[1] = 0;
+        this->argumentCompleter_[2] = 0;
+        this->argumentCompleter_[3] = 0;
+        this->argumentCompleter_[4] = 0;
+
+        this->keybindMode_ = KeybindMode::OnPress;
+        this->axisParamIndex_ = -1;
+        this->bAxisRelative_ = false;
+    }
+
+    ConsoleCommand& ConsoleCommand::setArgumentCompleter(unsigned int param, ArgumentCompleter* completer)
+    {
+        if (param < 5)
+            this->argumentCompleter_[param] = completer;
+        else
+        {
+            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << ": index out of bound." << std::endl;
+        }
+        return (*this);
+    }
+
+    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
+    {
+        if (param < 5)
+            return this->argumentCompleter_[param];
+        else
+            return 0;
+    }
+
+    void ConsoleCommand::createArgumentCompletionList(unsigned int param, const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)
+    {
+        if (param < 5 && this->argumentCompleter_[param])
+            this->argumentList_ = (*this->argumentCompleter_[param])(param1, param2, param3, param4, param5);
+        else
+            this->argumentList_.clear();
+    }
+}
Index: code/branches/network/src/core/ConsoleCommand.h
===================================================================
--- code/branches/network/src/core/ConsoleCommand.h	(revision 1445)
+++ code/branches/network/src/core/ConsoleCommand.h	(revision 1446)
@@ -34,25 +34,110 @@
 #include "Executor.h"
 #include "ClassManager.h"
-#include "Identifier.h"
 #include "CommandExecutor.h"
+#include "ArgumentCompletionFunctions.h"
 
 
+#define SetConsoleCommand(classname, function,  bCreateShortcut) \
+    SetConsoleCommandGeneric(classname##function##consolecommand__, classname, orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), #function), bCreateShortcut)
 
-#define ConsoleCommand(classname, function, accesslevel, bCreateShortcut) \
-    ConsoleCommandGeneric(classname##function##consolecommand__, classname, orxonox::createExecutor(orxonox::createFunctor(&classname::function), #function, accesslevel), bCreateShortcut)
-
-#define ConsoleCommandGeneric(fakevariable, classname, executor, bCreateShortcut) \
-    Executor& fakevariable = ClassManager<classname>::getIdentifier()->addConsoleCommand((ExecutorStatic*)executor, bCreateShortcut)
+#define SetConsoleCommandGeneric(fakevariable, classname, command, bCreateShortcut) \
+    ConsoleCommand& fakevariable = ClassManager<classname>::getIdentifier()->addConsoleCommand(command, bCreateShortcut)
 
 
-#define ConsoleCommandShortcut(classname, function, accesslevel) \
-    ConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createExecutor(orxonox::createFunctor(&classname::function), #function, accesslevel))
+#define SetConsoleCommandShortcut(classname, function) \
+    SetConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), #function))
 
-#define ConsoleCommandShortcutExtern(function, accesslevel) \
-    ConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createExecutor(orxonox::createFunctor(&function), #function, accesslevel))
+#define SetConsoleCommandShortcutExtern(function) \
+    SetConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createConsoleCommand(orxonox::createFunctor(&function), #function))
 
-#define ConsoleCommandShortcutGeneric(fakevariable, executor) \
-    Executor& fakevariable = CommandExecutor::addConsoleCommandShortcut((ExecutorStatic*)executor)
+#define SetConsoleCommandShortcutGeneric(fakevariable, command) \
+    ConsoleCommand& fakevariable = CommandExecutor::addConsoleCommandShortcut(command)
 
 
+namespace orxonox
+{
+    namespace AccessLevel
+    {
+        enum Level
+        {
+            None,
+            User,
+            Admin,
+            Offline,
+            Debug,
+            Disabled
+        };
+    }
+
+    class _CoreExport ConsoleCommand : public ExecutorStatic
+    {
+        public:
+            ConsoleCommand(FunctorStatic* functor, const std::string& name = "");
+
+            inline ConsoleCommand& setDescription(const std::string& description)
+                { this->ExecutorStatic::setDescription(description); return (*this); }
+            inline ConsoleCommand& setDescriptionParam(int param, const std::string& description)
+                { this->ExecutorStatic::setDescriptionParam(param, description); return (*this); }
+            inline ConsoleCommand& setDescriptionReturnvalue(const std::string& description)
+                { this->ExecutorStatic::setDescriptionReturnvalue(description); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1)
+                { this->ExecutorStatic::setDefaultValues(param1); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2)
+                { this->ExecutorStatic::setDefaultValues(param1, param2); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3)
+                { this->ExecutorStatic::setDefaultValues(param1, param2, param3); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4)
+                { this->ExecutorStatic::setDefaultValues(param1, param2, param3, param4); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4, const MultiTypeMath& param5)
+                { this->ExecutorStatic::setDefaultValues(param1, param2, param3, param4, param5); return (*this); }
+            inline ConsoleCommand& setDefaultValue(unsigned int index, const MultiTypeMath& param)
+                { this->ExecutorStatic::setDefaultValue(index, param); return (*this); }
+
+            inline ConsoleCommand& setAccessLevel(AccessLevel::Level level)
+                { this->accessLevel_ = level; return (*this); }
+            inline AccessLevel::Level getAccessLevel() const
+                { return this->accessLevel_; }
+
+            ConsoleCommand& setArgumentCompleter(unsigned int param, ArgumentCompleter* completer);
+            ArgumentCompleter* getArgumentCompleter(unsigned int param) const;
+
+            void createArgumentCompletionList(unsigned int param, const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "");
+            const ArgumentCompletionList& getArgumentCompletionList() const
+                { return this->argumentList_; }
+            ArgumentCompletionList::const_iterator getArgumentCompletionListBegin() const
+                { return this->argumentList_.begin(); }
+            ArgumentCompletionList::const_iterator getArgumentCompletionListEnd() const
+                { return this->argumentList_.end(); }
+
+            inline ConsoleCommand& setKeybindMode(KeybindMode::Enum mode)
+                { this->keybindMode_ = mode; return *this; }
+            inline KeybindMode::Enum getKeybindMode() const
+                { return this->keybindMode_; }
+
+            inline ConsoleCommand& setAxisParamIndex(int index)
+                { this->axisParamIndex_ = index; return *this; }
+            inline int getAxisParamIndex() const
+                { return this->axisParamIndex_; }
+
+            inline ConsoleCommand& setIsAxisRelative(bool val)
+                { this->bAxisRelative_ = val; return *this; }
+            inline int getIsAxisRelative() const
+                { return this->bAxisRelative_; }
+
+        private:
+            AccessLevel::Level accessLevel_;
+            ArgumentCompleter* argumentCompleter_[5];
+            ArgumentCompletionList argumentList_;
+
+            KeybindMode::Enum keybindMode_;
+            int axisParamIndex_;
+            bool bAxisRelative_;
+    };
+
+    inline ConsoleCommand* createConsoleCommand(FunctorStatic* functor, const std::string& name = "")
+    {
+        return new ConsoleCommand(functor, name);
+    }
+}
+
 #endif /* _ConsoleCommand_H__ */
Index: code/branches/network/src/core/ConsoleCommandCompilation.cc
===================================================================
--- code/branches/network/src/core/ConsoleCommandCompilation.cc	(revision 1446)
+++ code/branches/network/src/core/ConsoleCommandCompilation.cc	(revision 1446)
@@ -0,0 +1,175 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ConsoleCommandCompilation.h"
+#include "ConsoleCommand.h"
+#include "Debug.h"
+#include "util/ExprParser.h"
+
+namespace orxonox
+{
+    SetConsoleCommandShortcutExtern(source).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(echo);
+    SetConsoleCommandShortcutExtern(puts);
+
+    SetConsoleCommandShortcutExtern(read).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(append).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(write).setArgumentCompleter(0, autocompletion::files());
+
+    SetConsoleCommandShortcutExtern(calculate);
+
+    void source(const std::string& filename)
+    {
+        static std::set<std::string> executingFiles;
+
+        std::set<std::string>::const_iterator it = executingFiles.find(filename);
+        if (it != executingFiles.end())
+        {
+            COUT(1) << "Error: Recurring source command in \"" << filename << "\". Stopped execution." << std::endl;
+            return;
+        }
+
+        // Open the file
+        std::ifstream file;
+        file.open(filename.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "Error: Couldn't open file \"" << filename << "\"." << std::endl;
+            return;
+        }
+
+        executingFiles.insert(filename);
+
+        // Iterate through the file and put the lines into the CommandExecutor
+        char line[1024];
+        while (file.good() && !file.eof())
+        {
+            file.getline(line, 1024);
+            CommandExecutor::execute(line);
+        }
+
+        executingFiles.erase(filename);
+        file.close();
+    }
+
+    std::string echo(const std::string& text)
+    {
+        std::cout << text << std::endl;
+        return text;
+    }
+
+    void puts(bool newline, const std::string& text)
+    {
+        if (newline)
+        {
+            COUT(0) << text << std::endl;
+        }
+        else
+        {
+            COUT(0) << text;
+        }
+    }
+
+    void write(const std::string& filename, const std::string& text)
+    {
+        std::ofstream file;
+        file.open(filename.c_str(), std::fstream::out);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "Error: Couldn't write to file \"" << filename << "\"." << std::endl;
+            return;
+        }
+
+        file << text << std::endl;
+        file.close();
+    }
+
+    void append(const std::string& filename, const std::string& text)
+    {
+        std::ofstream file;
+        file.open(filename.c_str(), std::fstream::app);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "Error: Couldn't append to file \"" << filename << "\"." << std::endl;
+            return;
+        }
+
+        file << text << std::endl;
+        file.close();
+    }
+
+    std::string read(const std::string& filename)
+    {
+        std::ifstream file;
+        file.open(filename.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "Error: Couldn't read from file \"" << filename << "\"." << std::endl;
+            return "";
+        }
+
+        std::string output = "";
+        char line[1024];
+        while (file.good() && !file.eof())
+        {
+            file.getline(line, 1024);
+            output += line;
+            output += "\n";
+        }
+
+        file.close();
+
+        return output;
+    }
+
+    float calculate(const std::string& calculation)
+    {
+        ExprParser expr(calculation);
+        if (expr.getSuccess())
+        {
+            if (expr.getResult() == 42.0)
+            {
+                COUT(3) << "Greetings from the restaurant at the end of the universe." << std::endl;
+            }
+            if (expr.getRemains() != "")
+            {
+                COUT(2) << "Warning: Expression could not be parsed to the end! Remains: '" << expr.getRemains() << "'" << std::endl;
+            }
+            return expr.getResult();
+        }
+        else
+        {
+            COUT(1) << "Error: Cannot calculate expression: Parse error." << std::endl;
+            return 0;
+        }
+    }
+}
Index: code/branches/network/src/core/ConsoleCommandCompilation.h
===================================================================
--- code/branches/network/src/core/ConsoleCommandCompilation.h	(revision 1446)
+++ code/branches/network/src/core/ConsoleCommandCompilation.h	(revision 1446)
@@ -0,0 +1,49 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ConsoleCommandCompilation_H__
+#define _ConsoleCommandCompilation_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+
+namespace orxonox
+{
+    _CoreExport void source(const std::string& filename);
+    _CoreExport std::string echo(const std::string& text);
+    _CoreExport void puts(bool newline, const std::string& test);
+
+    _CoreExport void write(const std::string& filename, const std::string& text);
+    _CoreExport void append(const std::string& filename, const std::string& text);
+    _CoreExport std::string read(const std::string& filename);
+
+    _CoreExport float calculate(const std::string& calculation);
+}
+
+#endif /* _ConsoleCommandCompilation_H__ */
Index: code/branches/network/src/core/CorePrereqs.h
===================================================================
--- code/branches/network/src/core/CorePrereqs.h	(revision 1445)
+++ code/branches/network/src/core/CorePrereqs.h	(revision 1446)
@@ -66,6 +66,4 @@
 namespace orxonox
 {
-#ifndef _XMLPort_Mode__
-#define _XMLPort_Mode__
   namespace XMLPort
   {
@@ -76,5 +74,4 @@
     };
   }
-#endif
 
   namespace KeybindMode
@@ -91,4 +88,6 @@
   typedef std::string LanguageEntryLabel;
 
+  class ArgumentCompleter;
+  class ArgumentCompletionListElement;
   class BaseFactory;
   class BaseMetaObjectListElement;
@@ -112,4 +111,5 @@
   class ConfigFileSection;
   class ConfigValueContainer;
+  class ConsoleCommand;
   class CoreSettings;
   class Error;
@@ -125,4 +125,5 @@
   class Identifier;
   class IdentifierDistributor;
+  class IRC;
   template <class T>
   class Iterator;
@@ -141,9 +142,14 @@
   class ObjectListElement;
   class OrxonoxClass;
+  class OutputBuffer;
+  class OutputBufferListener;
   class OutputHandler;
   class Shell;
+  class ShellListener;
   template <class T>
   class SubclassIdentifier;
   class TclBind;
+  struct TclInterpreterBundle;
+  class TclThreadManager;
   class Tickable;
   template <class T, class O>
Index: code/branches/network/src/core/CoreSettings.cc
===================================================================
--- code/branches/network/src/core/CoreSettings.cc	(revision 1445)
+++ code/branches/network/src/core/CoreSettings.cc	(revision 1446)
@@ -117,5 +117,7 @@
 
     /**
-        @brief Static function that holds the singleton.
+        @brief Returns the softDebugLevel for the given device (returns a default-value if the class ist right about to be created).
+        @param device The device
+        @return The softDebugLevel
     */
     int CoreSettings::getSoftDebugLevel(OutputHandler::OutputDevice device)
@@ -136,4 +138,24 @@
         return 2;
     }
+
+     /**
+        @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
+        @param device The device
+        @param level The level
+    */
+     void CoreSettings::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
+     {
+        if (!CoreSettings::isCreatingCoreSettings())
+        {
+            if (device == OutputHandler::LD_All)
+                CoreSettings::getInstance().softDebugLevel_ = level;
+            else if (device == OutputHandler::LD_Console)
+                CoreSettings::getInstance().softDebugLevelConsole_ = level;
+            else if (device == OutputHandler::LD_Logfile)
+                CoreSettings::getInstance().softDebugLevelLogfile_ = level;
+            else if (device == OutputHandler::LD_Shell)
+                CoreSettings::getInstance().softDebugLevelShell_ = level;
+        }
+     }
 
     /**
Index: code/branches/network/src/core/CoreSettings.h
===================================================================
--- code/branches/network/src/core/CoreSettings.h	(revision 1445)
+++ code/branches/network/src/core/CoreSettings.h	(revision 1446)
@@ -54,4 +54,5 @@
 
             static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
+            static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
             static const std::string& getLanguage();
             static void resetLanguage();
Index: code/branches/network/src/core/Debug.h
===================================================================
--- code/branches/network/src/core/Debug.h	(revision 1445)
+++ code/branches/network/src/core/Debug.h	(revision 1446)
@@ -206,4 +206,13 @@
    COUT ## x
 
+  #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
+   #define COUT0  \
+    if (getSoftDebugLevel() >= ORX_NONE)  \
+     COUT_EXEC(0)
+  #else
+   #define COUT0 if (ORX_NONE)\
+    COUT_EXEC(0)
+  #endif
+
   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    #define COUT1  \
@@ -256,6 +265,4 @@
  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
 
- #define COUT0 \
-  COUT_EXEC(0)
 #endif /* ifndef COUT */
 
@@ -280,4 +287,13 @@
    CCOUT ## x
 
+  #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
+   #define CCOUT0  \
+    if (getSoftDebugLevel() >= ORX_NONE)  \
+     CCOUT_EXEC(0)
+  #else
+   #define CCOUT0 if (ORX_NONE)\
+    CCOUT_EXEC(0)
+  #endif
+
   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    #define CCOUT1  \
@@ -330,6 +346,4 @@
  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
 
- #define CCOUT0 \
-  CCOUT_EXEC(0)
 #endif /* ifndef CCOUT */
 
Index: code/branches/network/src/core/Executor.cc
===================================================================
--- code/branches/network/src/core/Executor.cc	(revision 1445)
+++ code/branches/network/src/core/Executor.cc	(revision 1446)
@@ -34,12 +34,8 @@
 namespace orxonox
 {
-    Executor::Executor(Functor* functor, const std::string& name, AccessLevel::Level level)
+    Executor::Executor(Functor* functor, const std::string& name)
     {
         this->functor_ = functor;
         this->name_ = name;
-        this->accessLevel_ = level;
-        this->keybindMode_ = KeybindMode::OnPress;
-        this->axisParamIndex_ = -1;
-        this->bAxisRelative_ = false;
 
         this->bAddedDescription_ = false;
Index: code/branches/network/src/core/Executor.h
===================================================================
--- code/branches/network/src/core/Executor.h	(revision 1445)
+++ code/branches/network/src/core/Executor.h	(revision 1446)
@@ -35,4 +35,5 @@
 #include "util/SubString.h"
 #include "util/String.h"
+#include "util/Math.h"
 #include "Functor.h"
 #include "Debug.h"
@@ -100,5 +101,5 @@
             COUT(5) << tokens[i]; \
         } \
-        COUT(5) << ") and " << (paramCount - tokens.size()) << " default values ("; \
+        COUT(5) << ") and " << max((int)paramCount - (int)tokens.size(), 0) << " default values ("; \
         for (unsigned int i = tokens.size(); i < paramCount; i++) \
         { \
@@ -134,17 +135,4 @@
     return true
 
-namespace AccessLevel
-{
-    enum Level
-    {
-        None,
-        User,
-        Admin,
-        Offline,
-        Debug,
-        Disabled
-    };
-}
-
 namespace orxonox
 {
@@ -152,5 +140,5 @@
     {
         public:
-            Executor(Functor* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None);
+            Executor(Functor* functor, const std::string& name = "");
             virtual ~Executor();
 
@@ -181,4 +169,6 @@
             const std::string& getDescriptionReturnvalue(int param) const;
 
+            inline Functor* getFunctor() const
+                { return this->functor_; }
             inline unsigned int getParamCount() const
                 { return this->functor_->getParamCount(); }
@@ -199,24 +189,4 @@
                 { return this->name_; }
 
-            inline void setAccessLevel(AccessLevel::Level level)
-                { this->accessLevel_ = level; }
-            inline AccessLevel::Level getAccessLevel() const
-                { return this->accessLevel_; }
-
-            inline Executor& setKeybindMode(KeybindMode::Enum mode)
-                { this->keybindMode_ = mode; return *this; }
-            inline KeybindMode::Enum getKeybindMode() const
-                { return this->keybindMode_; }
-
-            inline Executor& setAxisParamIndex(int index)
-                { this->axisParamIndex_ = index; return *this; }
-            inline int getAxisParamIndex() const
-                { return this->axisParamIndex_; }
-
-            inline Executor& setIsAxisRelative(bool val)
-                { this->bAxisRelative_ = val; return *this; }
-            inline int getIsAxisRelative() const
-                { return this->bAxisRelative_; }
-
             Executor& setDefaultValues(const MultiTypeMath& param1);
             Executor& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2);
@@ -249,8 +219,4 @@
             bool bAddedDefaultValue_[MAX_FUNCTOR_ARGUMENTS];
 
-            KeybindMode::Enum keybindMode_;
-            int axisParamIndex_;
-            bool bAxisRelative_;
-
         private:
             LanguageEntryLabel description_;
@@ -261,6 +227,4 @@
             bool bAddedDescriptionReturnvalue_;
             bool bAddedDescriptionParam_[MAX_FUNCTOR_ARGUMENTS];
-
-            AccessLevel::Level accessLevel_;
     };
 
@@ -268,5 +232,5 @@
     {
         public:
-            ExecutorStatic(FunctorStatic* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None) : Executor(functor, name, level) {}
+            ExecutorStatic(FunctorStatic* functor, const std::string& name = "") : Executor(functor, name) {}
             virtual ~ExecutorStatic() {}
     };
@@ -276,5 +240,5 @@
     {
         public:
-            ExecutorMember(FunctorMember<T>* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None) : Executor(functor, name, level) {}
+            ExecutorMember(FunctorMember<T>* functor, const std::string& name = "") : Executor(functor, name) {}
             virtual ~ExecutorMember() {}
 
@@ -322,18 +286,18 @@
     };
 
-    inline Executor* createExecutor(Functor* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None)
-    {
-        return new Executor(functor, name, level);
+    inline Executor* createExecutor(Functor* functor, const std::string& name = "")
+    {
+        return new Executor(functor, name);
     }
 
     template <class T>
-    inline ExecutorMember<T>* createExecutor(FunctorMember<T>* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None)
-    {
-        return new ExecutorMember<T>(functor, name, level);
+    inline ExecutorMember<T>* createExecutor(FunctorMember<T>* functor, const std::string& name = "")
+    {
+        return new ExecutorMember<T>(functor, name);
     }
 
-    inline ExecutorStatic* createExecutor(FunctorStatic* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None)
-    {
-        return new ExecutorStatic(functor, name, level);
+    inline ExecutorStatic* createExecutor(FunctorStatic* functor, const std::string& name = "")
+    {
+        return new ExecutorStatic(functor, name);
     }
 }
Index: code/branches/network/src/core/IRC.cc
===================================================================
--- code/branches/network/src/core/IRC.cc	(revision 1446)
+++ code/branches/network/src/core/IRC.cc	(revision 1446)
@@ -0,0 +1,141 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <boost/thread/thread.hpp>
+
+#include "IRC.h"
+#include "ConsoleCommand.h"
+#include "TclThreadManager.h"
+#include "CoreIncludes.h"
+#include "util/Convert.h"
+
+#define IRC_TCL_THREADID 1421421421
+
+namespace orxonox
+{
+    SetConsoleCommand(IRC, say,  true).setAccessLevel(AccessLevel::User);
+    SetConsoleCommand(IRC, msg,  false).setAccessLevel(AccessLevel::User);
+    SetConsoleCommand(IRC, nick, false).setAccessLevel(AccessLevel::User);
+
+    IRC* instance_irc = &IRC::getInstance();
+
+    IRC::IRC()
+    {
+        RegisterRootObject(IRC);
+        this->bundle_ = 0;
+    }
+
+    void IRC::initialize()
+    {
+        unsigned int threadID = (unsigned int)IRC_TCL_THREADID;
+        TclThreadManager::createID(threadID);
+        this->bundle_ = TclThreadManager::getInstance().getInterpreterBundle(threadID);
+
+        try
+        {
+            this->bundle_->interpreter_->def("orxonox::irc::say", IRC::tcl_say, Tcl::variadic());
+            this->bundle_->interpreter_->def("orxonox::irc::privmsg", IRC::tcl_privmsg, Tcl::variadic());
+            this->bundle_->interpreter_->def("orxonox::irc::action", IRC::tcl_action, Tcl::variadic());
+            this->bundle_->interpreter_->def("orxonox::irc::info", IRC::tcl_info, Tcl::variadic());
+        }
+        catch (Tcl::tcl_error const &e)
+        {   COUT(1) << "Tcl (IRC) error: " << e.what();   }
+        catch (std::exception const &e)
+        {   COUT(1) << "Error while initializing Tcl (IRC): " << e.what();   }
+
+        this->nickname_ = "orx" + getConvertedValue<int, std::string>((unsigned int)rand());
+        TclThreadManager::execute(threadID, "set nickname " + this->nickname_);
+        TclThreadManager::execute(threadID, "source irc.tcl");
+    }
+
+    IRC& IRC::getInstance()
+    {
+        static IRC instance;
+        return instance;
+    }
+
+    bool IRC::eval(const std::string& command)
+    {
+        if (!IRC::getInstance().bundle_)
+        {
+            IRC::getInstance().initialize();
+            COUT(1) << "Error: IRC client wasn't yet initialized, please try again." << std::endl;
+            return false;
+        }
+
+        try
+        {
+            IRC::getInstance().bundle_->interpreter_->eval(command);
+            return true;
+        }
+        catch (Tcl::tcl_error const &e)
+        {   COUT(1) << "Tcl (IRC) error: " << e.what();   }
+        catch (std::exception const &e)
+        {   COUT(1) << "Error while executing Tcl (IRC): " << e.what();   }
+
+        return false;
+    }
+
+    void IRC::say(const std::string& message)
+    {
+        if (IRC::eval("irk::say $conn #orxonox {" + message + "}"))
+            IRC::tcl_say(Tcl::object(), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
+    }
+
+    void IRC::msg(const std::string& channel, const std::string& message)
+    {
+        if (IRC::eval("irk::say $conn " + channel + " {" + message + "}"))
+            IRC::tcl_privmsg(Tcl::object(channel), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
+    }
+
+    void IRC::nick(const std::string& nickname)
+    {
+        if (IRC::eval("irk::nick $conn " + nickname))
+            IRC::getInstance().nickname_ = nickname;
+    }
+
+    void IRC::tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+    {
+        COUT(0) << "IRC> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+
+    void IRC::tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args)
+    {
+        COUT(0) << "IRC (" << query.get() << ")> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+
+    void IRC::tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+    {
+        COUT(0) << "IRC> * " << nick.get() << " " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+
+    void IRC::tcl_info(Tcl::object const &channel, Tcl::object const &args)
+    {
+        COUT(0) << "IRC> --> " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+}
Index: code/branches/network/src/core/IRC.h
===================================================================
--- code/branches/network/src/core/IRC.h	(revision 1446)
+++ code/branches/network/src/core/IRC.h	(revision 1446)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _IRC_H__
+#define _IRC_H__
+
+#include "CorePrereqs.h"
+
+#include "OrxonoxClass.h"
+#include "cpptcl/CppTcl.h"
+
+namespace orxonox
+{
+    class _CoreExport IRC : public OrxonoxClass
+    {
+        public:
+            static IRC& getInstance();
+
+            static void say(const std::string& message);
+            static void msg(const std::string& channel, const std::string& message);
+            static void nick(const std::string& nickname);
+
+            static void tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
+            static void tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args);
+            static void tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
+            static void tcl_info(Tcl::object const &channel, Tcl::object const &args);
+
+        private:
+            static bool eval(const std::string& command);
+            void initialize();
+
+            IRC();
+            IRC(const IRC& other);
+            ~IRC() {}
+
+            TclInterpreterBundle* bundle_;
+            std::string nickname_;
+    };
+}
+
+#endif /* _IRC_H__ */
Index: code/branches/network/src/core/Identifier.cc
===================================================================
--- code/branches/network/src/core/Identifier.cc	(revision 1445)
+++ code/branches/network/src/core/Identifier.cc	(revision 1446)
@@ -37,5 +37,5 @@
 
 #include "Factory.h"
-#include "Executor.h"
+#include "ConsoleCommand.h"
 #include "CommandExecutor.h"
 
@@ -231,4 +231,10 @@
     void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
     {
+        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
+        if (it != this->configValues_.end())
+        {
+            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
+        }
+
         this->bHasConfigValues_ = true;
         this->configValues_[varname] = container;
@@ -270,14 +276,20 @@
         @return The executor of the command
     */
-    ExecutorStatic& Identifier::addConsoleCommand(ExecutorStatic* executor, bool bCreateShortcut)
-    {
+    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
+        if (it != this->consoleCommands_.end())
+        {
+            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
+        }
+
         this->bHasConsoleCommands_ = true;
-        this->consoleCommands_[executor->getName()] = executor;
-        this->consoleCommands_LC_[getLowercase(executor->getName())] = executor;
+        this->consoleCommands_[command->getName()] = command;
+        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
 
         if (bCreateShortcut)
-            CommandExecutor::addConsoleCommandShortcut(executor);
-
-        return (*executor);
+            CommandExecutor::addConsoleCommandShortcut(command);
+
+        return (*command);
     }
 
@@ -287,7 +299,7 @@
         @return The executor of the requested console command
     */
-    ExecutorStatic* Identifier::getConsoleCommand(const std::string& name) const
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = this->consoleCommands_.find(name);
+    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
         if (it != this->consoleCommands_.end())
             return (*it).second;
@@ -301,7 +313,7 @@
         @return The executor of the requested console command
     */
-    ExecutorStatic* Identifier::getLowercaseConsoleCommand(const std::string& name) const
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = this->consoleCommands_LC_.find(name);
+    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
         if (it != this->consoleCommands_LC_.end())
             return (*it).second;
Index: code/branches/network/src/core/Identifier.h
===================================================================
--- code/branches/network/src/core/Identifier.h	(revision 1445)
+++ code/branches/network/src/core/Identifier.h	(revision 1446)
@@ -63,4 +63,5 @@
 #include "Debug.h"
 #include "Iterator.h"
+#include "MetaObjectList.h"
 #include "util/String.h"
 
@@ -175,16 +176,16 @@
 
             /** @brief Returns the map that stores all console commands. @return The const_iterator */
-            inline const std::map<std::string, ExecutorStatic*>& getConsoleCommandMap() const { return this->consoleCommands_; }
+            inline const std::map<std::string, ConsoleCommand*>& getConsoleCommandMap() const { return this->consoleCommands_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandMapBegin() const { return this->consoleCommands_.begin(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandMapBegin() const { return this->consoleCommands_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandMapEnd() const { return this->consoleCommands_.end(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandMapEnd() const { return this->consoleCommands_.end(); }
 
             /** @brief Returns the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            inline const std::map<std::string, ExecutorStatic*>& getLowercaseConsoleCommandMap() const { return this->consoleCommands_LC_; }
+            inline const std::map<std::string, ConsoleCommand*>& getLowercaseConsoleCommandMap() const { return this->consoleCommands_LC_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandMapBegin() const { return this->consoleCommands_LC_.begin(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandMapBegin() const { return this->consoleCommands_LC_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandMapEnd() const { return this->consoleCommands_LC_.end(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandMapEnd() const { return this->consoleCommands_LC_.end(); }
 
 
@@ -213,7 +214,7 @@
             virtual XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname) = 0;
 
-            ExecutorStatic& addConsoleCommand(ExecutorStatic* executor, bool bCreateShortcut);
-            ExecutorStatic* getConsoleCommand(const std::string& name) const;
-            ExecutorStatic* getLowercaseConsoleCommand(const std::string& name) const;
+            ConsoleCommand& addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut);
+            ConsoleCommand* getConsoleCommand(const std::string& name) const;
+            ConsoleCommand* getLowercaseConsoleCommand(const std::string& name) const;
 
         protected:
@@ -270,6 +271,6 @@
 
             bool bHasConsoleCommands_;                                     //!< True if this class has at least one assigned console command
-            std::map<std::string, ExecutorStatic*> consoleCommands_;       //!< All console commands of this class
-            std::map<std::string, ExecutorStatic*> consoleCommands_LC_;    //!< All console commands of this class with their names in lowercase
+            std::map<std::string, ConsoleCommand*> consoleCommands_;       //!< All console commands of this class
+            std::map<std::string, ConsoleCommand*> consoleCommands_LC_;    //!< All console commands of this class with their names in lowercase
     };
 
Index: code/branches/network/src/core/InputBuffer.cc
===================================================================
--- code/branches/network/src/core/InputBuffer.cc	(revision 1445)
+++ code/branches/network/src/core/InputBuffer.cc	(revision 1446)
@@ -37,179 +37,232 @@
 namespace orxonox
 {
-  InputBuffer::InputBuffer(const std::string allowedChars) :
-    buffer_(""),
-    allowedChars_(allowedChars),
-    lastKey_(KeyCode::Unassigned),
-    timeSinceKeyPressed_(0.0f),
-    timeSinceKeyRepeated_(0.0f),
-    keysToRepeat_(0)
-  {
-    RegisterObject(InputBuffer);
-    setConfigValues();
-  }
-
-  void InputBuffer::setConfigValues()
-  {
-    SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat deleay of the input buffer");
-    SetConfigValue(keyRepeatTime_, 0.022).description("Key repeat time of the input buffer");
-    if (keyRepeatDeleay_ < 0.0)
-    {
-      ResetConfigValue(keyRepeatDeleay_);
-    }
-    if (keyRepeatTime_ < 0.0)
-    {
-      ResetConfigValue(keyRepeatTime_);
-    }
-  }
-  /*
-  void InputBuffer::registerListener(InputBufferListener* listener, void (InputBufferListener::*function)(), bool bOnlySingleInput)
-  {
-    struct InputBufferListenerTuple newListener = {listener, function, true, bOnlySingleInput, ' '};
-    listeners_.insert(listeners_.end(), newListener);
-  }
-
-  void InputBuffer::registerListener(InputBufferListener* listener, void (InputBufferListener::*function)(), char char_, bool bOnlySingleInput)
-  {
-    struct InputBufferListenerTuple newListener = {listener, function, false, bOnlySingleInput, char_};
-    listeners_.insert(listeners_.end(), newListener);
-  }
-  */
-  void InputBuffer::set(const std::string& input)
-  {
-    buffer_ = "";
-    append(input);
-  }
-
-  void InputBuffer::append(const std::string& input)
-  {
-    for (unsigned int i = 0; i < input.size(); i++)
-    {
-      if (charIsAllowed(input[i]))
-        buffer_ += input[i];
-
-      updated(input[i], false);
-    }
-    updated();
-  }
-
-  void InputBuffer::append(const char& input)
-  {
-    if (charIsAllowed(input))
-      buffer_ += input;
-
-    updated(input, true);
-  }
-
-  void InputBuffer::clear()
-  {
-    buffer_ = "";
-    updated();
-  }
-
-  void InputBuffer::removeLast()
-  {
-    buffer_ = buffer_.substr(0, buffer_.size() - 1);
-    updated();
-  }
-
-  void InputBuffer::updated()
-  {
-    for (std::list<InputBufferListenerTuple>::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
-    {
-      if ((*it).bListenToAllChanges_)
-        (*(*it).listener_.*(*it).function_)();
-    }
-  }
-
-  void InputBuffer::updated(const char& update, bool bSingleInput)
-  {
-    for (std::list<InputBufferListenerTuple>::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
-    {
-      if (((*it).bListenToAllChanges_ || ((*it).char_ == update)) && (!(*it).bOnlySingleInput_ || bSingleInput))
-        (*(*it).listener_.*(*it).function_)();
-    }
-  }
-
-  bool InputBuffer::charIsAllowed(const char& input)
-  {
-    if (allowedChars_ == "")
-      return true;
-    else
-      return (allowedChars_.find(input) != std::string::npos);
-  }
-
-
-  void InputBuffer::processKey(const KeyEvent &evt)
-  {
-    if (evt.isModifierDown(KeyboardModifier::Ctrl))
-    {
-      if (evt.key == KeyCode::V)
-        append(fromClipboard());
-      else if (evt.key == KeyCode::C)
-        toClipboard(buffer_);
-      else if (evt.key == KeyCode::X)
-      {
-        toClipboard(buffer_);
-        clear();
-      }
-    }
-    else if (evt.isModifierDown(KeyboardModifier::Shift))
-    {
-      if (evt.key == KeyCode::Insert)
-      {
-        append(fromClipboard());
-      }
-      else if (evt.key == KeyCode::Delete)
-      {
-        toClipboard(buffer_);
-        clear();
-      }
-    }
-    //std::string input = keyboard_->getAsString(e.key);
-    /*if (input.size() >= 1)
-    append(input[0]);*/
-
-    append((char)evt.text);
-  }
-
-  /**
-  * This tick() function is called by the InputManager if the InputBuffer is active.
-  * @param dt Delta time
-  */
-  void InputBuffer::tickInput(float dt, const HandlerState& state)
-  {
-    timeSinceKeyPressed_ += dt;
-    if (keysToRepeat_ < 10 && timeSinceKeyPressed_ > keyRepeatDeleay_)
-    {
-      // initial time out has gone by, start repeating keys
-      while (timeSinceKeyPressed_ - timeSinceKeyRepeated_ > keyRepeatTime_)
-      {
-        timeSinceKeyRepeated_ += keyRepeatTime_;
-        keysToRepeat_++;
-      }
-    }
-  }
-
-  void InputBuffer::keyPressed(const KeyEvent &evt)
-  {
-    lastKey_ = evt.key;
-    timeSinceKeyPressed_ = 0.0;
-    timeSinceKeyRepeated_ = keyRepeatDeleay_;
-    keysToRepeat_ = 0;
-
-    processKey(evt);
-  }
-
-  void InputBuffer::keyHeld(const KeyEvent& evt)
-  {
-    if (evt.key == lastKey_)
-    {
-      while (keysToRepeat_)
-      {
+    InputBuffer::InputBuffer()
+    {
+        RegisterObject(InputBuffer);
+
+        this->buffer_ = "";
+        this->cursor_ = 0;
+        this->allowedChars_ = "abcdefghijklmnopqrstuvwxyz \
+                               ABCDEFGHIJKLMNOPQRSTUVWXYZ \
+                               äëïöüÄËÏÖÜáâàéêèíîìóôòúûù \
+                               0123456789 \
+                               \\\"(){}[]<>.:,;_-+*/=!?|$&%^~#";
+
+        this->lastKey_ = KeyCode::Unassigned;
+        this->timeSinceKeyPressed_ = 0.0f;
+        this->timeSinceKeyRepeated_ = 0.0f;
+        this->keysToRepeat_ = 0;
+
+        setConfigValues();
+    }
+
+    InputBuffer::InputBuffer(const std::string allowedChars)
+    {
+        RegisterObject(InputBuffer);
+
+        this->allowedChars_ = allowedChars;
+        this->buffer_ = "";
+        this->cursor_ = 0;
+
+        this->lastKey_ = KeyCode::Unassigned;
+        this->timeSinceKeyPressed_ = 0.0f;
+        this->timeSinceKeyRepeated_ = 0.0f;
+        this->keysToRepeat_ = 0;
+
+        setConfigValues();
+    }
+
+    void InputBuffer::setConfigValues()
+    {
+        SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat deleay of the input buffer");
+        SetConfigValue(keyRepeatTime_, 0.022).description("Key repeat time of the input buffer");
+
+        if (keyRepeatDeleay_ < 0.0)
+        {
+            ResetConfigValue(keyRepeatDeleay_);
+        }
+        if (keyRepeatTime_ < 0.0)
+        {
+            ResetConfigValue(keyRepeatTime_);
+        }
+    }
+
+    void InputBuffer::unregisterListener(InputBufferListener* listener)
+    {
+        for (std::list<InputBufferListenerTuple>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+        {
+            if ((*it).listener_ == listener)
+                this->listeners_.erase(it++);
+            else
+                ++it;
+        }
+    }
+
+    void InputBuffer::set(const std::string& input, bool update)
+    {
+        this->clear(false);
+        this->insert(input, update);
+    }
+
+    void InputBuffer::insert(const std::string& input, bool update)
+    {
+        for (unsigned int i = 0; i < input.size(); ++i)
+        {
+            this->insert(input[i], false);
+
+            if (update)
+                this->updated(input[i], false);
+        }
+
+        if (update)
+            this->updated();
+    }
+
+    void InputBuffer::insert(const char& input, bool update)
+    {
+        if (this->charIsAllowed(input))
+        {
+            this->buffer_.insert(this->cursor_, 1, input);
+            ++this->cursor_;
+        }
+
+        if (update)
+            this->updated(input, true);
+    }
+
+    void InputBuffer::clear(bool update)
+    {
+        this->buffer_ = "";
+        this->cursor_ = 0;
+
+        if (update)
+            this->updated();
+    }
+
+    void InputBuffer::removeBehindCursor(bool update)
+    {
+        if (this->cursor_ > 0)
+        {
+            --this->cursor_;
+            this->buffer_.erase(this->cursor_, 1);
+
+            if (update)
+                this->updated();
+        }
+    }
+
+    void InputBuffer::removeAtCursor(bool update)
+    {
+        if (this->cursor_ < this->buffer_.size())
+        {
+            this->buffer_.erase(this->cursor_, 1);
+
+            if (update)
+                this->updated();
+        }
+    }
+
+    void InputBuffer::updated()
+    {
+        for (std::list<InputBufferListenerTuple>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((*it).bListenToAllChanges_)
+                (*(*it).listener_.*(*it).function_)();
+        }
+    }
+
+    void InputBuffer::updated(const char& update, bool bSingleInput)
+    {
+        for (std::list<InputBufferListenerTuple>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((!(*it).trueKeyFalseChar_) && ((*it).bListenToAllChanges_ || ((*it).char_ == update)) && (!(*it).bOnlySingleInput_ || bSingleInput))
+                (*(*it).listener_.*(*it).function_)();
+        }
+    }
+
+    bool InputBuffer::charIsAllowed(const char& input)
+    {
+        if (this->allowedChars_ == "")
+            return true;
+        else
+            return (this->allowedChars_.find(input) != std::string::npos);
+    }
+
+
+    void InputBuffer::processKey(const KeyEvent &evt)
+    {
+        if (evt.isModifierDown(KeyboardModifier::Alt) && evt.key == KeyCode::Tab)
+            return;
+
+        for (std::list<InputBufferListenerTuple>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((*it).trueKeyFalseChar_ && ((*it).key_ == evt.key))
+                (*(*it).listener_.*(*it).function_)();
+        }
+
+        if (evt.isModifierDown(KeyboardModifier::Ctrl))
+        {
+            if (evt.key == KeyCode::V)
+                this->insert(fromClipboard());
+            else if (evt.key == KeyCode::C)
+                toClipboard(this->buffer_);
+            else if (evt.key == KeyCode::X)
+            {
+                toClipboard(this->buffer_);
+                this->clear();
+            }
+        }
+        else if (evt.isModifierDown(KeyboardModifier::Shift))
+        {
+            if (evt.key == KeyCode::Insert)
+                this->insert(fromClipboard());
+            else if (evt.key == KeyCode::Delete)
+            {
+                toClipboard(this->buffer_);
+                this->clear();
+            }
+        }
+
+        this->insert((char)evt.text);
+    }
+
+    /**
+        @brief This tick() function is called by the InputManager if the InputBuffer is active.
+        @param dt Delta time
+    */
+    void InputBuffer::tickInput(float dt, const HandlerState& state)
+    {
+        timeSinceKeyPressed_ += dt;
+        if (keysToRepeat_ < 10 && timeSinceKeyPressed_ > keyRepeatDeleay_)
+        {
+            // initial time out has gone by, start repeating keys
+            while (timeSinceKeyPressed_ - timeSinceKeyRepeated_ > keyRepeatTime_)
+            {
+                timeSinceKeyRepeated_ += keyRepeatTime_;
+                keysToRepeat_++;
+            }
+        }
+    }
+
+    void InputBuffer::keyPressed(const KeyEvent &evt)
+    {
+        lastKey_ = evt.key;
+        timeSinceKeyPressed_ = 0.0;
+        timeSinceKeyRepeated_ = keyRepeatDeleay_;
+        keysToRepeat_ = 0;
+
         processKey(evt);
-        keysToRepeat_--;
-      }
-    }
-  }
-
+    }
+
+    void InputBuffer::keyHeld(const KeyEvent& evt)
+    {
+        if (evt.key == lastKey_)
+        {
+            while (keysToRepeat_)
+            {
+                processKey(evt);
+                keysToRepeat_--;
+            }
+        }
+    }
 }
Index: code/branches/network/src/core/InputBuffer.h
===================================================================
--- code/branches/network/src/core/InputBuffer.h	(revision 1445)
+++ code/branches/network/src/core/InputBuffer.h	(revision 1446)
@@ -36,90 +36,122 @@
 
 #include "InputInterfaces.h"
-#include "Tickable.h"
+#include "OrxonoxClass.h"
 
 namespace orxonox
 {
-  class _CoreExport InputBufferListener
-  {};
+    class _CoreExport InputBufferListener
+    {};
 
-  class _CoreExport InputBuffer : public KeyHandler, public OrxonoxClass
-  {
-    struct InputBufferListenerTuple
+    class _CoreExport InputBuffer : public KeyHandler, public OrxonoxClass
     {
-      InputBufferListener* listener_;
-      void (InputBufferListener::*function_)();
-      bool bListenToAllChanges_;
-      bool bOnlySingleInput_;
-      char char_;
+        struct InputBufferListenerTuple
+        {
+            InputBufferListener* listener_;
+            void (InputBufferListener::*function_)();
+            bool bListenToAllChanges_;
+            bool bOnlySingleInput_;
+            bool trueKeyFalseChar_;
+            char char_;
+            KeyCode::Enum key_;
+        };
+
+        public:
+            InputBuffer();
+            InputBuffer(const std::string allowedChars);
+
+            void setConfigValues();
+
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), bool bOnlySingleInput)
+            {
+                struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, true, bOnlySingleInput, false, '\0', KeyCode::Unassigned};
+                this->listeners_.insert(this->listeners_.end(), newListener);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)() const, bool bOnlySingleInput)
+            {
+                struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, true, bOnlySingleInput, false, '\0', KeyCode::Unassigned};
+                this->listeners_.insert(this->listeners_.end(), newListener);
+            }
+
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), char _char, bool bOnlySingleInput)
+            {
+                struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, bOnlySingleInput, false, _char, KeyCode::Unassigned};
+                this->listeners_.insert(this->listeners_.end(), newListener);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)() const, char _char, bool bOnlySingleInput)
+            {
+                struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, bOnlySingleInput, false, _char, KeyCode::Unassigned};
+                this->listeners_.insert(this->listeners_.end(), newListener);
+            }
+
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), KeyCode::Enum key)
+            {
+                struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, true, true, '\0', key};
+                this->listeners_.insert(this->listeners_.end(), newListener);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)() const, KeyCode::Enum key)
+            {
+                struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, true, true, '\0', key};
+                this->listeners_.insert(this->listeners_.end(), newListener);
+            }
+
+            void unregisterListener(InputBufferListener* listener);
+
+            void set(const std::string& input, bool update = true);
+            void insert(const std::string& input, bool update = true);
+            void insert(const char& input, bool update = true);
+            void clear(bool update = true);
+            void removeAtCursor(bool update = true);
+            void removeBehindCursor(bool update = true);
+
+            void updated();
+            void updated(const char& update, bool bSingleInput);
+
+            inline std::string get() const
+                { return this->buffer_; }
+            inline unsigned int getSize() const
+                { return this->buffer_.size(); }
+
+            inline unsigned int getCursorPosition() const
+                { return this->cursor_; }
+            inline void setCursorPosition(unsigned int cursor)
+                { if (cursor <= this->buffer_.size()) { this->cursor_ = cursor; } }
+            inline void setCursorToEnd()
+                { this->cursor_ = this->buffer_.size(); }
+            inline void setCursorToBegin()
+                { this->cursor_ = 0; }
+            inline void increaseCursor()
+                { if (this->cursor_ < this->buffer_.size()) { ++this->cursor_; } }
+            inline void decreaseCursor()
+                { if (this->cursor_ > 0) { --this->cursor_; } }
+
+        private:
+            bool charIsAllowed(const char& input);
+
+            void keyPressed (const KeyEvent& evt);
+            void keyReleased(const KeyEvent& evt) { }
+            void keyHeld    (const KeyEvent& evt);
+            void processKey (const KeyEvent &e);
+
+            void tickInput(float dt, const HandlerState& state);
+
+            std::string buffer_;
+            std::list<InputBufferListenerTuple> listeners_;
+            std::string allowedChars_;
+            unsigned int cursor_;
+
+            KeyCode::Enum lastKey_;
+            float timeSinceKeyPressed_;
+            float timeSinceKeyRepeated_;
+            int keysToRepeat_;
+
+            float keyRepeatDeleay_;
+            float keyRepeatTime_;
     };
-
-  public:
-    InputBuffer(const std::string allowedChars =
-      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZäöüÄÖÜ0123456789 \\\"(){}[]<>.:,;_-+*/=!?|$&%^");
-
-    void setConfigValues();
-
-    template <class T>
-    void registerListener(T* listener, void (T::*function)(), bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, true, bOnlySingleInput, ' '};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
-    template <class T>
-    void registerListener(T* listener, void (T::*function)() const, bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, true, bOnlySingleInput, ' '};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
-
-    template <class T>
-    void registerListener(T* listener, void (T::*function)(), char char_, bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, bOnlySingleInput, char_};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
-    template <class T>
-    void registerListener(T* listener, void (T::*function)() const, char char_, bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, bOnlySingleInput, char_};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
-
-    void set(const std::string& input);
-    void append(const std::string& input);
-    void append(const char& input);
-    void removeLast();
-    void clear();
-
-    void updated();
-    void updated(const char& update, bool bSingleInput);
-
-    inline std::string get() const
-    { return this->buffer_; }
-
-  private:  // functions
-    bool charIsAllowed(const char& input);
-
-    void keyPressed (const KeyEvent& evt);
-    void keyReleased(const KeyEvent& evt) { }
-    void keyHeld    (const KeyEvent& evt);
-    void processKey (const KeyEvent &e);
-
-    void tickInput(float dt, const HandlerState& state);
-
-  private: // variables
-    std::string buffer_;
-    std::list<InputBufferListenerTuple> listeners_;
-    std::string allowedChars_;
-
-    KeyCode::Enum lastKey_;
-    float timeSinceKeyPressed_;
-    float timeSinceKeyRepeated_;
-    int keysToRepeat_;
-
-    // configured values
-    float keyRepeatDeleay_;
-    float keyRepeatTime_;
-  };
 }
 
Index: code/branches/network/src/core/InputManager.cc
===================================================================
--- code/branches/network/src/core/InputManager.cc	(revision 1445)
+++ code/branches/network/src/core/InputManager.cc	(revision 1446)
@@ -42,10 +42,11 @@
 #include "CommandExecutor.h"
 #include "ConsoleCommand.h"
+#include "Shell.h"
 
 namespace orxonox
 {
-  ConsoleCommandShortcut(InputManager, keyBind, AccessLevel::User);
-  ConsoleCommandShortcut(InputManager, storeKeyStroke, AccessLevel::Offline);
-  ConsoleCommandShortcut(InputManager, calibrate, AccessLevel::User);
+  SetConsoleCommandShortcut(InputManager, keyBind);
+  SetConsoleCommandShortcut(InputManager, storeKeyStroke);
+  SetConsoleCommandShortcut(InputManager, calibrate);
 
   // ###############################
@@ -150,4 +151,5 @@
       buffer_ = new InputBuffer();
       addKeyHandler(buffer_, "buffer");
+      Shell::getInstance().setInputBuffer(buffer_);
 
       keyBinder_ = new KeyBinder();
@@ -233,5 +235,5 @@
         // register our listener in OIS.
         mouse_->setEventCallback(this);
-        CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
+        CCOUT(ORX_DEBUG) << "Created OIS mouse" << std::endl;
         return true;
       }
@@ -907,5 +909,5 @@
       for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
         activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, axis, fValue);
-    }    
+    }
   }
 
@@ -953,5 +955,5 @@
     if (lastState & OIS::Pov::West)
       buttonReleased(arg, 32 + id * 4 + 3);
-    
+
     povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
 
Index: code/branches/network/src/core/Iterator.h
===================================================================
--- code/branches/network/src/core/Iterator.h	(revision 1445)
+++ code/branches/network/src/core/Iterator.h	(revision 1446)
@@ -50,5 +50,4 @@
 
 #include "ObjectList.h"
-#include "Debug.h"
 
 namespace orxonox
Index: code/branches/network/src/core/KeyBinder.cc
===================================================================
--- code/branches/network/src/core/KeyBinder.cc	(revision 1445)
+++ code/branches/network/src/core/KeyBinder.cc	(revision 1446)
@@ -42,4 +42,5 @@
 #include "CoreIncludes.h"
 #include "CommandExecutor.h"
+#include "ConsoleCommand.h"
 #include "Executor.h"
 // TODO: only needed by the CalibratorCallback class; move to new file
@@ -66,5 +67,5 @@
       cmd.nValuesAdded_ = 0;
       cmd.value_ = 0;
-      return CommandExecutor::execute(cmd.evaluation_);
+      return cmd.evaluation_.execute();
     }
     else
@@ -82,5 +83,5 @@
   bool SimpleCommand::execute(float abs, float rel)
   {
-    return CommandExecutor::execute(evaluation_);
+    return evaluation_.execute();
   }
 
@@ -183,5 +184,5 @@
         SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
             '\\', false, '"', false, '(', ')', false, '\0');
-        
+
         unsigned int iToken = 0;
 
@@ -238,5 +239,5 @@
 
         // check for param command
-        int paramIndex = eval.getEvaluatedExecutor()->getAxisParamIndex();
+        int paramIndex = eval.getConsoleCommand()->getAxisParamIndex();
         if (paramIndex >= 0)
         {
@@ -244,10 +245,10 @@
           ParamCommand* cmd = new ParamCommand();
           cmd->paramModifier_ = paramModifier;
-          cmd->bRelative_ = eval.getEvaluatedExecutor()->getIsAxisRelative();
+          cmd->bRelative_ = eval.getConsoleCommand()->getIsAxisRelative();
 
           // add command to the buffer if not yet existing
           for (unsigned int iParamCmd = 0; iParamCmd < paramCommandBuffer.size(); iParamCmd++)
           {
-            if (getLowercase(paramCommandBuffer[iParamCmd]->evaluation_.getCommandString())
+            if (getLowercase(paramCommandBuffer[iParamCmd]->evaluation_.getOriginalCommand())
                 == getLowercase(commandStr))
             {
@@ -271,5 +272,5 @@
             if (!addParamCommand(cmd))
             {
-              mode = eval.getEvaluatedExecutor()->getKeybindMode();
+              mode = eval.getConsoleCommand()->getKeybindMode();
               commands[mode].push_back(cmd);
             }
@@ -282,5 +283,5 @@
 
           if (mode == KeybindMode::None)
-            mode = eval.getEvaluatedExecutor()->getKeybindMode();
+            mode = eval.getConsoleCommand()->getKeybindMode();
 
           commands[mode].push_back(cmd);
@@ -331,5 +332,5 @@
     }
   }
-  
+
   bool HalfAxis::addParamCommand(ParamCommand* command)
   {
Index: code/branches/network/src/core/KeyBinder.h
===================================================================
--- code/branches/network/src/core/KeyBinder.h	(revision 1445)
+++ code/branches/network/src/core/KeyBinder.h	(revision 1446)
@@ -43,5 +43,5 @@
 #include "util/Math.h"
 #include "OrxonoxClass.h"
-#include "CommandExecutor.h"
+#include "CommandEvaluation.h"
 #include "InputInterfaces.h"
 
Index: code/branches/network/src/core/Language.cc
===================================================================
--- code/branches/network/src/core/Language.cc	(revision 1445)
+++ code/branches/network/src/core/Language.cc	(revision 1446)
@@ -37,4 +37,6 @@
 
 #include "CoreSettings.h"
+
+#include "Debug.h"
 
 namespace orxonox
Index: code/branches/network/src/core/Language.h
===================================================================
--- code/branches/network/src/core/Language.h	(revision 1445)
+++ code/branches/network/src/core/Language.h	(revision 1446)
@@ -50,5 +50,4 @@
 #include <map>
 #include <string>
-
 
 #define AddLanguageEntry(label, fallbackstring) \
Index: code/branches/network/src/core/OrxonoxClass.cc
===================================================================
--- code/branches/network/src/core/OrxonoxClass.cc	(revision 1445)
+++ code/branches/network/src/core/OrxonoxClass.cc	(revision 1446)
@@ -33,4 +33,6 @@
 
 #include "OrxonoxClass.h"
+#include "MetaObjectList.h"
+#include "Identifier.h"
 
 namespace orxonox
@@ -41,4 +43,6 @@
       parents_(0)
     {
+        this->metaList_ = new MetaObjectList();
+
         this->setConfigValues();
     }
@@ -47,7 +51,88 @@
     OrxonoxClass::~OrxonoxClass()
     {
+        delete this->metaList_;
+
         // parents_ exists only if isCreatingHierarchy() of the associated Identifier returned true while creating the class
         if (this->parents_)
             delete this->parents_;
     }
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const Identifier* identifier)
+        { return this->getIdentifier()->isA(identifier); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const Identifier* identifier)
+        { return this->getIdentifier()->isExactlyA(identifier); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const Identifier* identifier)
+        { return this->getIdentifier()->isChildOf(identifier); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const Identifier* identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const Identifier* identifier)
+        { return this->getIdentifier()->isParentOf(identifier); }
+    /** @brief Returns true if the objects class is a direct parent of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const Identifier* identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier); }
+
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isA(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isExactlyA(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isChildOf(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isParentOf(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct parent of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier->getIdentifier()); }
+
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isA(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isExactlyA(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isChildOf(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isParentOf(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct parent of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier.getIdentifier()); }
+
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const OrxonoxClass* object)
+        { return this->getIdentifier()->isA(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const OrxonoxClass* object)
+        { return this->getIdentifier()->isExactlyA(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isChildOf(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isDirectChildOf(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isParentOf(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isDirectParentOf(object->getIdentifier()); }
 }
Index: code/branches/network/src/core/OrxonoxClass.h
===================================================================
--- code/branches/network/src/core/OrxonoxClass.h	(revision 1445)
+++ code/branches/network/src/core/OrxonoxClass.h	(revision 1446)
@@ -43,7 +43,4 @@
 #include <string>
 
-#include "MetaObjectList.h"
-#include "Iterator.h"
-
 namespace orxonox
 {
@@ -75,90 +72,39 @@
 
             /** @brief Returns the MetaObjectList of the object, containing a link to all ObjectLists and ObjectListElements the object is registered in. @return The list */
-            inline MetaObjectList& getMetaList() { return this->metaList_; }
+            inline MetaObjectList& getMetaList() { return (*this->metaList_); }
 
 
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const Identifier* identifier)
-                { return this->getIdentifier()->isA(identifier); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const Identifier* identifier)
-                { return this->getIdentifier()->isExactlyA(identifier); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const Identifier* identifier)
-                { return this->getIdentifier()->isChildOf(identifier); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const Identifier* identifier)
-                { return this->getIdentifier()->isDirectChildOf(identifier); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const Identifier* identifier)
-                { return this->getIdentifier()->isParentOf(identifier); }
-            /** @brief Returns true if the objects class is a direct parent of the given type. */
-            inline bool isDirectParentOf(const Identifier* identifier)
-                { return this->getIdentifier()->isDirectParentOf(identifier); }
+            bool isA(const Identifier* identifier);
+            bool isExactlyA(const Identifier* identifier);
+            bool isChildOf(const Identifier* identifier);
+            bool isDirectChildOf(const Identifier* identifier);
+            bool isParentOf(const Identifier* identifier);
+            bool isDirectParentOf(const Identifier* identifier);
 
+            bool isA(const SubclassIdentifier<class B>* identifier);
+            bool isExactlyA(const SubclassIdentifier<class B>* identifier);
+            bool isChildOf(const SubclassIdentifier<class B>* identifier);
+            bool isDirectChildOf(const SubclassIdentifier<class B>* identifier);
+            bool isParentOf(const SubclassIdentifier<class B>* identifier);
+            bool isDirectParentOf(const SubclassIdentifier<class B>* identifier);
 
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isA(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isExactlyA(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isChildOf(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isDirectChildOf(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isParentOf(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct parent of the given type. */
-            inline bool isDirectParentOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isDirectParentOf(identifier->getIdentifier()); }
+            bool isA(const SubclassIdentifier<class B> identifier);
+            bool isExactlyA(const SubclassIdentifier<class B> identifier);
+            bool isChildOf(const SubclassIdentifier<class B> identifier);
+            bool isDirectChildOf(const SubclassIdentifier<class B> identifier);
+            bool isParentOf(const SubclassIdentifier<class B> identifier);
+            bool isDirectParentOf(const SubclassIdentifier<class B> identifier);
 
-
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isA(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isExactlyA(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isChildOf(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isDirectChildOf(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isParentOf(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct parent of the given type. */
-            inline bool isDirectParentOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isDirectParentOf(identifier.getIdentifier()); }
-
-
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const OrxonoxClass* object)
-                { return this->getIdentifier()->isA(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const OrxonoxClass* object)
-                { return this->getIdentifier()->isExactlyA(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isChildOf(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isDirectChildOf(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isParentOf(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectParentOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isDirectParentOf(object->getIdentifier()); }
+            bool isA(const OrxonoxClass* object);
+            bool isExactlyA(const OrxonoxClass* object);
+            bool isChildOf(const OrxonoxClass* object);
+            bool isDirectChildOf(const OrxonoxClass* object);
+            bool isParentOf(const OrxonoxClass* object);
+            bool isDirectParentOf(const OrxonoxClass* object);
 
         private:
-            Identifier* identifier_;                    //!< The Identifier of the object
+            Identifier* identifier_;                   //!< The Identifier of the object
             std::set<const Identifier*>* parents_;     //!< List of all parents of the object
-            MetaObjectList metaList_;                   //!< MetaObjectList, containing all ObjectLists and ObjectListElements the object is registered in
+            MetaObjectList* metaList_;                 //!< MetaObjectList, containing all ObjectLists and ObjectListElements the object is registered in
     };
 }
Index: code/branches/network/src/core/OutputBuffer.cc
===================================================================
--- code/branches/network/src/core/OutputBuffer.cc	(revision 1446)
+++ code/branches/network/src/core/OutputBuffer.cc	(revision 1446)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OutputBuffer.h"
+
+#define OUTPUTBUFFER_MAX_LINE_LENGTH 16384
+
+namespace orxonox
+{
+    void OutputBuffer::registerListener(OutputBufferListener* listener)
+    {
+        this->listeners_.insert(this->listeners_.end(), listener);
+    }
+
+    void OutputBuffer::unregisterListener(OutputBufferListener* listener)
+    {
+        for (std::list<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+        {
+            if ((*it) == listener)
+                this->listeners_.erase(it++);
+            else
+                ++it;
+        }
+    }
+
+    OutputBuffer& OutputBuffer::operator<<(std::ostream& (*manipulator)(std::ostream&))
+    {
+                this->stream_ << manipulator;
+                this->callListeners();
+                return *this;
+    }
+
+    OutputBuffer& OutputBuffer::operator<<(std::ios& (*manipulator)(std::ios&))
+    {
+                this->stream_ << manipulator;
+                this->callListeners();
+                return *this;
+    }
+
+    OutputBuffer& OutputBuffer::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
+    {
+                this->stream_ << manipulator;
+                this->callListeners();
+                return *this;
+    }
+
+    bool OutputBuffer::getLine(std::string* output)
+    {
+        char line[OUTPUTBUFFER_MAX_LINE_LENGTH];
+
+        this->stream_.getline(line, OUTPUTBUFFER_MAX_LINE_LENGTH);
+        (*output) = std::string(line);
+
+        bool eof = this->stream_.eof();
+        bool fail = this->stream_.fail();
+
+        if (eof)
+            this->stream_.flush();
+
+        if (eof || fail)
+            this->stream_.clear();
+
+        return (!eof && !fail);
+    }
+
+    void OutputBuffer::callListeners()
+    {
+        for (std::list<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+            (*it)->outputChanged();
+    }
+}
Index: code/branches/network/src/core/OutputBuffer.h
===================================================================
--- code/branches/network/src/core/OutputBuffer.h	(revision 1446)
+++ code/branches/network/src/core/OutputBuffer.h	(revision 1446)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _OutputBuffer_H__
+#define _OutputBuffer_H__
+
+#include <list>
+#include <sstream>
+#include <iostream>
+
+#include "CorePrereqs.h"
+
+namespace orxonox
+{
+    class _CoreExport OutputBufferListener
+    {
+        friend class OutputBuffer;
+
+        public:
+            virtual ~OutputBufferListener() {}
+
+        private:
+            virtual void outputChanged() = 0;
+    };
+
+    class _CoreExport OutputBuffer
+    {
+        public:
+            OutputBuffer() {}
+            ~OutputBuffer() {}
+
+            template <class T>
+            inline OutputBuffer& operator<<(T object)
+            {
+                this->stream_ << object;
+                this->callListeners();
+                return *this;
+            }
+
+            OutputBuffer& operator<<(std::ostream& (*manipulator)(std::ostream&));
+            OutputBuffer& operator<<(std::ios& (*manipulator)(std::ios&));
+            OutputBuffer& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
+
+            template <class T>
+            inline void add(T object)
+            {
+                this->stream_ << object;
+                this->callListeners();
+            }
+
+            template <class T>
+            inline void addLine(T object)
+            {
+                this->stream_ << object << std::endl;
+                this->callListeners();
+            }
+
+            inline void newline()
+            {
+                this->stream_ << std::endl;
+                this->callListeners();
+            }
+
+            inline void flush()
+            {
+                this->stream_.flush();
+            }
+
+            bool getLine(std::string* output);
+
+            void registerListener(OutputBufferListener* listener);
+            void unregisterListener(OutputBufferListener* listener);
+
+        private:
+            void callListeners();
+
+            std::stringstream stream_;
+            std::list<OutputBufferListener*> listeners_;
+    };
+}
+
+#endif /* _OutputBuffer_H__ */
Index: code/branches/network/src/core/OutputHandler.cc
===================================================================
--- code/branches/network/src/core/OutputHandler.cc	(revision 1445)
+++ code/branches/network/src/core/OutputHandler.cc	(revision 1446)
@@ -38,5 +38,9 @@
 namespace orxonox
 {
-    ConsoleCommandShortcutGeneric(log, createExecutor(createFunctor(&OutputHandler::log), "log", AccessLevel::None));
+    SetConsoleCommandShortcutGeneric(log,     createConsoleCommand(createFunctor(&OutputHandler::log),     "log"    ));
+    SetConsoleCommandShortcutGeneric(error,   createConsoleCommand(createFunctor(&OutputHandler::error),   "error"  ));
+    SetConsoleCommandShortcutGeneric(warning, createConsoleCommand(createFunctor(&OutputHandler::warning), "warning"));
+    SetConsoleCommandShortcutGeneric(info,    createConsoleCommand(createFunctor(&OutputHandler::info),    "info"   ));
+    SetConsoleCommandShortcutGeneric(debug,   createConsoleCommand(createFunctor(&OutputHandler::debug),   "debug"  ));
 
     /**
@@ -97,4 +101,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << sb;
+
         return *this;
     }
@@ -115,4 +122,7 @@
             this->logfile_.flush();
         }
+
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << manipulator;
 
         return *this;
@@ -135,4 +145,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << manipulator;
+
         return *this;
     }
@@ -154,4 +167,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << manipulator;
+
         return *this;
     }
Index: code/branches/network/src/core/OutputHandler.h
===================================================================
--- code/branches/network/src/core/OutputHandler.h	(revision 1445)
+++ code/branches/network/src/core/OutputHandler.h	(revision 1446)
@@ -44,4 +44,6 @@
 #include <string>
 
+#include "Shell.h"
+
 namespace orxonox
 {
@@ -63,4 +65,20 @@
             static inline std::string log(const std::string& text)
                 { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts an error on the outstream. @param text The text */
+            static inline std::string error(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts a warning on the outstream. @param text The text */
+            static inline std::string warning(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts an info on the outstream. @param text The text */
+            static inline std::string info(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts some debug output on the outstream. @param text The text */
+            static inline std::string debug(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
 
             /** @brief Returns a reference to the logfile. @return The logfile */
@@ -138,4 +156,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << output;
+
         return *this;
     }
@@ -159,4 +180,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
+            Shell::getInstance().getOutputBuffer() << output;
+
         return out;
     }
Index: code/branches/network/src/core/Script.cc
===================================================================
--- code/branches/network/src/core/Script.cc	(revision 1445)
+++ code/branches/network/src/core/Script.cc	(revision 1446)
@@ -67,5 +67,6 @@
   {
     output_ += str;
-    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
+//    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
+    COUT(5) << str;
   }
 
@@ -99,5 +100,5 @@
 
     if (luaTags) luaSource_ = replaceLuaTags(levelString);
-    COUT(4) << "ParsedSourceCode: " << luaSource_ << std::endl;
+    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
   }
 
@@ -127,5 +128,8 @@
     if (error == 0)
       error = lua_pcall(luaState_, 0, 0, 0);
-    if (error != 0) COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
+    if (error != 0)
+    {
+      COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
+    }
   }
 
Index: code/branches/network/src/core/Shell.cc
===================================================================
--- code/branches/network/src/core/Shell.cc	(revision 1446)
+++ code/branches/network/src/core/Shell.cc	(revision 1446)
@@ -0,0 +1,383 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Shell.h"
+#include "CommandExecutor.h"
+#include "CoreIncludes.h"
+#include "ConfigValueIncludes.h"
+#include "CoreSettings.h"
+#include "ConsoleCommand.h"
+#include "InputManager.h"
+
+#define SHELL_UPDATE_LISTENERS(function) \
+    for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it) \
+        (*it)->function()
+
+namespace orxonox
+{
+    SetConsoleCommand(Shell, clearShell, true);
+    SetConsoleCommand(Shell, history, true);
+
+    Shell::Shell()
+    {
+        RegisterRootObject(Shell);
+
+        this->scrollPosition_ = 0;
+        this->maxHistoryLength_ = 100;
+        this->historyPosition_ = 0;
+        this->historyOffset_ = 0;
+        this->finishedLastLine_ = true;
+        this->bAddOutputLevel_ = false;
+
+        this->clearLines();
+
+        this->inputBuffer_ = 0;
+        this->setInputBuffer(new InputBuffer());
+
+        this->outputBuffer_.registerListener(this);
+
+        this->setConfigValues();
+    }
+
+    Shell& Shell::createShell()
+    {
+        int level = CoreSettings::getSoftDebugLevel(OutputHandler::LD_Shell);
+        CoreSettings::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
+        static Shell instance;
+        CoreSettings::setSoftDebugLevel(OutputHandler::LD_Shell, level);
+        return instance;
+    }
+
+    Shell& Shell::getInstance()
+    {
+        static Shell& instance = createShell();
+        return instance;
+    }
+
+    void Shell::setConfigValues()
+    {
+        SetConfigValue(maxHistoryLength_, 100);
+        SetConfigValue(historyOffset_, 0);
+        SetConfigValueVector(commandHistory_, std::vector<std::string>());
+
+        if (this->historyOffset_ >= this->maxHistoryLength_)
+            this->historyOffset_ = 0;
+
+        while (this->commandHistory_.size() > this->maxHistoryLength_)
+        {
+            unsigned int index = this->commandHistory_.size() - 1;
+            this->commandHistory_.erase(this->commandHistory_.begin() + index);
+            ModifyConfigValue(commandHistory_, remove, index);
+        }
+    }
+
+    void Shell::setInputBuffer(InputBuffer* buffer)
+    {
+        if (this->inputBuffer_)
+        {
+            this->inputBuffer_->unregisterListener(this);
+            delete this->inputBuffer_;
+        }
+
+        this->inputBuffer_ = buffer;
+        this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
+        this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false);
+        this->inputBuffer_->registerListener(this, &Shell::hintandcomplete, '\t', true);
+        this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true);
+        this->inputBuffer_->registerListener(this, &Shell::deletechar, OIS::KC_DELETE);
+        this->inputBuffer_->registerListener(this, &Shell::exit, (char)27, true);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_right, OIS::KC_RIGHT);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_left, OIS::KC_LEFT);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_end, OIS::KC_END);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_home, OIS::KC_HOME);
+        this->inputBuffer_->registerListener(this, &Shell::history_up, OIS::KC_UP);
+        this->inputBuffer_->registerListener(this, &Shell::history_down, OIS::KC_DOWN);
+        this->inputBuffer_->registerListener(this, &Shell::scroll_up, OIS::KC_PGUP);
+        this->inputBuffer_->registerListener(this, &Shell::scroll_down, OIS::KC_PGDOWN);
+    }
+
+    void Shell::clearShell()
+    {
+        Shell::getInstance().clearLines();
+    }
+
+    void Shell::history()
+    {
+        Shell& instance = Shell::getInstance();
+
+        for (int i = instance.historyOffset_; i < (int)instance.commandHistory_.size(); ++i)
+            instance.addLine(instance.commandHistory_[i], -1);
+        for (int i =  0; i < (int)instance.historyOffset_; ++i)
+            instance.addLine(instance.commandHistory_[i], -1);
+    }
+
+    void Shell::registerListener(ShellListener* listener)
+    {
+        this->listeners_.insert(this->listeners_.end(), listener);
+    }
+
+    void Shell::unregisterListener(ShellListener* listener)
+    {
+        for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+        {
+            if ((*it) == listener)
+                this->listeners_.erase(it++);
+            else
+                ++it;
+        }
+    }
+
+    void Shell::setCursorPosition(unsigned int cursor)
+    {
+        this->inputBuffer_->setCursorPosition(cursor);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::setInput(const std::string& input)
+    {
+        this->inputBuffer_->set(input);
+        this->inputChanged();
+    }
+
+    void Shell::addLine(const std::string& line, int level)
+    {
+        int original_level = OutputHandler::getOutStream().getOutputLevel();
+        OutputHandler::getOutStream().setOutputLevel(level);
+
+        if (!this->finishedLastLine_)
+            this->outputBuffer_ << std::endl;
+
+        this->outputBuffer_ << line << std::endl;
+        OutputHandler::getOutStream().setOutputLevel(original_level);
+    }
+
+    void Shell::clearLines()
+    {
+        this->lines_.clear();
+        this->scrollIterator_ = this->lines_.begin();
+
+        this->scrollPosition_ = 0;
+        this->finishedLastLine_ = true;
+
+        SHELL_UPDATE_LISTENERS(linesChanged);
+    }
+
+    std::list<std::string>::const_iterator Shell::getNewestLineIterator() const
+    {
+        if (this->scrollPosition_)
+            return this->scrollIterator_;
+        else
+            return this->lines_.begin();
+    }
+
+    std::list<std::string>::const_iterator Shell::getEndIterator() const
+    {
+        return this->lines_.end();
+    }
+
+    void Shell::addToHistory(const std::string& command)
+    {
+        ModifyConfigValue(commandHistory_, set, this->historyOffset_, command);
+        this->historyPosition_ = 0;
+        ModifyConfigValue(historyOffset_, set, (this->historyOffset_ + 1) % this->maxHistoryLength_);
+    }
+
+    std::string Shell::getFromHistory() const
+    {
+        unsigned int index = mod(((int)this->historyOffset_) - ((int)this->historyPosition_), this->maxHistoryLength_);
+        if (index < this->commandHistory_.size() && this->historyPosition_ != 0)
+            return this->commandHistory_[index];
+        else
+            return "";
+    }
+
+    void Shell::outputChanged()
+    {
+        std::string output;
+        bool newline;
+        do
+        {
+            newline = this->outputBuffer_.getLine(&output);
+
+            if (!newline && output == "")
+                break;
+
+            if (this->finishedLastLine_)
+            {
+                if (this->bAddOutputLevel_)
+                    output.insert(0, 1, (char)OutputHandler::getOutStream().getOutputLevel());
+
+                this->lines_.insert(this->lines_.begin(), output);
+
+                if (this->scrollPosition_)
+                    this->scrollPosition_++;
+                else
+                    this->scrollIterator_ = this->lines_.begin();
+
+                this->finishedLastLine_ = newline;
+
+                if (!this->scrollPosition_)
+                {
+                    SHELL_UPDATE_LISTENERS(lineAdded);
+                }
+            }
+            else
+            {
+                (*this->lines_.begin()) += output;
+                this->finishedLastLine_ = newline;
+                SHELL_UPDATE_LISTENERS(onlyLastLineChanged);
+            }
+
+        } while (newline);
+    }
+
+    void Shell::inputChanged()
+    {
+        SHELL_UPDATE_LISTENERS(inputChanged);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::execute()
+    {
+        this->addToHistory(this->inputBuffer_->get());
+        this->addLine(this->inputBuffer_->get(), 0);
+
+        if (!CommandExecutor::execute(this->inputBuffer_->get()))
+            this->addLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1);
+
+        this->clear();
+    }
+
+    void Shell::hintandcomplete()
+    {
+        this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
+        this->addLine(CommandExecutor::hint(this->inputBuffer_->get()), -1);
+
+        this->inputChanged();
+    }
+
+    void Shell::backspace()
+    {
+        this->inputBuffer_->removeBehindCursor();
+        SHELL_UPDATE_LISTENERS(inputChanged);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::deletechar()
+    {
+        this->inputBuffer_->removeAtCursor();
+        SHELL_UPDATE_LISTENERS(inputChanged);
+    }
+
+    void Shell::clear()
+    {
+        this->inputBuffer_->clear();
+        this->historyPosition_ = 0;
+        SHELL_UPDATE_LISTENERS(inputChanged);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_right()
+    {
+        this->inputBuffer_->increaseCursor();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_left()
+    {
+        this->inputBuffer_->decreaseCursor();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_end()
+    {
+        this->inputBuffer_->setCursorToEnd();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_home()
+    {
+        this->inputBuffer_->setCursorToBegin();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::history_up()
+    {
+        if (this->historyPosition_ < this->commandHistory_.size())
+        {
+            this->historyPosition_++;
+            this->inputBuffer_->set(this->getFromHistory());
+        }
+    }
+
+    void Shell::history_down()
+    {
+        if (this->historyPosition_ > 0)
+        {
+            this->historyPosition_--;
+            this->inputBuffer_->set(this->getFromHistory());
+        }
+    }
+
+    void Shell::scroll_up()
+    {
+        if (this->scrollIterator_ != this->lines_.end())
+        {
+            ++this->scrollIterator_;
+            ++this->scrollPosition_;
+
+            SHELL_UPDATE_LISTENERS(linesChanged);
+        }
+    }
+
+    void Shell::scroll_down()
+    {
+        if (this->scrollIterator_ != this->lines_.begin())
+        {
+            --this->scrollIterator_;
+            --this->scrollPosition_;
+
+            SHELL_UPDATE_LISTENERS(linesChanged);
+        }
+    }
+
+    void Shell::exit()
+    {
+        if (this->inputBuffer_->getSize() > 0)
+        {
+            this->clear();
+            return;
+        }
+
+        this->clear();
+        this->scrollPosition_ = 0;
+        this->scrollIterator_ = this->lines_.begin();
+
+        SHELL_UPDATE_LISTENERS(exit);
+    }
+}
Index: code/branches/network/src/core/Shell.h
===================================================================
--- code/branches/network/src/core/Shell.h	(revision 1446)
+++ code/branches/network/src/core/Shell.h	(revision 1446)
@@ -0,0 +1,144 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Shell_H__
+#define _Shell_H__
+
+#include <list>
+#include <vector>
+
+#include "CorePrereqs.h"
+
+#include "OrxonoxClass.h"
+#include "InputBuffer.h"
+#include "OutputBuffer.h"
+
+namespace orxonox
+{
+    class _CoreExport ShellListener
+    {
+        friend class Shell;
+
+        public:
+            virtual ~ShellListener() {}
+
+        private:
+            virtual void linesChanged() {}
+            virtual void onlyLastLineChanged() {}
+            virtual void lineAdded() {}
+            virtual void inputChanged() {}
+            virtual void cursorChanged() {}
+            virtual void exit() {}
+    };
+
+    class _CoreExport Shell : virtual public OrxonoxClass, public InputBufferListener, public OutputBufferListener
+    {
+        public:
+            static Shell& getInstance();
+            static Shell& createShell();
+
+            static void clearShell();
+            static void history();
+
+            virtual void setConfigValues();
+
+            void registerListener(ShellListener* listener);
+            void unregisterListener(ShellListener* listener);
+
+            void setInputBuffer(InputBuffer* buffer);
+            inline InputBuffer& getInputBuffer()
+                { return (*this->inputBuffer_); }
+            inline OutputBuffer& getOutputBuffer()
+                { return this->outputBuffer_; }
+
+            void setCursorPosition(unsigned int cursor);
+            inline unsigned int getCursorPosition() const
+                { return this->inputBuffer_->getCursorPosition(); }
+
+            void setInput(const std::string& input);
+
+            inline void clearInput()
+                { this->setInput(""); }
+            inline std::string getInput() const
+                { return this->inputBuffer_->get(); }
+
+            std::list<std::string>::const_iterator getNewestLineIterator() const;
+            std::list<std::string>::const_iterator getEndIterator() const;
+
+            void addLine(const std::string& line, int level = 0);
+            void clearLines();
+
+            inline unsigned int getNumLines() const
+                { return this->lines_.size(); }
+            inline unsigned int getScrollPosition() const
+                { return this->scrollPosition_; }
+
+            inline void addOutputLevel(bool bAddOutputLevel)
+                { this->bAddOutputLevel_ = bAddOutputLevel; }
+
+        private:
+            Shell();
+            Shell(const Shell& other);
+            virtual ~Shell() {}
+
+            void addToHistory(const std::string& command);
+            std::string getFromHistory() const;
+
+            virtual void outputChanged();
+            void inputChanged();
+            void execute();
+            void hintandcomplete();
+            void backspace();
+            void deletechar();
+            void clear();
+            void cursor_right();
+            void cursor_left();
+            void cursor_end();
+            void cursor_home();
+            void history_up();
+            void history_down();
+            void scroll_up();
+            void scroll_down();
+            void exit();
+
+            std::list<ShellListener*> listeners_;
+            InputBuffer* inputBuffer_;
+            OutputBuffer outputBuffer_;
+            bool finishedLastLine_;
+            std::list<std::string> lines_;
+            std::list<std::string>::const_iterator scrollIterator_;
+            unsigned int scrollPosition_;
+            std::vector<std::string> commandHistory_;
+            unsigned int maxHistoryLength_;
+            unsigned int historyPosition_;
+            unsigned int historyOffset_;
+            bool bAddOutputLevel_;
+    };
+}
+
+#endif /* _Shell_H__ */
Index: code/branches/network/src/core/TclBind.cc
===================================================================
--- code/branches/network/src/core/TclBind.cc	(revision 1445)
+++ code/branches/network/src/core/TclBind.cc	(revision 1446)
@@ -33,9 +33,12 @@
 #include "CommandExecutor.h"
 #include "Debug.h"
+#include "TclThreadManager.h"
 #include "TclBind.h"
+#include "util/String.h"
 
 namespace orxonox
 {
-    ConsoleCommandShortcutGeneric(tcl, createExecutor(createFunctor(&TclBind::tcl), "tcl", AccessLevel::None));
+    SetConsoleCommandShortcutGeneric(tcl, createConsoleCommand(createFunctor(&TclBind::tcl), "tcl"));
+    SetConsoleCommandShortcutGeneric(bgerror, createConsoleCommand(createFunctor(&TclBind::bgerror), "bgerror"));
 
     TclBind::TclBind()
@@ -70,9 +73,20 @@
         {
             this->interpreter_ = new Tcl::interpreter(this->tclLibPath_);
-            this->interpreter_->def("puts", TclBind::puts, Tcl::variadic());
-            this->interpreter_->def("orxonox", TclBind::orxonox, Tcl::variadic());
-            this->interpreter_->def("execute", TclBind::execute, Tcl::variadic());
-            this->interpreter_->eval("proc unknown {args} { return [orxonox $args] }");
-            this->interpreter_->eval("rename exit tclexit; proc exit {} { orxonox exit }");
+            this->interpreter_->def("orxonox::query", TclBind::tcl_query, Tcl::variadic());
+            this->interpreter_->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+            this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
+
+            try
+            {
+                this->interpreter_->eval("proc query args { orxonox::query $args }");
+                this->interpreter_->eval("proc crossquery {id args} { orxonox::crossquery 0 $id $args }");
+                this->interpreter_->eval("set id 0");
+                this->interpreter_->eval("rename exit tcl::exit; proc exit {} { execute exit }");
+                this->interpreter_->eval("redef_puts");
+            }
+            catch (Tcl::tcl_error const &e)
+            {   COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl;   }
+            catch (std::exception const &e)
+            {   COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl;   }
         }
     }
@@ -89,19 +103,14 @@
     }
 
-    void TclBind::puts(Tcl::object const &args)
+    std::string TclBind::tcl_query(Tcl::object const &args)
     {
-        COUT(0) << args.get() << std::endl;
-    }
+        COUT(4) << "Tcl_query: " << args.get() << std::endl;
 
-    std::string TclBind::orxonox(Tcl::object const &args)
-    {
-std::cout << "Tcl_execute: args: " << args.get() << std::endl;
-        std::string command = args.get();
-
-        if (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
-            command = command.substr(1, command.size() - 2);
+        std::string command = stripEnclosingBraces(args.get());
 
         if (!CommandExecutor::execute(command, false))
+        {
             COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
+        }
 
         if (CommandExecutor::getLastEvaluation().hasReturnvalue())
@@ -111,6 +120,13 @@
     }
 
-    void TclBind::execute(Tcl::object const &args)
+    void TclBind::tcl_execute(Tcl::object const &args)
     {
+        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
+        std::string command = stripEnclosingBraces(args.get());
+
+        if (!CommandExecutor::execute(command, false))
+        {
+            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
+        }
     }
 
@@ -121,17 +137,20 @@
             std::string output = TclBind::getInstance().interpreter_->eval(tclcode);
             if (output != "")
+            {
                 COUT(0) << "tcl> " << output << std::endl;
+            }
             return output;
         }
         catch (Tcl::tcl_error const &e)
-        {
-            COUT(1) << "tcl> Error: " << e.what() << std::endl;
-        }
+        {   COUT(1) << "tcl> Error: " << e.what() << std::endl;   }
         catch (std::exception const &e)
-        {
-            COUT(1) << "Error while executing tcl: " << e.what() << std::endl;
-        }
+        {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
 
         return "";
+    }
+
+    void TclBind::bgerror(std::string error)
+    {
+        COUT(1) << "Tcl background error: " << stripEnclosingBraces(error) << std::endl;
     }
 
@@ -144,11 +163,7 @@
         }
         catch (Tcl::tcl_error const &e)
-        {
-            COUT(1) << "Error: " << e.what() << std::endl;
-        }
+        {   COUT(1) << "Tcl error: " << e.what() << std::endl;   }
         catch (std::exception const &e)
-        {
-            COUT(1) << "Error while executing tcl: " << e.what() << std::endl;
-        }
+        {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
 
         return false;
Index: code/branches/network/src/core/TclBind.h
===================================================================
--- code/branches/network/src/core/TclBind.h	(revision 1445)
+++ code/branches/network/src/core/TclBind.h	(revision 1446)
@@ -41,12 +41,16 @@
             static TclBind& getInstance();
 
+            static std::string tcl(const std::string& tclcode);
+            static void bgerror(std::string error);
+
             void setDataPath(const std::string& datapath);
+            std::string getTclLibPath() const { return this->tclLibPath_; }
             void createTclInterpreter();
             void createNewTclInterpreter();
+            Tcl::interpreter* getTclInterpreter() const { return this->interpreter_; }
 
-            static void puts(Tcl::object const &args);
-            static void execute(Tcl::object const &args);
-            static std::string orxonox(Tcl::object const &args);
-            static std::string tcl(const std::string& tclcode);
+            static std::string tcl_query(Tcl::object const &args);
+            static void tcl_execute(Tcl::object const &args);
+
             static bool eval(const std::string& tclcode);
 
Index: code/branches/network/src/core/TclThreadManager.cc
===================================================================
--- code/branches/network/src/core/TclThreadManager.cc	(revision 1446)
+++ code/branches/network/src/core/TclThreadManager.cc	(revision 1446)
@@ -0,0 +1,668 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <iostream>
+#include <string>
+
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+
+#include <OgreTimer.h>
+
+#include "CoreIncludes.h"
+#include "ConsoleCommand.h"
+#include "CommandExecutor.h"
+#include "Debug.h"
+#include "TclBind.h"
+#include "TclThreadManager.h"
+#include "util/Convert.h"
+
+#define TCLTHREADMANAGER_MAX_QUEUE_LENGTH 100
+#define TCLTHREADMANAGER_MAX_CPU_USAGE 0.50
+
+namespace orxonox
+{
+    SetConsoleCommandShortcutGeneric(tclexecute, createConsoleCommand(createFunctor(&TclThreadManager::execute), "tclexecute")).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommandShortcutGeneric(tclquery,   createConsoleCommand(createFunctor(&TclThreadManager::query),   "tclquery"  )).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, create,  false);
+    SetConsoleCommand(TclThreadManager, destroy, false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, execute, false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, query,   false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, status,  false);
+    SetConsoleCommand(TclThreadManager, dump,    false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, flush,   false).setArgumentCompleter(0, autocompletion::tclthreads());
+
+    TclThreadManager* instance_tclthreadmanager = &TclThreadManager::getInstance();
+
+    TclThreadManager::TclThreadManager()
+    {
+        RegisterRootObject(TclThreadManager);
+
+        this->threadCounter_ = 0;
+        this->orxonoxInterpreterBundle_.id_ = 0;
+        this->orxonoxInterpreterBundle_.interpreter_ = TclBind::getInstance().getTclInterpreter();
+#if (BOOST_VERSION >= 103500)
+        this->threadID_ = boost::this_thread::get_id();
+#else
+        //
+#endif
+    }
+
+    TclThreadManager& TclThreadManager::getInstance()
+    {
+        static TclThreadManager instance;
+        return instance;
+    }
+
+    unsigned int TclThreadManager::create()
+    {
+        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+        TclThreadManager::getInstance().threadCounter_++;
+        std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_);
+
+        TclInterpreterBundle* bundle = new TclInterpreterBundle;
+        bundle->id_ = TclThreadManager::getInstance().threadCounter_;
+        bundle->interpreter_ = TclThreadManager::getInstance().createNewTclInterpreter(name);
+        bundle->interpreterName_ = name;
+        bundle->running_ = true;
+        bundle->finished_ = true;
+
+        TclThreadManager::getInstance().interpreterBundles_[TclThreadManager::getInstance().threadCounter_] = bundle;
+        COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().threadCounter_ << std::endl;
+        return TclThreadManager::getInstance().threadCounter_;
+    }
+
+    unsigned int TclThreadManager::createID(unsigned int threadID)
+    {
+        unsigned int temp = TclThreadManager::getInstance().threadCounter_;
+        TclThreadManager::getInstance().threadCounter_ = threadID - 1;
+        TclThreadManager::create();
+        TclThreadManager::getInstance().threadCounter_ = temp;
+        return threadID;
+    }
+
+    void TclThreadManager::destroy(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            {
+                boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
+                bundle->running_ = false;
+            }
+            while (true)
+            {
+                {
+                    boost::mutex::scoped_lock finished_lock(bundle->finishedMutex_);
+                    if (bundle->finished_)
+                    {
+                        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+#if (BOOST_VERSION >= 103500)
+                        boost::mutex::scoped_try_lock interpreter_lock(bundle->interpreterMutex_);
+#else
+                        boost::try_mutex::scoped_try_lock interpreter_lock(bundle->interpreterMutex_);
+#endif
+                        try
+                        {
+                            while (!interpreter_lock.try_lock())
+                            {
+                                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
+#if (BOOST_VERSION >= 103500)
+                                boost::this_thread::yield();
+#else
+                                boost::thread::yield();
+#endif
+                            }
+                        } catch (...) {}
+                        delete bundle->interpreter_;
+                        delete bundle;
+                        TclThreadManager::getInstance().interpreterBundles_.erase(threadID);
+                        break;
+                    }
+                }
+
+                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
+#if (BOOST_VERSION >= 103500)
+                boost::this_thread::yield();
+#else
+                boost::thread::yield();
+#endif
+            }
+
+            COUT(0) << "Destroyed Tcl-interpreter with ID " << threadID << std::endl;
+        }
+    }
+
+    void TclThreadManager::execute(unsigned int threadID, const std::string& _command)
+    {
+        std::string command = stripEnclosingBraces(_command);
+
+        if (threadID == 0)
+            TclThreadManager::getInstance().pushCommandToQueue(command);
+        else
+            TclThreadManager::getInstance().pushCommandToQueue(threadID, command);
+    }
+
+    std::string TclThreadManager::query(unsigned int threadID, const std::string& command)
+    {
+        return TclThreadManager::getInstance().evalQuery(TclThreadManager::getInstance().orxonoxInterpreterBundle_.id_, threadID, command);
+    }
+
+    void TclThreadManager::status()
+    {
+        COUT(0) << "Thread ID" << '\t' << "Queue size" << '\t' << "State" << std::endl;
+
+        std::string output = "Orxonox";
+        output += "\t\t";
+        {
+            boost::mutex::scoped_lock queue_lock(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queueMutex_);
+            output += getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queue_.size());
+        }
+        output += "\t\t";
+        output += "busy";
+        COUT(0) << output << std::endl;
+
+        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = TclThreadManager::getInstance().interpreterBundles_.begin(); it != TclThreadManager::getInstance().interpreterBundles_.end(); ++it)
+        {
+            std::string output = getConvertedValue<unsigned int, std::string>((*it).first);
+            output += "\t\t";
+            {
+                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
+                output += getConvertedValue<unsigned int, std::string>((*it).second->queue_.size());
+            }
+            output += "\t\t";
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::mutex::scoped_try_lock interpreter_lock((*it).second->interpreterMutex_);
+#else
+                boost::try_mutex::scoped_try_lock interpreter_lock((*it).second->interpreterMutex_);
+#endif
+                if (interpreter_lock.try_lock())
+                    output += "ready";
+                else
+                    output += "busy";
+            }
+            COUT(0) << output << std::endl;
+        }
+    }
+
+    void TclThreadManager::dump(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = 0;
+        if (threadID == 0)
+        {
+            bundle = &TclThreadManager::getInstance().orxonoxInterpreterBundle_;
+            COUT(0) << "Queue dump of Orxonox:" << std::endl;
+        }
+        else
+        {
+            if ((bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
+            {
+                COUT(0) << "Queue dump of Tcl-thread " << threadID << ":" << std::endl;
+            }
+            else
+                return;
+        }
+
+        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+        unsigned int index = 0;
+        for (std::list<std::string>::const_iterator it = bundle->queue_.begin(); it != bundle->queue_.end(); ++it)
+        {
+            index++;
+            COUT(0) << index << ": " << (*it) << std::endl;
+        }
+    }
+
+    void TclThreadManager::flush(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = 0;
+        if (threadID == 0)
+            bundle = &TclThreadManager::getInstance().orxonoxInterpreterBundle_;
+        else
+            if (!(bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
+                return;
+
+        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+        bundle->queue_.clear();
+        if (threadID == 0)
+        {
+            COUT(0) << "Flushed queue of Orxonox Tcl-interpreter." << std::endl;
+        }
+        else
+        {
+            COUT(0) << "Flushed queue of Tcl-interpreter " << threadID << "." << std::endl;
+        }
+    }
+
+    void TclThreadManager::tcl_execute(Tcl::object const &args)
+    {
+        TclThreadManager::getInstance().pushCommandToQueue(stripEnclosingBraces(args.get()));
+    }
+
+    std::string TclThreadManager::tcl_query(int querierID, Tcl::object const &args)
+    {
+        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, stripEnclosingBraces(args.get()));
+    }
+
+    std::string TclThreadManager::tcl_crossquery(int querierID, int threadID, Tcl::object const &args)
+    {
+        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, (unsigned int)threadID, stripEnclosingBraces(args.get()));
+    }
+
+    bool TclThreadManager::tcl_running(int threadID)
+    {
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle((unsigned int)threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
+            return bundle->running_;
+        }
+        return false;
+    }
+
+    Tcl::interpreter* TclThreadManager::createNewTclInterpreter(const std::string& threadID)
+    {
+        Tcl::interpreter* i = 0;
+        i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath());
+
+        try
+        {
+            i->def("orxonox::query", TclThreadManager::tcl_query, Tcl::variadic());
+            i->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+            i->def("orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic());
+            i->def("orxonox::running", TclThreadManager::tcl_running);
+
+            i->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());
+            i->eval("proc query args { orxonox::query " + threadID + " $args }");
+            i->eval("proc crossquery {id args} { orxonox::crossquery " + threadID + " $id $args }");
+            i->eval("set id " + threadID);
+
+            i->eval("rename exit tcl::exit");
+            i->eval("proc exit {} { orxonox TclThreadManager destroy " + threadID + " }");
+
+            i->eval("redef_puts");
+
+//            i->eval("rename while tcl::while");
+//            i->eval("proc while {test command} { tcl::while {[uplevel 1 expr $test]} {uplevel 1 $command} }"); // (\"$test\" && [orxonox::running " + threadID + "]])
+//            i->eval("rename for tcl::for");
+//            i->eval("proc for {start test next command} { uplevel tcl::for \"$start\" \"$test\" \"$next\" \"$command\" }");
+        }
+        catch (Tcl::tcl_error const &e)
+        {   COUT(1) << "Tcl error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
+        catch (std::exception const &e)
+        {   COUT(1) << "Error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
+
+        return i;
+    }
+
+    TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int threadID)
+    {
+        boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
+        std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.find(threadID);
+        if (it != this->interpreterBundles_.end())
+        {
+            return (*it).second;
+        }
+        else
+        {
+            this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing.");
+            return 0;
+        }
+    }
+
+    std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
+    {
+        std::string output = "";
+        for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                output += " ";
+
+            output += getConvertedValue<unsigned int, std::string>(*it);
+        }
+        return output;
+    }
+
+    void TclThreadManager::error(const std::string& error)
+    {
+#if (BOOST_VERSION >= 103500)
+        if (boost::this_thread::get_id() != this->threadID_)
+#else
+        if (boost::thread() != this->threadID_)
+#endif
+        {
+            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::this_thread::yield();
+#else
+                boost::thread::yield();
+#endif
+                return;
+            }
+        }
+
+        this->forceCommandToFrontOfQueue("error " + error);
+    }
+
+    void TclThreadManager::debug(const std::string& error)
+    {
+#if (BOOST_VERSION >= 103500)
+        if (boost::this_thread::get_id() != this->threadID_)
+#else
+        if (boost::thread() != this->threadID_)
+#endif
+        {
+            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::this_thread::yield();
+#else
+                boost::thread::yield();
+#endif
+                return;
+            }
+        }
+
+        this->forceCommandToFrontOfQueue("debug " + error);
+    }
+
+    void TclThreadManager::pushCommandToQueue(const std::string& command)
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        while (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            this->fullQueueCondition_.wait(queue_lock);
+
+        this->orxonoxInterpreterBundle_.queue_.push_back(command);
+    }
+
+    void TclThreadManager::forceCommandToFrontOfQueue(const std::string& command)
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        this->orxonoxInterpreterBundle_.queue_.push_front(command);
+    }
+
+    std::string TclThreadManager::popCommandFromQueue()
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        std::string temp = this->orxonoxInterpreterBundle_.queue_.front();
+        this->orxonoxInterpreterBundle_.queue_.pop_front();
+        this->fullQueueCondition_.notify_one();
+        return temp;
+    }
+
+    bool TclThreadManager::queueIsEmpty()
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        return this->orxonoxInterpreterBundle_.queue_.empty();
+    }
+
+    void TclThreadManager::pushCommandToQueue(unsigned int threadID, const std::string& command)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+            if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            {
+                this->error("Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command.");
+                return;
+            }
+
+            bundle->queue_.push_back(command);
+        }
+    }
+
+    std::string TclThreadManager::popCommandFromQueue(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+            std::string temp = bundle->queue_.front();
+            bundle->queue_.pop_front();
+            return temp;
+        }
+        return "";
+    }
+
+    bool TclThreadManager::queueIsEmpty(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+            return bundle->queue_.empty();
+        }
+        return true;
+    }
+
+    bool TclThreadManager::updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target)
+    {
+        if (querier == target)
+            return false;
+
+        boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
+
+        {
+            boost::mutex::scoped_lock queriers_lock(querier->queriersMutex_);
+            target->queriers_.insert(target->queriers_.end(), querier->queriers_.begin(), querier->queriers_.end());
+        }
+
+        target->queriers_.insert(target->queriers_.end(), querier->id_);
+
+        if (std::find(target->queriers_.begin(), target->queriers_.end(), target->id_) != target->queriers_.end())
+        {
+            this->error("Error: Circular query (" + this->dumpList(target->queriers_) + " -> " + getConvertedValue<unsigned int, std::string>(target->id_) + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target->id_) + " from other interpreter with ID " + getConvertedValue<unsigned int, std::string>(querier->id_) + ".");
+            return false;
+        }
+
+        return true;
+    }
+
+    std::string TclThreadManager::evalQuery(unsigned int querierID, const std::string& command)
+    {
+        TclInterpreterBundle* querier = this->getInterpreterBundle(querierID);
+        std::string output = "";
+        if (querier)
+        {
+            if (this->updateQueriersList(querier, &this->orxonoxInterpreterBundle_))
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#else
+                boost::try_mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#endif
+                this->orxonoxEvalCondition_.wait(interpreter_lock);
+
+                if (!CommandExecutor::execute(command, false))
+                    this->error("Error: Can't execute command \"" + command + "\"!");
+
+                if (CommandExecutor::getLastEvaluation().hasReturnvalue())
+                    output = CommandExecutor::getLastEvaluation().getReturnvalue().toString();
+            }
+
+            boost::mutex::scoped_lock queriers_lock(this->orxonoxInterpreterBundle_.queriersMutex_);
+            this->orxonoxInterpreterBundle_.queriers_.clear();
+        }
+        return output;
+    }
+
+    std::string TclThreadManager::evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command)
+    {
+        TclInterpreterBundle* target = 0;
+        if (threadID)
+            target = this->getInterpreterBundle(threadID);
+        else
+            target = &this->orxonoxInterpreterBundle_;
+
+        std::string output = "";
+        if (target)
+        {
+            TclInterpreterBundle* querier = 0;
+            if (querierID)
+                querier = this->getInterpreterBundle(querierID);
+            else
+                querier = &this->orxonoxInterpreterBundle_;
+
+            if (querier)
+            {
+                if (this->updateQueriersList(querier, target))
+                {
+#if (BOOST_VERSION >= 103500)
+                    boost::mutex::scoped_try_lock interpreter_lock(target->interpreterMutex_);
+#else
+                    boost::try_mutex::scoped_try_lock interpreter_lock(target->interpreterMutex_);
+#endif
+                    bool successfullyLocked = false;
+                    try
+                    {
+                        if (querierID == 0 || std::find(querier->queriers_.begin(), querier->queriers_.end(), (unsigned int)0) != querier->queriers_.end())
+                            successfullyLocked = interpreter_lock.try_lock();
+                        else
+                        {
+                            while (!interpreter_lock.try_lock())
+                            {
+#if (BOOST_VERSION >= 103500)
+                                boost::this_thread::yield();
+#else
+                                boost::thread::yield();
+#endif
+                            }
+
+                            successfullyLocked = true;
+                        }
+                    } catch (...) {}
+
+                    if (successfullyLocked)
+                    {
+                        this->debug("TclThread_query: " + command);
+                        try
+                        {   output = (std::string)target->interpreter_->eval(command);   }
+                        catch (Tcl::tcl_error const &e)
+                        {   this->error("Tcl error: " + (std::string)e.what());   }
+                        catch (std::exception const &e)
+                        {   this->error("Error while executing Tcl: " + (std::string)e.what());   }
+                    }
+                    else
+                    {
+                        this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now.");
+                    }
+                }
+
+                boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
+                target->queriers_.clear();
+            }
+        }
+        return output;
+    }
+
+    void TclThreadManager::tick(float dt)
+    {
+        {
+            this->orxonoxEvalCondition_.notify_one();
+#if (BOOST_VERSION >= 103500)
+            boost::this_thread::yield();
+#else
+            boost::thread::yield();
+#endif
+        }
+
+        {
+            boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
+            for (std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
+            {
+                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
+                if (!(*it).second->queue_.empty())
+                {
+                    std::string command = (*it).second->queue_.front();
+                    (*it).second->queue_.pop_front();
+                    {
+                        boost::mutex::scoped_lock finished_lock((*it).second->finishedMutex_);
+                        (*it).second->finished_ = false;
+                    }
+                    boost::thread(boost::bind(&tclThread, (*it).second, command));
+                }
+            }
+        }
+
+        {
+#if (BOOST_VERSION >= 103500)
+            boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#else
+            boost::try_mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#endif
+            unsigned long maxtime = (unsigned long)(dt * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
+            Ogre::Timer timer;
+            while (!this->queueIsEmpty())
+            {
+                CommandExecutor::execute(this->popCommandFromQueue(), false);
+                if (timer.getMicroseconds() > maxtime)
+                    break;
+            }
+        }
+    }
+
+    std::list<unsigned int> TclThreadManager::getThreadList() const
+    {
+        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+        std::list<unsigned int> threads;
+        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
+            threads.push_back((*it).first);
+        return threads;
+    }
+
+    void tclThread(TclInterpreterBundle* interpreterBundle, std::string command)
+    {
+        TclThreadManager::getInstance().debug("TclThread_execute: " + command);
+#if (BOOST_VERSION >= 103500)
+        boost::mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
+#else
+        boost::try_mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
+#endif
+        try
+        {
+            interpreterBundle->interpreter_->eval(command);
+        }
+        catch (Tcl::tcl_error const &e)
+        {
+            TclThreadManager::getInstance().error("Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what());
+        }
+        catch (std::exception const &e)
+        {
+            TclThreadManager::getInstance().error("Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what());
+        }
+
+        boost::mutex::scoped_lock finished_lock(interpreterBundle->finishedMutex_);
+        interpreterBundle->finished_ = true;
+        interpreterBundle->finishedCondition_.notify_all();
+    }
+}
Index: code/branches/network/src/core/TclThreadManager.h
===================================================================
--- code/branches/network/src/core/TclThreadManager.h	(revision 1446)
+++ code/branches/network/src/core/TclThreadManager.h	(revision 1446)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TclThreadManager_H__
+#define _TclThreadManager_H__
+
+#include <queue>
+#include <map>
+#include <list>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/thread.hpp>
+
+#include "CorePrereqs.h"
+#include "Tickable.h"
+#include "cpptcl/CppTcl.h"
+
+namespace orxonox
+{
+    class boost::thread;
+
+    struct _CoreExport TclInterpreterBundle
+    {
+        unsigned int id_;
+
+        std::list<std::string> queue_;
+        boost::mutex queueMutex_;
+
+        Tcl::interpreter* interpreter_;
+        std::string interpreterName_;
+        boost::try_mutex interpreterMutex_;
+
+        std::list<unsigned int> queriers_;
+        boost::mutex queriersMutex_;
+
+        bool running_;
+        boost::mutex runningMutex_;
+
+        bool finished_;
+        boost::mutex finishedMutex_;
+        boost::condition finishedCondition_;
+    };
+
+    class _CoreExport TclThreadManager : public Tickable
+    {
+        public:
+            static TclThreadManager& getInstance();
+
+            static unsigned int create();
+            static unsigned int createID(unsigned int threadID);
+            static void destroy(unsigned int threadID);
+            static void execute(unsigned int threadID, const std::string& command);
+            static std::string query(unsigned int threadID, const std::string& command);
+            static void status();
+            static void dump(unsigned int threadID);
+            static void flush(unsigned int threadID);
+
+            static void tcl_execute(Tcl::object const &args);
+            static std::string tcl_query(int querierID, Tcl::object const &args);
+            static std::string tcl_crossquery(int querierID, int threadID, Tcl::object const &args);
+            static bool tcl_running(int threadID);
+
+            Tcl::interpreter* createNewTclInterpreter(const std::string& threadID);
+            TclInterpreterBundle* getInterpreterBundle(unsigned int threadID);
+            std::string dumpList(const std::list<unsigned int>& list);
+            void error(const std::string& error);
+            void debug(const std::string& error);
+
+            void pushCommandToQueue(const std::string& command);
+            void forceCommandToFrontOfQueue(const std::string& command);
+            std::string popCommandFromQueue();
+            bool queueIsEmpty();
+
+            void pushCommandToQueue(unsigned int threadID, const std::string& command);
+            std::string popCommandFromQueue(unsigned int threadID);
+            bool queueIsEmpty(unsigned int threadID);
+
+            bool updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target);
+
+            std::string evalQuery(unsigned int querierID, const std::string& command);
+            std::string evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command);
+
+            virtual void tick(float dt);
+
+            std::list<unsigned int> getThreadList() const;
+
+        private:
+            TclThreadManager();
+            TclThreadManager(const TclThreadManager& other);
+            ~TclThreadManager() {}
+
+            unsigned int threadCounter_;
+            TclInterpreterBundle orxonoxInterpreterBundle_;
+            std::map<unsigned int, TclInterpreterBundle*> interpreterBundles_;
+            boost::mutex bundlesMutex_;
+            boost::condition fullQueueCondition_;
+            boost::condition orxonoxEvalCondition_;
+#if (BOOST_VERSION >= 103500)
+            boost::thread::id threadID_;
+#else
+            boost::thread threadID_;
+#endif
+    };
+
+    _CoreExport void tclThread(TclInterpreterBundle* interpreterBundle, std::string command);
+}
+
+#endif /* _TclThreadManager_H__ */
Index: code/branches/network/src/core/XMLPort.h
===================================================================
--- code/branches/network/src/core/XMLPort.h	(revision 1445)
+++ code/branches/network/src/core/XMLPort.h	(revision 1446)
@@ -78,17 +78,4 @@
 namespace orxonox
 {
-
-#ifndef _XMLPort_Mode__
-#define _XMLPort_Mode__
-    namespace XMLPort
-    {
-        enum Mode
-        {
-            LoadObject,
-            SaveObject
-        };
-    }
-#endif
-
     // ###############################
     // ###  XMLPortParamContainer  ###
Index: code/branches/network/src/cpptcl/CppTcl.cc
===================================================================
--- code/branches/network/src/cpptcl/CppTcl.cc	(revision 1445)
+++ code/branches/network/src/cpptcl/CppTcl.cc	(revision 1446)
Index: code/branches/network/src/network/CMakeLists.txt
===================================================================
--- code/branches/network/src/network/CMakeLists.txt	(revision 1445)
+++ code/branches/network/src/network/CMakeLists.txt	(revision 1446)
Index: code/branches/network/src/network/GameStateClient.cc
===================================================================
--- code/branches/network/src/network/GameStateClient.cc	(revision 1445)
+++ code/branches/network/src/network/GameStateClient.cc	(revision 1446)
@@ -42,5 +42,5 @@
     int id;
   };
-  
+
   GameStateClient::GameStateClient() {
     COUT(5) << "this: " << this << std::endl;
@@ -96,5 +96,5 @@
     return false;
   }
-  
+
   GameStateCompressed *GameStateClient::popPartialGameState(){
     GameState *gs = getPartialSnapshot();
@@ -104,5 +104,5 @@
     return cgs;
   }
-  
+
   void GameStateClient::addGameState(GameStateCompressed *gs){
     if(tempGameState_!=NULL){
@@ -128,5 +128,5 @@
       return GAMESTATEID_INITIAL;
   }
-  
+
 
   /**
@@ -193,5 +193,7 @@
           }
           if( !no->create() )
+          {
             COUT(1) << "We couldn't manifest (create() ) the object: " << sync.objectID << std::endl;
+          }
           it=orxonox::ObjectList<Synchronisable>::end();
         }
@@ -199,6 +201,8 @@
         // we have our object
         if(! it->updateData(sync))
+        {
           COUT(1) << "We couldn't update objectID: " \
           << sync.objectID << "; classID: " << sync.classID << std::endl;
+        }
       }
       ++it;
@@ -272,6 +276,6 @@
     return retval;
   }
-  
-  
+
+
   GameState *GameStateClient::undiff(GameState *old, GameState *diff) {
     if(!old || !diff)
@@ -334,5 +338,5 @@
     switch ( retval ) {
       case Z_OK: COUT(5) << "G.St.Cl: compress: successfully compressed" << std::endl; break;
-      case Z_MEM_ERROR: COUT(1) << "G.St.Cl: compress: not enough memory available in gamestate.compress" << std::endl; 
+      case Z_MEM_ERROR: COUT(1) << "G.St.Cl: compress: not enough memory available in gamestate.compress" << std::endl;
       return NULL;
       case Z_BUF_ERROR: COUT(2) << "G.St.Cl: compress: not enough memory available in the buffer in gamestate.compress" << std::endl;
@@ -352,6 +356,6 @@
     return compressedGamestate;
   }
-  
-  
+
+
   GameState *GameStateClient::decompress(GameStateCompressed *a) {
     //COUT(4) << "GameStateClient: uncompressing gamestate. id: " << a->id << ", baseid: " << a->base_id << ", normsize: " << a->normsize << ", compsize: " << a->compsize << std::endl;
@@ -409,5 +413,5 @@
     return t;
   }
-  
+
   void GameStateClient::cleanup(){
     std::map<int, GameState*>::iterator temp, it = gameStateMap.begin();
@@ -431,7 +435,7 @@
     }
     COUT(4) << std::endl;
-    
-  }
-  
+
+  }
+
   bool GameStateClient::saveShipCache(){
     if(myShip_==NULL)
@@ -448,5 +452,5 @@
       return false;
   }
-  
+
   bool GameStateClient::loadShipCache(){
     if(myShip_){
@@ -459,16 +463,16 @@
       return false;
   }
-  
+
     //##### ADDED FOR TESTING PURPOSE #####
   GameState* GameStateClient::testDecompress( GameStateCompressed* gc ) {
     return decompress( gc );
   }
-  
+
   GameState* GameStateClient::testUndiff( GameState* g_old, GameState* g_diffed ) {
     return undiff( g_old, g_diffed );
   }
   //##### ADDED FOR TESTING PURPOSE #####
-  
-  
+
+
 }
 
Index: code/branches/network/src/network/PacketDecoder.cc
===================================================================
--- code/branches/network/src/network/PacketDecoder.cc	(revision 1445)
+++ code/branches/network/src/network/PacketDecoder.cc	(revision 1446)
@@ -84,5 +84,5 @@
     return false;
   }
-  
+
   bool PacketDecoder::testAndRemoveCRC(ENetPacket *packet){
     uint32_t submittetcrc;
@@ -102,5 +102,5 @@
     return false;
   }
-  
+
   // ATTENTION: TODO watch, that arguments we pass over to the processFunction gets deleted in THE PROCESSXXX function
 
@@ -118,5 +118,5 @@
     enet_packet_destroy( packet );
   }
-  
+
   bool PacketDecoder::command( ENetPacket* packet, int clientId ){
     int length = *(int*)((unsigned char *)packet->data+sizeof(int));
@@ -175,5 +175,7 @@
     //since data is not allocated, because it's just a pointer, allocate it with size of gamestatedatastream
     if(currentState->compsize==0)
+    {
       COUT(2) << "PacketDecoder: compsize is 0" << std::endl;
+    }
 //     currentState->data = (unsigned char*)(malloc( currentState->compsize ));
     if(currentState->compsize==0)
@@ -181,5 +183,7 @@
     currentState->data = new unsigned char[currentState->compsize];
     if(currentState->data==NULL)
+    {
       COUT(2) << "PacketDecoder: Gamestatepacket-decoder: memory leak" << std::endl;
+    }
     //copy the GameStateCompressed data
     memcpy( (void*)(currentState->data), (const void*)(packet->data+5*sizeof( int ) + 2*sizeof(bool)), currentState->compsize );
@@ -206,6 +210,6 @@
     processClassid(cid);
   }
-  
-  
+
+
   bool PacketDecoder::decodeWelcome( ENetPacket* packet, int clientID ){
     welcome *w = new welcome;
@@ -217,5 +221,5 @@
     return processWelcome(w);
   }
-  
+
   bool PacketDecoder::decodeConnectRequest( ENetPacket *packet, int clientID ){
     connectRequest *con = new connectRequest;
@@ -256,10 +260,10 @@
     return;
   }
-  
+
   bool PacketDecoder::processWelcome( welcome *w ){
     delete w;
     return true;
   }
-  
+
   bool PacketDecoder::processConnectRequest( connectRequest *con, int clientID ){
     COUT(3) << "packetdecoder: processing connectRequest" << std::endl;
@@ -280,5 +284,7 @@
   {
     if(clientId!=CLIENTID_CLIENT)
+    {
       COUT(5) << "client: " << clientId << std::endl;
+    }
     COUT(5) << "data id: " << data->id << std::endl;
     COUT(5) << "data:    " << data->message << std::endl;
Index: code/branches/network/src/network/dummyclient3.cc
===================================================================
--- code/branches/network/src/network/dummyclient3.cc	(revision 1445)
+++ code/branches/network/src/network/dummyclient3.cc	(revision 1446)
@@ -51,6 +51,11 @@
   Client client( str, PORT );
   if ( client.establishConnection() )
+  {
     COUT(3) << "connection established" << std::endl;
-  else COUT(0) << "problems establishing connection" << std::endl;
+  }
+  else
+  {
+    COUT(0) << "problems establishing connection" << std::endl;
+  }
   char message[10000];
   char signs[] = "abcdefghijklmnopqrstuvwxy";
Index: code/branches/network/src/orxonox/GraphicsEngine.cc
===================================================================
--- code/branches/network/src/orxonox/GraphicsEngine.cc	(revision 1445)
+++ code/branches/network/src/orxonox/GraphicsEngine.cc	(revision 1446)
@@ -45,5 +45,5 @@
 #include "core/Debug.h"
 #include "core/CommandExecutor.h"
-
+#include "console/InGameConsole.h"
 
 namespace orxonox {
@@ -345,4 +345,5 @@
     int h = rw->getHeight();
     InputManager::setWindowExtents(w, h);
+    InGameConsole::getInstance().resize();
   }
 
Index: code/branches/network/src/orxonox/Orxonox.cc
===================================================================
--- code/branches/network/src/orxonox/Orxonox.cc	(revision 1445)
+++ code/branches/network/src/orxonox/Orxonox.cc	(revision 1446)
@@ -51,5 +51,4 @@
 //#include "util/Sleep.h"
 #include "util/ArgReader.h"
-#include "util/ExprParser.h"
 
 // core
@@ -57,8 +56,6 @@
 #include "core/ConsoleCommand.h"
 #include "core/Debug.h"
-#include "core/Factory.h"
 #include "core/Loader.h"
 #include "core/Tickable.h"
-#include "core/InputBuffer.h"
 #include "core/InputManager.h"
 #include "core/TclBind.h"
@@ -72,7 +69,5 @@
 
 // objects and tools
-#include "tools/Timer.h"
 #include "hud/HUD.h"
-#include "console/InGameConsole.h"
 
 // FIXME: is this really file scope?
@@ -83,71 +78,7 @@
 namespace orxonox
 {
-  ConsoleCommandShortcut(Orxonox, exit, AccessLevel::None).setKeybindMode(KeybindMode::OnPress);
-  ConsoleCommandShortcut(Orxonox, slomo, AccessLevel::Offline).setDefaultValue(0, 1.0)
-    .setAxisParamIndex(0).setIsAxisRelative(false);
-  ConsoleCommandShortcut(Orxonox, setTimeFactor, AccessLevel::Offline).setDefaultValue(0, 1.0);
-  ConsoleCommandShortcut(Orxonox, activateConsole, AccessLevel::None);
-  class Testconsole : public InputBufferListener
-  {
-    public:
-      Testconsole(InputBuffer* ib) : ib_(ib) {}
-      void listen() const
-      {
-        std::cout << "> " << this->ib_->get() << std::endl;
-      }
-      void execute() const
-      {
-        std::cout << ">> " << this->ib_->get() << std::endl;
-        if (!CommandExecutor::execute(this->ib_->get()))
-          std::cout << "Error" << std::endl;
-        this->ib_->clear();
-      }
-      void hintandcomplete() const
-      {
-        std::cout << CommandExecutor::hint(this->ib_->get()) << std::endl;
-        this->ib_->set(CommandExecutor::complete(this->ib_->get()));
-      }
-      void clear() const
-      {
-        this->ib_->clear();
-      }
-      void removeLast() const
-      {
-        this->ib_->removeLast();
-      }
-      void exit() const
-      {
-        InputManager::setInputState(InputManager::IS_NORMAL);
-      }
-
-    private:
-      InputBuffer* ib_;
-  };
-
-  class Calculator
-  {
-  public:
-    static float calculate(const std::string& calculation)
-    {
-      ExprParser expr(calculation);
-      if (expr.getSuccess())
-      {
-        if (expr.getResult() == 42.0)
-          std::cout << "Greetings from the restaurant at the end of the universe." << std::endl;
-        // FIXME: insert modifier to display in full precision
-        std::cout << "Result is: " << expr.getResult() << std::endl;
-        if (expr.getRemains() != "")
-          std::cout << "Warning: Expression could not be parsed to the end! Remains: '"
-              << expr.getRemains() << "'" << std::endl;
-        return expr.getResult();
-      }
-      else
-      {
-        std::cout << "Cannot calculate expression: Parse error" << std::endl;
-        return 0;
-      }
-    }
-  };
-  ConsoleCommandShortcut(Calculator, calculate, AccessLevel::None);
+  SetConsoleCommandShortcut(Orxonox, exit).setKeybindMode(KeybindMode::OnPress);
+  SetConsoleCommandShortcut(Orxonox, slomo).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0).setAxisParamIndex(0).setIsAxisRelative(false);
+  SetConsoleCommandShortcut(Orxonox, setTimeFactor).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0);
 
   /**
@@ -165,5 +96,4 @@
     // turn on frame smoothing by setting a value different from 0
     frameSmoothingTime_(0.0f),
-    orxonoxConsole_(0),
     orxonoxHUD_(0),
     bAbort_(false),
@@ -351,24 +281,4 @@
     COUT(3) << "Orxonox: Loading HUD..." << std::endl;
     orxonoxHUD_ = &HUD::getSingleton();
-
-    COUT(3) << "Orxonox: Loading Console..." << std::endl;
-    InputBuffer* ib = dynamic_cast<InputBuffer*>(InputManager::getKeyHandler("buffer"));
-    /*
-    Testconsole* console = new Testconsole(ib);
-    ib->registerListener(console, &Testconsole::listen, true);
-    ib->registerListener(console, &Testconsole::execute, '\r', false);
-    ib->registerListener(console, &Testconsole::hintandcomplete, '\t', true);
-    ib->registerListener(console, &Testconsole::clear, '�', true);
-    ib->registerListener(console, &Testconsole::removeLast, '\b', true);
-    ib->registerListener(console, &Testconsole::exit, (char)0x1B, true);
-    */
-    orxonoxConsole_ = new InGameConsole(ib);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::listen, true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::execute, '\r', false);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::hintandcomplete, '\t', true);
-    //ib->registerListener(orxonoxConsole_, &InGameConsole::clear, '§', true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::removeLast, '\b', true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::exit, (char)0x1B, true);
-
     return true;
   }
@@ -495,5 +405,5 @@
         renderTime = 0.0f;
       }
-      
+
       // Call those objects that need the real time
       for (Iterator<TickableReal> it = ObjectList<TickableReal>::start(); it; ++it)
@@ -502,6 +412,4 @@
       for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; ++it)
         it->tick((float)evt.timeSinceLastFrame * this->timefactor_);
-      // TODO: currently a hack. Somehow the console doesn't work with OrxonoxClass
-      orxonoxConsole_->tick((float)evt.timeSinceLastFrame);
 
       // don't forget to call _fireFrameStarted in ogre to make sure
@@ -571,12 +479,3 @@
     return (float)(times.back() - times.front()) / ((times.size() - 1) * 1000);
   }
-
-  /**
-   * Static function that shows the console in game mode.
-   */
-  void Orxonox::activateConsole()
-  {
-    // currently, the console shows itself when feeded with input.
-    InputManager::setInputState(InputManager::IS_CONSOLE);
-  }
 }
Index: code/branches/network/src/orxonox/Orxonox.h
===================================================================
--- code/branches/network/src/orxonox/Orxonox.h	(revision 1445)
+++ code/branches/network/src/orxonox/Orxonox.h	(revision 1446)
@@ -70,5 +70,4 @@
       static inline float getTimeFactor() { return Orxonox::getSingleton()->timefactor_; }
       static inline void exit() { Orxonox::getSingleton()->abortRequest(); }
-      static inline void activateConsole();
 
    private:
@@ -97,5 +96,4 @@
       // TODO: make this a config-value by creating a config class for orxonox
       float                 frameSmoothingTime_;
-      InGameConsole*        orxonoxConsole_;
       HUD*                  orxonoxHUD_;
       bool                  bAbort_;        //!< aborts the render loop if true
Index: code/branches/network/src/orxonox/console/InGameConsole.cc
===================================================================
--- code/branches/network/src/orxonox/console/InGameConsole.cc	(revision 1445)
+++ code/branches/network/src/orxonox/console/InGameConsole.cc	(revision 1446)
@@ -23,5 +23,5 @@
  *      Felix Schulthess
  *   Co-authors:
- *      ...
+ *      Fabian 'x3n' Landau
  *
  */
@@ -40,243 +40,464 @@
 #include "core/Debug.h"
 #include "core/CoreIncludes.h"
+#include "core/ConfigValueIncludes.h"
 #include "core/ConsoleCommand.h"
 #include "core/InputManager.h"
+#include "util/Math.h"
 #include "GraphicsEngine.h"
 
-#define LINES 20
+#define LINES 30
+#define CHAR_WIDTH 7.85 // fix this please - determine the char-width dynamically
 
 namespace orxonox
 {
+    SetConsoleCommand(InGameConsole, openConsole, true);
+    SetConsoleCommand(InGameConsole, closeConsole, true);
+
     using namespace Ogre;
 
-    const float REL_WIDTH = 0.8;
-    const float REL_HEIGHT = 0.4;
-    const float BLINK = 0.25;
-
-    InGameConsole::InGameConsole(InputBuffer* ib) :
-        windowW(0), windowH(0),
-        scroll(0), scrollTimer(0.0f),
-        cursor(0.0f),
-        active(false),
-        ib_(ib),
-        om(0),
-        consoleOverlay(0),
-        consoleOverlayContainer(0),
-        consoleOverlayNoise(0),
-        consoleOverlayBorder(0),
-        consoleOverlayTextAreas(0)
-    {
-        //RegisterObject(InGameConsole);
-        init();
-    }
-
-    InGameConsole::~InGameConsole(void){
-        for(int i=0; i<LINES; i++) delete consoleOverlayTextAreas[i];
-        delete consoleOverlayTextAreas;
-    }
-
-    void InGameConsole::listen(){
-        if(!active) activate();
-        print(convert2UTF(this->ib_->get()));
-    }
-
-    void InGameConsole::execute(){	
-        newline();
-        if (!CommandExecutor::execute(this->ib_->get())){
-            print("Error");
-            newline();
-        }
-        this->ib_->clear();
-    }
-
-    void InGameConsole::hintandcomplete(){
-        print(CommandExecutor::hint(this->ib_->get()));
-        newline();
-        this->ib_->set(CommandExecutor::complete(this->ib_->get()));
-        print(convert2UTF(this->ib_->get()));
-    }
-
-    void InGameConsole::clear(){
-        this->ib_->clear();
-    }
-
-    void InGameConsole::removeLast(){
-        this->ib_->removeLast();
-    }
-
-    void InGameConsole::exit(){
-        clear();
-        deactivate();
-        InputManager::setInputState(InputManager::IS_NORMAL);
-    }
-
-    /**
-    @brief called once by constructor
-    */
-    void InGameConsole::init(){
+    float InGameConsole::REL_WIDTH = 0.8;
+    float InGameConsole::REL_HEIGHT = 0.4;
+    float InGameConsole::BLINK = 0.5;
+
+    /**
+        @brief Constructor: Creates and initializes the InGameConsole.
+    */
+    InGameConsole::InGameConsole() :
+        om_(0), consoleOverlay_(0), consoleOverlayContainer_(0),
+        consoleOverlayNoise_(0), consoleOverlayBorder_(0), consoleOverlayTextAreas_(0)
+    {
+        RegisterObject(InGameConsole);
+
+        this->active_ = false;
+        this->cursor_ = 0.0;
+        this->cursorSymbol_ = '|';
+        this->inputWindowStart_ = 0;
+        this->numLinesShifted_ = LINES - 1;
+
+        this->init();
+        this->setConfigValues();
+
+        Shell::getInstance().addOutputLevel(true);
+    }
+
+    /**
+        @brief Destructor: Destroys the TextAreas.
+    */
+    InGameConsole::~InGameConsole(void)
+    {
+        for (int i = 0; i < LINES; i++)
+            if (this->consoleOverlayTextAreas_[i])
+                delete this->consoleOverlayTextAreas_[i];
+
+        if (this->consoleOverlayTextAreas_)
+            delete this->consoleOverlayTextAreas_;
+    }
+
+    /**
+        @brief Returns a reference to the only existing instance of InGameConsole.
+    */
+    InGameConsole& InGameConsole::getInstance()
+    {
+        static InGameConsole instance;
+        return instance;
+    }
+
+    /**
+        @brief Sets the config values, describing the size of the console.
+    */
+    void InGameConsole::setConfigValues()
+    {
+        SetConfigValue(REL_WIDTH, 0.8);
+        SetConfigValue(REL_HEIGHT, 0.4);
+        SetConfigValue(BLINK, 0.5);
+    }
+
+    /**
+        @brief Called if all output-lines have to be redrawn.
+    */
+    void InGameConsole::linesChanged()
+    {
+        std::list<std::string>::const_iterator it = Shell::getInstance().getNewestLineIterator();
+        int max = 0;
+        for (int i = 1; i < LINES; ++i)
+        {
+            if (it != Shell::getInstance().getEndIterator())
+            {
+                ++it;
+                max = i;
+            }
+            else
+                break;
+        }
+
+        for (int i = LINES - 1; i > max; --i)
+            this->print("", i, true);
+
+        for (int i = max; i >= 1; --i)
+        {
+            --it;
+            this->print(*it, i, true);
+        }
+    }
+
+    /**
+        @brief Called if only the last output-line has changed.
+    */
+    void InGameConsole::onlyLastLineChanged()
+    {
+        if (LINES > 1)
+            this->print(*Shell::getInstance().getNewestLineIterator(), 1);
+    }
+
+    /**
+        @brief Called if a new output-line was added.
+    */
+    void InGameConsole::lineAdded()
+    {
+        this->numLinesShifted_ = 0;
+        this->shiftLines();
+        this->onlyLastLineChanged();
+    }
+
+    /**
+        @brief Called if the text in the input-line has changed.
+    */
+    void InGameConsole::inputChanged()
+    {
+        if (LINES > 0)
+            this->print(Shell::getInstance().getInput(), 0);
+
+        if (Shell::getInstance().getInput() == "" || Shell::getInstance().getInput().size() == 0)
+            this->inputWindowStart_ = 0;
+    }
+
+    /**
+        @brief Called if the position of the cursor in the input-line has changed.
+    */
+    void InGameConsole::cursorChanged()
+    {
+        std::string input = Shell::getInstance().getInput();
+        input.insert(Shell::getInstance().getCursorPosition(), 1, this->cursorSymbol_);
+        if (LINES > 0)
+            this->print(input, 0);
+    }
+
+    /**
+        @brief Called if the console gets closed.
+    */
+    void InGameConsole::exit()
+    {
+        this->deactivate();
+    }
+
+    /**
+        @brief Called once by constructor, initializes the InGameConsole.
+    */
+    void InGameConsole::init()
+    {
         // for the beginning, don't scroll
-        scroll = 0;
-        scrollTimer = 0;
-        cursor = 0;
+        this->scroll_ = 0;
+        this->scrollTimer_ = 0;
+        this->cursor_ = 0;
 
         // create overlay and elements
-        om = &Ogre::OverlayManager::getSingleton();
+        this->om_ = &Ogre::OverlayManager::getSingleton();
 
         // create a container
-        consoleOverlayContainer = static_cast<OverlayContainer*>(om->createOverlayElement("Panel", "container"));
-        consoleOverlayContainer->setMetricsMode(Ogre::GMM_RELATIVE);
-        consoleOverlayContainer->setPosition((1-REL_WIDTH)/2, 0);
-        consoleOverlayContainer->setDimensions(REL_WIDTH, REL_HEIGHT);
+        this->consoleOverlayContainer_ = static_cast<OverlayContainer*>(this->om_->createOverlayElement("Panel", "InGameConsoleContainer"));
+        this->consoleOverlayContainer_->setMetricsMode(Ogre::GMM_RELATIVE);
+        this->consoleOverlayContainer_->setPosition((1 - InGameConsole::REL_WIDTH) / 2, 0);
+        this->consoleOverlayContainer_->setDimensions(InGameConsole::REL_WIDTH, InGameConsole::REL_HEIGHT);
 
         // create BorderPanel
-        consoleOverlayBorder = static_cast<BorderPanelOverlayElement*>(om->createOverlayElement("BorderPanel", "borderPanel"));
-        consoleOverlayBorder->setMetricsMode(Ogre::GMM_PIXELS);
-        consoleOverlayBorder->setMaterialName("ConsoleCenter");
+        this->consoleOverlayBorder_ = static_cast<BorderPanelOverlayElement*>(this->om_->createOverlayElement("BorderPanel", "InGameConsoleBorderPanel"));
+        this->consoleOverlayBorder_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayBorder_->setMaterialName("ConsoleCenter");
         // set parameters for border
-        consoleOverlayBorder->setBorderSize(16, 16, 0, 16);
-        consoleOverlayBorder->setBorderMaterialName("ConsoleBorder");
-        consoleOverlayBorder->setLeftBorderUV(0.0, 0.49, 0.5, 0.51);
-        consoleOverlayBorder->setRightBorderUV(0.5, 0.49, 1.0, 0.5);
-        consoleOverlayBorder->setBottomBorderUV(0.49, 0.5, 0.51, 1.0);
-        consoleOverlayBorder->setBottomLeftBorderUV(0.0, 0.5, 0.5, 1.0);
-        consoleOverlayBorder->setBottomRightBorderUV(0.5, 0.5, 1.0, 1.0);
+        this->consoleOverlayBorder_->setBorderSize(16, 16, 0, 16);
+        this->consoleOverlayBorder_->setBorderMaterialName("ConsoleBorder");
+        this->consoleOverlayBorder_->setLeftBorderUV(0.0, 0.49, 0.5, 0.51);
+        this->consoleOverlayBorder_->setRightBorderUV(0.5, 0.49, 1.0, 0.5);
+        this->consoleOverlayBorder_->setBottomBorderUV(0.49, 0.5, 0.51, 1.0);
+        this->consoleOverlayBorder_->setBottomLeftBorderUV(0.0, 0.5, 0.5, 1.0);
+        this->consoleOverlayBorder_->setBottomRightBorderUV(0.5, 0.5, 1.0, 1.0);
 
         // create the text lines
-        consoleOverlayTextAreas = new TextAreaOverlayElement*[LINES];
-        for(int i = 0; i<LINES; i++){
-            consoleOverlayTextAreas[i] = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "textArea"+Ogre::StringConverter::toString(i)));
-            consoleOverlayTextAreas[i]->setMetricsMode(Ogre::GMM_PIXELS);
-            consoleOverlayTextAreas[i]->setFontName("Console");
-            consoleOverlayTextAreas[i]->setCharHeight(20);
-            consoleOverlayTextAreas[i]->setParameter("colour_top", "0.21 0.69 0.21");
-            consoleOverlayTextAreas[i]->setLeft(8);
-            consoleOverlayTextAreas[i]->setCaption("");
+        this->consoleOverlayTextAreas_ = new TextAreaOverlayElement*[LINES];
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i] = static_cast<TextAreaOverlayElement*>(this->om_->createOverlayElement("TextArea", "InGameConsoleTextArea" + Ogre::StringConverter::toString(i)));
+            this->consoleOverlayTextAreas_[i]->setMetricsMode(Ogre::GMM_PIXELS);
+            this->consoleOverlayTextAreas_[i]->setFontName("Console");
+            this->consoleOverlayTextAreas_[i]->setCharHeight(18);
+            this->consoleOverlayTextAreas_[i]->setParameter("colour_top", "0.21 0.69 0.21");
+            this->consoleOverlayTextAreas_[i]->setLeft(8);
+            this->consoleOverlayTextAreas_[i]->setCaption("");
         }
 
         // create noise
-        consoleOverlayNoise = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel", "noise"));
-        consoleOverlayNoise->setMetricsMode(Ogre::GMM_PIXELS);
-        consoleOverlayNoise->setPosition(5,0);
-        consoleOverlayNoise->setMaterialName("ConsoleNoise");
-
-        consoleOverlay = om->create("Console");
-        consoleOverlay->add2D(consoleOverlayContainer);
-        consoleOverlayContainer->addChild(consoleOverlayBorder);
-//comment following line to disable noise
-        consoleOverlayContainer->addChild(consoleOverlayNoise);
-        for(int i = 0; i<LINES; i++) consoleOverlayContainer->addChild(consoleOverlayTextAreas[i]);
-        resize();
+        this->consoleOverlayNoise_ = static_cast<PanelOverlayElement*>(this->om_->createOverlayElement("Panel", "InGameConsoleNoise"));
+        this->consoleOverlayNoise_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayNoise_->setPosition(5,0);
+        this->consoleOverlayNoise_->setMaterialName("ConsoleNoise");
+
+        this->consoleOverlay_ = this->om_->create("InGameConsoleConsole");
+        this->consoleOverlay_->add2D(this->consoleOverlayContainer_);
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayBorder_);
+        //comment following line to disable noise
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayNoise_);
+        for (int i = 0; i < LINES; i++)
+            this->consoleOverlayContainer_->addChild(this->consoleOverlayTextAreas_[i]);
+
+        this->resize();
 
         // move overlay "above" the top edge of the screen
         // we take -1.2 because the border mkes the panel bigger
-        consoleOverlayContainer->setTop(-1.2*REL_HEIGHT);
+        this->consoleOverlayContainer_->setTop(-1.2 * InGameConsole::REL_HEIGHT);
         // show overlay
-        consoleOverlay->show();
-
-        COUT(3) << "Info: InGameConsole initialized" << std::endl;
-    }
-
-    /**
-    @brief used to control the actual scrolling and cursor
-    */
-    void InGameConsole::tick(float dt){
-        scrollTimer += dt;
-        if(scrollTimer >= 0.01){
-            float top = consoleOverlayContainer->getTop();
-            scrollTimer = 0;
-            if(scroll!=0){
+        this->consoleOverlay_->show();
+
+        COUT(4) << "Info: InGameConsole initialized" << std::endl;
+    }
+
+    /**
+        @brief Resizes the console elements. Call if window size changes.
+    */
+    void InGameConsole::resize()
+    {
+        this->windowW_ = GraphicsEngine::getSingleton().getWindowWidth();
+        this->windowH_ = GraphicsEngine::getSingleton().getWindowHeight();
+        this->consoleOverlayBorder_->setWidth((int) this->windowW_* InGameConsole::REL_WIDTH);
+        this->consoleOverlayBorder_->setHeight((int) this->windowH_ * InGameConsole::REL_HEIGHT);
+        this->consoleOverlayNoise_->setWidth((int) this->windowW_ * InGameConsole::REL_WIDTH - 10);
+        this->consoleOverlayNoise_->setHeight((int) this->windowH_ * InGameConsole::REL_HEIGHT - 5);
+
+        // now adjust the text lines...
+        this->desiredTextWidth_ = (int) (this->windowW_ * InGameConsole::REL_WIDTH) - 12;
+
+        if (LINES > 0)
+            this->maxCharsPerLine_ = max((unsigned int)10, (unsigned int) ((float)this->desiredTextWidth_ / CHAR_WIDTH));
+        else
+            this->maxCharsPerLine_ = 10;
+
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i]->setWidth(this->desiredTextWidth_);
+            this->consoleOverlayTextAreas_[i]->setTop((int) this->windowH_ * InGameConsole::REL_HEIGHT - 24 - 14*i);
+        }
+
+        this->linesChanged();
+    }
+
+    /**
+        @brief Used to control the actual scrolling and the cursor.
+    */
+    void InGameConsole::tick(float dt)
+    {
+        this->scrollTimer_ += dt;
+        if (this->scrollTimer_ >= 0.01)
+        {
+            float top = this->consoleOverlayContainer_->getTop();
+            this->scrollTimer_ = 0;
+            if (this->scroll_ != 0)
+            {
                 // scroll
-                top = top + 0.02*scroll;
-                consoleOverlayContainer->setTop(top);
+                top = top + 0.02 * this->scroll_;
+                this->consoleOverlayContainer_->setTop(top);
             }
-            if(top <= -1.2*REL_HEIGHT){
+            if (top <= -1.2 * InGameConsole::REL_HEIGHT)
+            {
                 // window has completely scrolled up
-                scroll = 0;
-                consoleOverlay->hide();
-                active = false;
+                this->scroll_ = 0;
+                this->consoleOverlay_->hide();
+                this->active_ = false;
+                Shell::getInstance().unregisterListener(this);
             }
-            if(top >= 0){
+            if (top >= 0)
+            {
                 // window has completely scrolled down
-                scroll = 0;
-                consoleOverlayContainer->setTop(0);
-                active = true;
+                this->scroll_ = 0;
+                this->consoleOverlayContainer_->setTop(0);
+                this->active_ = true;
             }
         }
 
-        cursor += dt;
-        if(cursor >= 2*BLINK) cursor = 0;
-        print(convert2UTF(this->ib_->get()));
-
-// this creates a flickering effect
-        consoleOverlayNoise->setTiling(1, rand()%5+1);
-    }
-
-    /**
-    @brief resizes the console elements. call if window size changes
-    */
-    void InGameConsole::resize(){
-        windowW = GraphicsEngine::getSingleton().getWindowWidth();
-        windowH = GraphicsEngine::getSingleton().getWindowHeight();
-        consoleOverlayBorder->setWidth((int) windowW*REL_WIDTH);
-        consoleOverlayBorder->setHeight((int) windowH*REL_HEIGHT);
-        consoleOverlayNoise->setWidth((int) windowW*REL_WIDTH - 10);
-        consoleOverlayNoise->setHeight((int) windowH*REL_HEIGHT - 5);
-        // now adjust the text lines...
-        for(int i = 0; i<LINES; i++){
-            consoleOverlayTextAreas[i]->setWidth(windowW*REL_WIDTH);
-            consoleOverlayTextAreas[i]->setTop((int)windowH*REL_HEIGHT - 24 - 16*i);
-        }
-    }
-
-    /**
-    @brief shows console
-    */
-    void InGameConsole::activate(){
-        consoleOverlay->show();
+        this->cursor_ += dt;
+        if (this->cursor_ >= 2 * InGameConsole::BLINK)
+            this->cursor_ = 0;
+
+        if (this->cursor_ >= InGameConsole::BLINK && this->cursorSymbol_ == '|')
+        {
+            this->cursorSymbol_ = ' ';
+            this->cursorChanged();
+        }
+        else if (this->cursor_ < InGameConsole::BLINK && this->cursorSymbol_ == ' ')
+        {
+            this->cursorSymbol_ = '|';
+            this->cursorChanged();
+        }
+
+        // this creates a flickering effect
+        this->consoleOverlayNoise_->setTiling(1, rand() % 5 + 1);
+    }
+
+    /**
+        @brief Shows the InGameConsole.
+    */
+    void InGameConsole::activate()
+    {
+        InputManager::setInputState(InputManager::IS_CONSOLE);
+        Shell::getInstance().registerListener(this);
+        this->linesChanged();
+
+        this->consoleOverlay_->show();
         // just in case window size has changed...
-        resize();
+        this->resize();
         // scroll down
-        scroll = 1;
+        this->scroll_ = 1;
         // the rest is done by tick
     }
 
     /**
-    @brief hides console
-    */
-    void InGameConsole::deactivate(){
+    @brief Hides the InGameConsole.
+    */
+    void InGameConsole::deactivate()
+    {
         // scroll up
-        scroll = -1;
+        this->scroll_ = -1;
         // the rest is done by tick
-    }
-
-    /**
-    @brief prints string to bottom line
-    @param s string to be printed
-    */
-    void InGameConsole::print(Ogre::UTFString s){
-        if(cursor>BLINK) consoleOverlayTextAreas[0]->setCaption(">" + s);
-        else consoleOverlayTextAreas[0]->setCaption(">" + s + "_");
-    }
-
-    /**
-    @brief shifts all lines up and clears the bottom line
-    */
-    void InGameConsole::newline(){
-        Ogre::UTFString line;
-        for(int i = LINES-1; i>=1; i--){
-            line = consoleOverlayTextAreas[i-1]->getCaption();
-            // don't copy the cursor...
-            int l = line.length();
-            if(!line.empty() && line.substr(l-1) == "_") line.erase(l-1);
-            consoleOverlayTextAreas[i]->setCaption(line);
-        }
-        consoleOverlayTextAreas[0]->setCaption(">");
-    }
-
-    Ogre::UTFString InGameConsole::convert2UTF(std::string s){
+        InputManager::setInputState(InputManager::IS_NORMAL);
+    }
+
+    /**
+        @brief Activates the console.
+    */
+    void InGameConsole::openConsole()
+    {
+        InGameConsole::getInstance().activate();
+    }
+
+    /**
+        @brief Deactivates the console.
+    */
+    void InGameConsole::closeConsole()
+    {
+        InGameConsole::getInstance().deactivate();
+    }
+
+    /**
+        @brief Shifts all output lines one line up
+    */
+    void InGameConsole::shiftLines()
+    {
+        for (unsigned int i = LINES - 1; i > 1; --i)
+        {
+            this->consoleOverlayTextAreas_[i]->setCaption(this->consoleOverlayTextAreas_[i - 1]->getCaption());
+            this->consoleOverlayTextAreas_[i]->setColourTop(this->consoleOverlayTextAreas_[i - 1]->getColourTop());
+            this->consoleOverlayTextAreas_[i]->setColourBottom(this->consoleOverlayTextAreas_[i - 1]->getColourBottom());
+        }
+    }
+
+    void InGameConsole::colourLine(int colourcode, int index)
+    {
+        if (colourcode == -1)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.90, 0.90, 0.90, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 1.00, 1.00, 1.00));
+        }
+        else if (colourcode == 1)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.95, 0.25, 0.25, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.50, 0.50, 1.00));
+        }
+        else if (colourcode == 2)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.95, 0.50, 0.20, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.70, 0.50, 1.00));
+        }
+        else if (colourcode == 3)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.50, 0.50, 0.95, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 0.80, 1.00, 1.00));
+        }
+        else if (colourcode == 4)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.65, 0.48, 0.44, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.90, 0.90, 1.00));
+        }
+        else if (colourcode == 5)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.40, 0.20, 0.40, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 0.60, 0.80, 1.00));
+        }
+        else
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.21, 0.69, 0.21, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 1.00, 0.80, 1.00));
+        }
+    }
+
+    /**
+        @brief Prints string to bottom line.
+        @param s String to be printed
+    */
+    void InGameConsole::print(const std::string& text, int index, bool alwaysShift)
+    {
+        char level = 0;
+        if (text.size() > 0)
+            level = text[0];
+
+        std::string output = text;
+
+        if (level >= -1 && level <= 5)
+            output.erase(0, 1);
+
+        if (LINES > index)
+        {
+            this->colourLine(level, index);
+
+            if (index > 0)
+            {
+                unsigned int linesUsed = 1;
+                while (output.size() > this->maxCharsPerLine_)
+                {
+                    ++linesUsed;
+                    this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output.substr(0, this->maxCharsPerLine_)));
+                    output.erase(0, this->maxCharsPerLine_);
+                    output.insert(0, 1, ' ');
+                    if (linesUsed > numLinesShifted_ || alwaysShift)
+                        this->shiftLines();
+                    this->colourLine(level, index);
+                }
+                this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output));
+                this->numLinesShifted_ = linesUsed;
+            }
+            else
+            {
+                if (output.size() > this->maxCharsPerLine_)
+                {
+                    if (Shell::getInstance().getInputBuffer().getCursorPosition() < this->inputWindowStart_)
+                        this->inputWindowStart_ = Shell::getInstance().getInputBuffer().getCursorPosition();
+                    else if (Shell::getInstance().getInputBuffer().getCursorPosition() >= (this->inputWindowStart_ + this->maxCharsPerLine_ - 1))
+                        this->inputWindowStart_ = Shell::getInstance().getInputBuffer().getCursorPosition() - this->maxCharsPerLine_ + 1;
+
+                    output = output.substr(this->inputWindowStart_, this->maxCharsPerLine_);
+                }
+                this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output));
+            }
+        }
+    }
+
+    /**
+        @brief Converts a string into an Ogre::UTFString.
+        @param s The string to convert
+        @return The converted string
+    */
+    Ogre::UTFString InGameConsole::convert2UTF(std::string s)
+    {
         Ogre::UTFString utf;
-        int i;
         Ogre::UTFString::code_point cp;
-        for (i=0; i<(int)s.size(); ++i){
+        for (unsigned int i = 0; i < s.size(); ++i)
+        {
           cp = s[i];
           cp &= 0xFF;
Index: code/branches/network/src/orxonox/console/InGameConsole.h
===================================================================
--- code/branches/network/src/orxonox/console/InGameConsole.h	(revision 1445)
+++ code/branches/network/src/orxonox/console/InGameConsole.h	(revision 1446)
@@ -37,44 +37,63 @@
 
 #include "core/Tickable.h"
-#include "core/InputBuffer.h"
+#include "core/Shell.h"
 
 
 namespace orxonox
 {
-    class _OrxonoxExport InGameConsole : public InputBufferListener
+    class _OrxonoxExport InGameConsole : public Tickable, public ShellListener
     {
         public:
-            InGameConsole(InputBuffer* ib);
-            ~InGameConsole();
-            void listen();
-            void execute();
-            void hintandcomplete();
-            void clear();
-            void removeLast();
-            void exit();
-            void init();
+            static InGameConsole& getInstance();
+
+            void setConfigValues();
             void tick(float dt);
+
             void activate();
             void deactivate();
+            void resize();
+
+            static void openConsole();
+            static void closeConsole();
 
         private:
-            void resize();
-            void print(Ogre::UTFString s);
-            void newline();
-            Ogre::UTFString convert2UTF(std::string s);
+            InGameConsole();
+            InGameConsole(const InGameConsole& other);
+            ~InGameConsole();
 
-            int windowW;
-            int windowH;
-            int scroll;
-            float scrollTimer;
-            float cursor;
-            bool active;
-            InputBuffer* ib_;
-            Ogre::OverlayManager* om;
-            Ogre::Overlay* consoleOverlay;
-            Ogre::OverlayContainer* consoleOverlayContainer;
-            Ogre::PanelOverlayElement* consoleOverlayNoise;
-            Ogre::BorderPanelOverlayElement* consoleOverlayBorder;
-            Ogre::TextAreaOverlayElement** consoleOverlayTextAreas;
+            virtual void linesChanged();
+            virtual void onlyLastLineChanged();
+            virtual void lineAdded();
+            virtual void inputChanged();
+            virtual void cursorChanged();
+            virtual void exit();
+
+            void init();
+            void shiftLines();
+            void colourLine(int colourcode, int index);
+            void print(const std::string& text, int index, bool alwaysShift = false);
+            static Ogre::UTFString convert2UTF(std::string s);
+
+            static float REL_WIDTH;
+            static float REL_HEIGHT;
+            static float BLINK;
+
+            int windowW_;
+            int windowH_;
+            int desiredTextWidth_;
+            unsigned int maxCharsPerLine_;
+            unsigned int numLinesShifted_;
+            int scroll_;
+            float scrollTimer_;
+            float cursor_;
+            unsigned int inputWindowStart_;
+            char cursorSymbol_;
+            bool active_;
+            Ogre::OverlayManager* om_;
+            Ogre::Overlay* consoleOverlay_;
+            Ogre::OverlayContainer* consoleOverlayContainer_;
+            Ogre::PanelOverlayElement* consoleOverlayNoise_;
+            Ogre::BorderPanelOverlayElement* consoleOverlayBorder_;
+            Ogre::TextAreaOverlayElement** consoleOverlayTextAreas_;
     };
 }
Index: code/branches/network/src/orxonox/hud/HUD.cc
===================================================================
--- code/branches/network/src/orxonox/hud/HUD.cc	(revision 1445)
+++ code/branches/network/src/orxonox/hud/HUD.cc	(revision 1446)
@@ -47,5 +47,5 @@
 namespace orxonox
 {
-    ConsoleCommandShortcut(HUD, cycleNavigationFocus, AccessLevel::User);
+    SetConsoleCommandShortcut(HUD, cycleNavigationFocus).setAccessLevel(AccessLevel::User);
 
     using namespace Ogre;
Index: code/branches/network/src/orxonox/objects/Ambient.cc
===================================================================
--- code/branches/network/src/orxonox/objects/Ambient.cc	(revision 1445)
+++ code/branches/network/src/orxonox/objects/Ambient.cc	(revision 1446)
@@ -47,5 +47,5 @@
 namespace orxonox
 {
-    ConsoleCommand(Ambient, setAmbientLightTest, AccessLevel::Offline, false).setDefaultValues(ColourValue(1, 1, 1, 1));
+    SetConsoleCommand(Ambient, setAmbientLightTest, false).setDefaultValues(ColourValue(1, 1, 1, 1)).setAccessLevel(AccessLevel::Offline);
 
     CreateFactory(Ambient);
Index: code/branches/network/src/orxonox/objects/SpaceShip.cc
===================================================================
--- code/branches/network/src/orxonox/objects/SpaceShip.cc	(revision 1445)
+++ code/branches/network/src/orxonox/objects/SpaceShip.cc	(revision 1446)
@@ -51,15 +51,15 @@
 namespace orxonox
 {
-    ConsoleCommand(SpaceShip, setMaxSpeedTest, AccessLevel::Debug, false);
-    ConsoleCommand(SpaceShip, whereAmI, AccessLevel::User, true);
-    ConsoleCommand(SpaceShip, moveLongitudinal, AccessLevel::User, true).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
-    ConsoleCommand(SpaceShip, moveLateral, AccessLevel::User, true).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
-    ConsoleCommand(SpaceShip, moveYaw, AccessLevel::User, true).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
-    ConsoleCommand(SpaceShip, movePitch, AccessLevel::User, true).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
-    ConsoleCommand(SpaceShip, moveRoll, AccessLevel::User, true).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
-    ConsoleCommand(SpaceShip, fire, AccessLevel::User, true).setKeybindMode(KeybindMode::OnHold);
-    ConsoleCommandGeneric(test1, SpaceShip, createExecutor(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxSpeed", AccessLevel::Debug), false);
-    ConsoleCommandGeneric(test2, SpaceShip, createExecutor(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxBlubber", AccessLevel::Debug), false);
-    ConsoleCommandGeneric(test3, SpaceShip, createExecutor(createFunctor(&SpaceShip::setMaxSpeedTest), "setRofl", AccessLevel::Debug), false);
+    SetConsoleCommand(SpaceShip, setMaxSpeedTest, false).setAccessLevel(AccessLevel::Debug);
+    SetConsoleCommand(SpaceShip, whereAmI, true).setAccessLevel(AccessLevel::User);
+    SetConsoleCommand(SpaceShip, moveLongitudinal, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, moveLateral, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, moveYaw, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, movePitch, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, moveRoll, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, fire, true).setAccessLevel(AccessLevel::User).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommandGeneric(test1, SpaceShip, createConsoleCommand(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxSpeed"), false).setAccessLevel(AccessLevel::Debug);
+    SetConsoleCommandGeneric(test2, SpaceShip, createConsoleCommand(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxBlubber"), false).setAccessLevel(AccessLevel::Debug);
+    SetConsoleCommandGeneric(test3, SpaceShip, createConsoleCommand(createFunctor(&SpaceShip::setMaxSpeedTest), "setRofl"), false).setAccessLevel(AccessLevel::Debug);
 
     CreateFactory(SpaceShip);
Index: code/branches/network/src/orxonox/tools/Timer.cc
===================================================================
--- code/branches/network/src/orxonox/tools/Timer.cc	(revision 1445)
+++ code/branches/network/src/orxonox/tools/Timer.cc	(revision 1446)
@@ -27,4 +27,6 @@
  */
 
+#include <set>
+
 #include "OrxonoxStableHeaders.h"
 #include "Timer.h"
@@ -37,5 +39,8 @@
 namespace orxonox
 {
-    ConsoleCommandShortcutExtern(delay, AccessLevel::None);
+    SetConsoleCommandShortcutExtern(delay);
+    SetConsoleCommandShortcutExtern(killdelays);
+
+    static std::set<StaticTimer*> delaytimerset;
 
     /**
@@ -47,4 +52,6 @@
     {
         StaticTimer *delaytimer = new StaticTimer();
+        delaytimerset.insert(delaytimer);
+
         ExecutorStatic* delayexecutor = createExecutor(createFunctor(&executeDelayedCommand));
         delayexecutor->setDefaultValues(delaytimer, command);
@@ -61,4 +68,16 @@
         CommandExecutor::execute(command);
         delete timer;
+        delaytimerset.erase(timer);
+    }
+
+    /**
+        @brief Kills all delayed commands.
+    */
+    void killdelays()
+    {
+        for (std::set<StaticTimer*>::iterator it = delaytimerset.begin(); it != delaytimerset.end(); ++it)
+            delete (*it);
+
+        delaytimerset.clear();
     }
 
Index: code/branches/network/src/orxonox/tools/Timer.h
===================================================================
--- code/branches/network/src/orxonox/tools/Timer.h	(revision 1445)
+++ code/branches/network/src/orxonox/tools/Timer.h	(revision 1446)
@@ -69,4 +69,5 @@
     class StaticTimer;
     void delay(float delay, const std::string& command);
+    void killdelays();
     void executeDelayedCommand(StaticTimer* timer, const std::string& command);
 
Index: code/branches/network/src/util/Convert.h
===================================================================
--- code/branches/network/src/util/Convert.h	(revision 1445)
+++ code/branches/network/src/util/Convert.h	(revision 1446)
@@ -384,4 +384,6 @@
         else if (input.getType() == MT_vector3)
             return ConvertValue(output, input.getVector3());
+        else if (input.getType() == MT_vector4)
+            return ConvertValue(output, input.getVector4());
         else if (input.getType() == MT_quaternion)
             return ConvertValue(output, input.getQuaternion());
Index: code/branches/network/src/util/Math.h
===================================================================
--- code/branches/network/src/util/Math.h	(revision 1445)
+++ code/branches/network/src/util/Math.h	(revision 1446)
@@ -121,4 +121,13 @@
 
 template <typename T>
+inline int mod(T x, int max)
+{
+    if (x >= 0)
+        return (x % max);
+    else
+        return ((x % max) + max);
+}
+
+template <typename T>
 T interpolate(float time, const T& start, const T& end)
 {
Index: code/branches/network/src/util/MultiType.h
===================================================================
--- code/branches/network/src/util/MultiType.h	(revision 1445)
+++ code/branches/network/src/util/MultiType.h	(revision 1446)
@@ -54,4 +54,5 @@
     MT_vector2,
     MT_vector3,
+    MT_vector4,
     MT_colourvalue,
     MT_quaternion,
Index: code/branches/network/src/util/MultiTypeMath.cc
===================================================================
--- code/branches/network/src/util/MultiTypeMath.cc	(revision 1445)
+++ code/branches/network/src/util/MultiTypeMath.cc	(revision 1446)
@@ -37,4 +37,6 @@
     else if (type == MT_vector3)
         this->vector3_ = orxonox::Vector3(0, 0, 0);
+    else if (type == MT_vector4)
+        this->vector4_ = orxonox::Vector4(0, 0, 0, 0);
     else if (type == MT_colourvalue)
         this->colourvalue_ = orxonox::ColourValue(0, 0, 0, 0);
@@ -55,4 +57,6 @@
         else if (this->type_ == MT_vector3)
             return (this->vector3_ == mtm.vector3_);
+        else if (this->type_ == MT_vector4)
+            return (this->vector4_ == mtm.vector4_);
         else if (this->type_ == MT_colourvalue)
             return (this->colourvalue_ == mtm.colourvalue_);
@@ -68,4 +72,14 @@
 }
 
+bool MultiTypeMath::operator==(const MultiTypeString& mts) const
+{
+    return MultiTypeString::operator==(mts);
+}
+
+bool MultiTypeMath::operator==(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator==(mtp);
+}
+
 bool MultiTypeMath::operator!=(const MultiTypeMath& mtm) const
 {
@@ -76,4 +90,6 @@
         else if (this->type_ == MT_vector3)
             return (this->vector3_ != mtm.vector3_);
+        else if (this->type_ == MT_vector4)
+            return (this->vector4_ != mtm.vector4_);
         else if (this->type_ == MT_colourvalue)
             return (this->colourvalue_ != mtm.colourvalue_);
@@ -87,4 +103,14 @@
 
     return true;
+}
+
+bool MultiTypeMath::operator!=(const MultiTypeString& mts) const
+{
+    return MultiTypeString::operator!=(mts);
+}
+
+bool MultiTypeMath::operator!=(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator!=(mtp);
 }
 
@@ -123,4 +149,6 @@
 MultiTypeMath::operator orxonox::Vector3() const
 { return (this->type_ == MT_vector3) ? this->vector3_ : getConvertedValue<MultiTypeMath, orxonox::Vector3>(*this); }
+MultiTypeMath::operator orxonox::Vector4() const
+{ return (this->type_ == MT_vector4) ? this->vector4_ : getConvertedValue<MultiTypeMath, orxonox::Vector4>(*this); }
 MultiTypeMath::operator orxonox::Quaternion() const
 { return (this->type_ == MT_quaternion) ? this->quaternion_ : getConvertedValue<MultiTypeMath, orxonox::Quaternion>(*this); }
@@ -137,4 +165,5 @@
     this->vector2_ = mtm.vector2_;
     this->vector3_ = mtm.vector3_;
+    this->vector4_ = mtm.vector4_;
     this->quaternion_ = mtm.quaternion_;
     this->colourvalue_ = mtm.colourvalue_;
@@ -143,4 +172,14 @@
 }
 
+void MultiTypeMath::setValue(const MultiTypeString& mts)
+{
+    MultiTypeString::setValue(mts);
+}
+
+void MultiTypeMath::setValue(const MultiTypePrimitive& mtp)
+{
+    MultiTypePrimitive::setValue(mtp);
+}
+
 std::string MultiTypeMath::getTypename() const
 {
@@ -149,4 +188,6 @@
     else if (this->type_ == MT_vector3)
         return "Vector3";
+    else if (this->type_ == MT_vector4)
+        return "Vector4";
     else if (this->type_ == MT_colourvalue)
         return "ColourValue";
@@ -169,4 +210,6 @@
     else if (this->type_ == MT_vector3)
         ConvertValue(&output, this->vector3_);
+    else if (this->type_ == MT_vector4)
+        ConvertValue(&output, this->vector4_);
     else if (this->type_ == MT_colourvalue)
         ConvertValue(&output, this->colourvalue_);
@@ -189,4 +232,6 @@
     else if (this->type_ == MT_vector3)
         return ConvertValue(&this->vector3_, value, orxonox::Vector3(0, 0, 0));
+    else if (this->type_ == MT_vector4)
+        return ConvertValue(&this->vector4_, value, orxonox::Vector4(0, 0, 0, 0));
     else if (this->type_ == MT_colourvalue)
         return ConvertValue(&this->colourvalue_, value, orxonox::ColourValue(0, 0, 0, 0));
@@ -201,4 +246,54 @@
 }
 
+bool MultiTypeMath::assimilate(const MultiTypeMath& mtm, const MultiTypeMath& defvalue)
+{
+    if (this->type_ == MT_void)
+        return ConvertValue(&this->value_.void_, mtm, defvalue.value_.void_);
+    else if (this->type_ == MT_int)
+        return ConvertValue(&this->value_.int_, mtm, defvalue.value_.int_);
+    else if (this->type_ == MT_uint)
+        return ConvertValue(&this->value_.uint_, mtm, defvalue.value_.uint_);
+    else if (this->type_ == MT_char)
+        return ConvertValue(&this->value_.char_, mtm, defvalue.value_.char_);
+    else if (this->type_ == MT_uchar)
+        return ConvertValue(&this->value_.uchar_, mtm, defvalue.value_.uchar_);
+    else if (this->type_ == MT_short)
+        return ConvertValue(&this->value_.short_, mtm, defvalue.value_.short_);
+    else if (this->type_ == MT_ushort)
+        return ConvertValue(&this->value_.ushort_, mtm, defvalue.value_.ushort_);
+    else if (this->type_ == MT_long)
+        return ConvertValue(&this->value_.long_, mtm, defvalue.value_.long_);
+    else if (this->type_ == MT_ulong)
+        return ConvertValue(&this->value_.ulong_, mtm, defvalue.value_.ulong_);
+    else if (this->type_ == MT_float)
+        return ConvertValue(&this->value_.float_, mtm, defvalue.value_.float_);
+    else if (this->type_ == MT_double)
+        return ConvertValue(&this->value_.double_, mtm, defvalue.value_.double_);
+    else if (this->type_ == MT_longdouble)
+        return ConvertValue(&this->value_.longdouble_, mtm, defvalue.value_.longdouble_);
+    else if (this->type_ == MT_bool)
+        return ConvertValue(&this->value_.bool_, mtm, defvalue.value_.bool_);
+    else if (this->type_ == MT_constchar)
+        return ConvertValue(&this->string_, mtm, defvalue.string_);
+    else if (this->type_ == MT_string)
+        return ConvertValue(&this->string_, mtm, defvalue.string_);
+    else if (this->type_ == MT_vector2)
+        return ConvertValue(&this->vector2_, mtm, defvalue.vector2_);
+    else if (this->type_ == MT_vector3)
+        return ConvertValue(&this->vector3_, mtm, defvalue.vector3_);
+    else if (this->type_ == MT_vector4)
+        return ConvertValue(&this->vector4_, mtm, defvalue.vector4_);
+    else if (this->type_ == MT_colourvalue)
+        return ConvertValue(&this->colourvalue_, mtm, defvalue.colourvalue_);
+    else if (this->type_ == MT_quaternion)
+        return ConvertValue(&this->quaternion_, mtm, defvalue.quaternion_);
+    else if (this->type_ == MT_radian)
+        return ConvertValue(&this->radian_, mtm, defvalue.radian_);
+    else if (this->type_ == MT_degree)
+        return ConvertValue(&this->degree_, mtm, defvalue.degree_);
+    else
+        return false;
+}
+
 std::ostream& operator<<(std::ostream& out, MultiTypeMath& mtm)
 {
Index: code/branches/network/src/util/MultiTypeMath.h
===================================================================
--- code/branches/network/src/util/MultiTypeMath.h	(revision 1445)
+++ code/branches/network/src/util/MultiTypeMath.h	(revision 1446)
@@ -63,4 +63,5 @@
         inline MultiTypeMath(const orxonox::Vector2&     value) { this->setValue(value); }
         inline MultiTypeMath(const orxonox::Vector3&     value) { this->setValue(value); }
+        inline MultiTypeMath(const orxonox::Vector4&     value) { this->setValue(value); }
         inline MultiTypeMath(const orxonox::ColourValue& value) { this->setValue(value); }
         inline MultiTypeMath(const orxonox::Quaternion&  value) { this->setValue(value); }
@@ -68,4 +69,6 @@
         inline MultiTypeMath(const orxonox::Degree&      value) { this->setValue(value); }
         inline MultiTypeMath(const MultiTypeMath& mtm)          { this->setValue(mtm);   }
+        inline MultiTypeMath(const MultiTypeString& mts)        { this->setValue(mts);   }
+        inline MultiTypeMath(const MultiTypePrimitive& mtp)     { this->setValue(mtp);   }
         virtual inline ~MultiTypeMath() {}
 
@@ -73,4 +76,5 @@
         inline MultiTypeMath& operator=(const orxonox::Vector2&     value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const orxonox::Vector3&     value) { this->setValue(value); return *this; }
+        inline MultiTypeMath& operator=(const orxonox::Vector4&     value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const orxonox::ColourValue& value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const orxonox::Quaternion&  value) { this->setValue(value); return *this; }
@@ -78,8 +82,11 @@
         inline MultiTypeMath& operator=(const orxonox::Degree&      value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const MultiTypeMath& mtm)          { this->setValue(mtm);   return *this; }
+        inline MultiTypeMath& operator=(const MultiTypeString& mts)        { this->setValue(mts);   return *this; }
+        inline MultiTypeMath& operator=(const MultiTypePrimitive mtp)      { this->setValue(mtp);   return *this; }
 
         using MultiTypeString::operator==;
         inline bool operator==(const orxonox::Vector2&     value) const { return (this->vector2_     == value); }
         inline bool operator==(const orxonox::Vector3&     value) const { return (this->vector3_     == value); }
+        inline bool operator==(const orxonox::Vector4&     value) const { return (this->vector4_     == value); }
         inline bool operator==(const orxonox::ColourValue& value) const { return (this->colourvalue_ == value); }
         inline bool operator==(const orxonox::Quaternion&  value) const { return (this->quaternion_  == value); }
@@ -87,8 +94,11 @@
         inline bool operator==(const orxonox::Degree&      value) const { return (this->degree_      == value); }
         bool operator==(const MultiTypeMath& mtm) const;
+        bool operator==(const MultiTypeString& mts) const;
+        bool operator==(const MultiTypePrimitive& mtp) const;
 
         using MultiTypeString::operator!=;
         inline bool operator!=(const orxonox::Vector2&     value) const { return (this->vector2_     != value); }
         inline bool operator!=(const orxonox::Vector3&     value) const { return (this->vector3_     != value); }
+        inline bool operator!=(const orxonox::Vector4&     value) const { return (this->vector4_     != value); }
         inline bool operator!=(const orxonox::ColourValue& value) const { return (this->colourvalue_ != value); }
         inline bool operator!=(const orxonox::Quaternion&  value) const { return (this->quaternion_  != value); }
@@ -96,4 +106,6 @@
         inline bool operator!=(const orxonox::Degree&      value) const { return (this->degree_      != value); }
         bool operator!=(const MultiTypeMath& mtm) const;
+        bool operator!=(const MultiTypeString& mts) const;
+        bool operator!=(const MultiTypePrimitive& mtp) const;
 
         virtual operator void*()                const;
@@ -114,4 +126,5 @@
         virtual operator orxonox::Vector2()     const;
         virtual operator orxonox::Vector3()     const;
+        virtual operator orxonox::Vector4()     const;
         virtual operator orxonox::ColourValue() const;
         virtual operator orxonox::Quaternion()  const;
@@ -122,4 +135,5 @@
         inline void setValue(const orxonox::Vector2&     value) { this->type_ = MT_vector2;     this->vector2_     = value; }
         inline void setValue(const orxonox::Vector3&     value) { this->type_ = MT_vector3;     this->vector3_     = value; }
+        inline void setValue(const orxonox::Vector4&     value) { this->type_ = MT_vector4;     this->vector4_     = value; }
         inline void setValue(const orxonox::ColourValue& value) { this->type_ = MT_colourvalue; this->colourvalue_ = value; }
         inline void setValue(const orxonox::Quaternion&  value) { this->type_ = MT_quaternion;  this->quaternion_  = value; }
@@ -127,7 +141,10 @@
         inline void setValue(const orxonox::Degree&      value) { this->type_ = MT_degree;      this->degree_      = value; }
         void setValue(const MultiTypeMath& mtm);
+        void setValue(const MultiTypeString& mts);
+        void setValue(const MultiTypePrimitive& mtp);
 
         inline orxonox::Vector2     getVector2()     const { return this->vector2_;     }
         inline orxonox::Vector3     getVector3()     const { return this->vector3_;     }
+        inline orxonox::Vector4     getVector4()     const { return this->vector4_;     }
         inline orxonox::ColourValue getColourValue() const { return this->colourvalue_; }
         inline orxonox::Quaternion  getQuaternion()  const { return this->quaternion_;  }
@@ -137,4 +154,5 @@
         inline orxonox::Vector2&     getVector2()     { return this->vector2_;     }
         inline orxonox::Vector3&     getVector3()     { return this->vector3_;     }
+        inline orxonox::Vector4&     getVector4()     { return this->vector4_;     }
         inline orxonox::ColourValue& getColourValue() { return this->colourvalue_; }
         inline orxonox::Quaternion&  getQuaternion()  { return this->quaternion_;  }
@@ -145,4 +163,5 @@
         inline void getValue(orxonox::Vector2*     variable) const { (*variable) = orxonox::Vector2     (this->vector2_);     }
         inline void getValue(orxonox::Vector3*     variable) const { (*variable) = orxonox::Vector3     (this->vector3_);     }
+        inline void getValue(orxonox::Vector4*     variable) const { (*variable) = orxonox::Vector4     (this->vector4_);     }
         inline void getValue(orxonox::ColourValue* variable) const { (*variable) = orxonox::ColourValue (this->colourvalue_); }
         inline void getValue(orxonox::Quaternion*  variable) const { (*variable) = orxonox::Quaternion  (this->quaternion_);  }
@@ -155,7 +174,10 @@
         virtual bool fromString(const std::string value);
 
+        virtual bool assimilate(const MultiTypeMath& mtm, const MultiTypeMath& defvalue = MultiTypeMath());
+
     protected:
         orxonox::Vector2      vector2_;
         orxonox::Vector3      vector3_;
+        orxonox::Vector4      vector4_;
         orxonox::ColourValue  colourvalue_;
         orxonox::Quaternion   quaternion_;
Index: code/branches/network/src/util/MultiTypePrimitive.cc
===================================================================
--- code/branches/network/src/util/MultiTypePrimitive.cc	(revision 1445)
+++ code/branches/network/src/util/MultiTypePrimitive.cc	(revision 1446)
@@ -266,4 +266,37 @@
 }
 
+bool MultiTypePrimitive::assimilate(const MultiTypePrimitive& mtp, const MultiTypePrimitive& defvalue)
+{
+    if (this->type_ == MT_void)
+        return ConvertValue(&this->value_.void_, mtp, defvalue.value_.void_);
+    else if (this->type_ == MT_int)
+        return ConvertValue(&this->value_.int_, mtp, defvalue.value_.int_);
+    else if (this->type_ == MT_uint)
+        return ConvertValue(&this->value_.uint_, mtp, defvalue.value_.uint_);
+    else if (this->type_ == MT_char)
+        return ConvertValue(&this->value_.char_, mtp, defvalue.value_.char_);
+    else if (this->type_ == MT_uchar)
+        return ConvertValue(&this->value_.uchar_, mtp, defvalue.value_.uchar_);
+    else if (this->type_ == MT_short)
+        return ConvertValue(&this->value_.short_, mtp, defvalue.value_.short_);
+    else if (this->type_ == MT_ushort)
+        return ConvertValue(&this->value_.ushort_, mtp, defvalue.value_.ushort_);
+    else if (this->type_ == MT_long)
+        return ConvertValue(&this->value_.long_, mtp, defvalue.value_.long_);
+    else if (this->type_ == MT_ulong)
+        return ConvertValue(&this->value_.ulong_, mtp, defvalue.value_.ulong_);
+    else if (this->type_ == MT_float)
+        return ConvertValue(&this->value_.float_, mtp, defvalue.value_.float_);
+    else if (this->type_ == MT_double)
+        return ConvertValue(&this->value_.double_, mtp, defvalue.value_.double_);
+    else if (this->type_ == MT_longdouble)
+        return ConvertValue(&this->value_.longdouble_, mtp, defvalue.value_.longdouble_);
+    else if (this->type_ == MT_bool)
+        return ConvertValue(&this->value_.bool_, mtp, defvalue.value_.bool_);
+    else
+        return false;
+
+}
+
 std::ostream& operator<<(std::ostream& out, const MultiTypePrimitive& mtp)
 {
Index: code/branches/network/src/util/MultiTypePrimitive.h
===================================================================
--- code/branches/network/src/util/MultiTypePrimitive.h	(revision 1445)
+++ code/branches/network/src/util/MultiTypePrimitive.h	(revision 1446)
@@ -138,5 +138,5 @@
         void setValue(const MultiTypePrimitive& mtp);
 
-        inline void*          getVoid()          const { return this->value_.void_;        }
+        inline void*          getVoid()          const { return this->value_.void_;       }
         inline int            getInt()           const { return this->value_.int_;        }
         inline unsigned int   getUnsignedInt()   const { return this->value_.uint_;       }
@@ -187,4 +187,6 @@
         virtual bool fromString(const std::string value);
 
+        virtual bool assimilate(const MultiTypePrimitive& mtp, const MultiTypePrimitive& defvalue = MultiTypePrimitive());
+
     protected:
         MultiTypeValue  value_;
Index: code/branches/network/src/util/MultiTypeString.cc
===================================================================
--- code/branches/network/src/util/MultiTypeString.cc	(revision 1445)
+++ code/branches/network/src/util/MultiTypeString.cc	(revision 1446)
@@ -33,5 +33,5 @@
 MultiTypeString::MultiTypeString(MultiType type) : MultiTypePrimitive(type)
 {
-    // Nothing to do for string and xml-element
+    // Nothing to do for string
 }
 
@@ -49,4 +49,9 @@
 }
 
+bool MultiTypeString::operator==(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator==(mtp);
+}
+
 bool MultiTypeString::operator!=(const MultiTypeString& mts) const
 {
@@ -60,4 +65,9 @@
 
     return true;
+}
+
+bool MultiTypeString::operator!=(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator!=(mtp);
 }
 
@@ -99,4 +109,9 @@
 }
 
+void MultiTypeString::setValue(const MultiTypePrimitive& mtp)
+{
+    MultiTypePrimitive::setValue(mtp);
+}
+
 std::string MultiTypeString::getTypename() const
 {
@@ -136,4 +151,40 @@
 }
 
+bool MultiTypeString::assimilate(const MultiTypeString& mts, const MultiTypeString& defvalue)
+{
+    if (this->type_ == MT_void)
+        return ConvertValue(&this->value_.void_, mts, defvalue.value_.void_);
+    else if (this->type_ == MT_int)
+        return ConvertValue(&this->value_.int_, mts, defvalue.value_.int_);
+    else if (this->type_ == MT_uint)
+        return ConvertValue(&this->value_.uint_, mts, defvalue.value_.uint_);
+    else if (this->type_ == MT_char)
+        return ConvertValue(&this->value_.char_, mts, defvalue.value_.char_);
+    else if (this->type_ == MT_uchar)
+        return ConvertValue(&this->value_.uchar_, mts, defvalue.value_.uchar_);
+    else if (this->type_ == MT_short)
+        return ConvertValue(&this->value_.short_, mts, defvalue.value_.short_);
+    else if (this->type_ == MT_ushort)
+        return ConvertValue(&this->value_.ushort_, mts, defvalue.value_.ushort_);
+    else if (this->type_ == MT_long)
+        return ConvertValue(&this->value_.long_, mts, defvalue.value_.long_);
+    else if (this->type_ == MT_ulong)
+        return ConvertValue(&this->value_.ulong_, mts, defvalue.value_.ulong_);
+    else if (this->type_ == MT_float)
+        return ConvertValue(&this->value_.float_, mts, defvalue.value_.float_);
+    else if (this->type_ == MT_double)
+        return ConvertValue(&this->value_.double_, mts, defvalue.value_.double_);
+    else if (this->type_ == MT_longdouble)
+        return ConvertValue(&this->value_.longdouble_, mts, defvalue.value_.longdouble_);
+    else if (this->type_ == MT_bool)
+        return ConvertValue(&this->value_.bool_, mts, defvalue.value_.bool_);
+    else if (this->type_ == MT_constchar)
+        return ConvertValue(&this->string_, mts, defvalue.string_);
+    else if (this->type_ == MT_string)
+        return ConvertValue(&this->string_, mts, defvalue.string_);
+    else
+        return false;
+}
+
 std::ostream& operator<<(std::ostream& out, MultiTypeString& mts)
 {
Index: code/branches/network/src/util/MultiTypeString.h
===================================================================
--- code/branches/network/src/util/MultiTypeString.h	(revision 1445)
+++ code/branches/network/src/util/MultiTypeString.h	(revision 1446)
@@ -61,54 +61,59 @@
         inline MultiTypeString(long double    value) : MultiTypePrimitive(value) {}
         inline MultiTypeString(bool           value) : MultiTypePrimitive(value) {}
-        inline MultiTypeString(const char*           value)   { this->setValue(value); }
-        inline MultiTypeString(const std::string&    value)   { this->setValue(value); }
-        inline MultiTypeString(const MultiTypeString& mts)    { this->setValue(mts);   }
+        inline MultiTypeString(const char*             value) { this->setValue(value); }
+        inline MultiTypeString(const std::string&      value) { this->setValue(value); }
+        inline MultiTypeString(const MultiTypeString&    mts)  { this->setValue(mts);   }
+        inline MultiTypeString(const MultiTypePrimitive& mtp)  { this->setValue(mtp);   }
         virtual inline ~MultiTypeString() {}
 
         using MultiTypePrimitive::operator=;
-        inline MultiTypeString& operator=(const char*             value)   { this->setValue(value); return *this; }
-        inline MultiTypeString& operator=(const std::string&      value)   { this->setValue(value); return *this; }
-        inline MultiTypeString& operator=(const MultiTypeString& mts)      { this->setValue(mts);   return *this; }
+        inline MultiTypeString& operator=(const char*             value) { this->setValue(value); return *this; }
+        inline MultiTypeString& operator=(const std::string&      value) { this->setValue(value); return *this; }
+        inline MultiTypeString& operator=(const MultiTypeString&    mts) { this->setValue(mts);   return *this; }
+        inline MultiTypeString& operator=(const MultiTypePrimitive& mtp) { this->setValue(mtp);   return *this; }
 
         using MultiTypePrimitive::operator==;
-        inline bool operator==(const char*             value) const { return (this->string_      == std::string(value)); }
-        inline bool operator==(const std::string&      value) const { return (this->string_      == value);              }
-        bool operator==(const MultiTypeString& mts) const;
+        inline bool operator==(const char*        value) const { return (this->string_ == std::string(value)); }
+        inline bool operator==(const std::string& value) const { return (this->string_ == value);              }
+        bool operator==(const MultiTypeString&    mts) const;
+        bool operator==(const MultiTypePrimitive& mtp) const;
 
         using MultiTypePrimitive::operator!=;
-        inline bool operator!=(const char*             value) const { return (this->string_      != std::string(value)); }
-        inline bool operator!=(const std::string&      value) const { return (this->string_      != value);              }
-        bool operator!=(const MultiTypeString& mts) const;
+        inline bool operator!=(const char*        value) const { return (this->string_ != std::string(value)); }
+        inline bool operator!=(const std::string& value) const { return (this->string_ != value);              }
+        bool operator!=(const MultiTypeString&    mts) const;
+        bool operator!=(const MultiTypePrimitive& mtp) const;
 
-        virtual operator void*()                const;
-        virtual operator int()                  const;
-        virtual operator unsigned int()         const;
-        virtual operator char()                 const;
-        virtual operator unsigned char()        const;
-        virtual operator short()                const;
-        virtual operator unsigned short()       const;
-        virtual operator long()                 const;
-        virtual operator unsigned long()        const;
-        virtual operator float ()               const;
-        virtual operator double ()              const;
-        virtual operator long double()          const;
-        virtual operator bool()                 const;
-        virtual operator std::string()          const;
-        virtual operator const char*()          const;
+        virtual operator void*()          const;
+        virtual operator int()            const;
+        virtual operator unsigned int()   const;
+        virtual operator char()           const;
+        virtual operator unsigned char()  const;
+        virtual operator short()          const;
+        virtual operator unsigned short() const;
+        virtual operator long()           const;
+        virtual operator unsigned long()  const;
+        virtual operator float ()         const;
+        virtual operator double ()        const;
+        virtual operator long double()    const;
+        virtual operator bool()           const;
+        virtual operator std::string()    const;
+        virtual operator const char*()    const;
 
         using MultiTypePrimitive::setValue;
-        inline void setValue(const char*             value) { this->type_ = MT_string;     this->string_     = std::string(value); }
-        inline void setValue(const std::string&      value) { this->type_ = MT_string;     this->string_     = value;              }
-        void setValue(const MultiTypeString& mts);
+        inline void setValue(const char*        value) { this->type_ = MT_string; this->string_ = std::string(value); }
+        inline void setValue(const std::string& value) { this->type_ = MT_string; this->string_ = value;              }
+        void setValue(const MultiTypeString&    mts);
+        void setValue(const MultiTypePrimitive& mtp);
 
-        inline std::string getString()          const { return this->string_;         }
-        inline const char*  getConstChar()      const { return this->string_.c_str(); }
+        inline std::string getString()     const { return this->string_;         }
+        inline const char*  getConstChar() const { return this->string_.c_str(); }
 
-        inline std::string& getString()          { return this->string_;         }
-        inline const char*  getConstChar()       { return this->string_.c_str(); }
+        inline std::string& getString()    { return this->string_;         }
+        inline const char*  getConstChar() { return this->string_.c_str(); }
 
         using MultiTypePrimitive::getValue;
-        inline void getValue(std::string*      variable) const { (*variable) = this->string_;         }
-        inline void getValue(const char**      variable) const { (*variable) = this->string_.c_str(); }
+        inline void getValue(std::string* variable) const { (*variable) = this->string_;         }
+        inline void getValue(const char** variable) const { (*variable) = this->string_.c_str(); }
 
         virtual std::string getTypename() const;
@@ -116,4 +121,6 @@
         virtual std::string toString() const;
         virtual bool fromString(const std::string value);
+
+        virtual bool assimilate(const MultiTypeString& mts, const MultiTypeString& defvalue = MultiTypeString());
 
     protected:
Index: code/branches/network/src/util/String.cc
===================================================================
--- code/branches/network/src/util/String.cc	(revision 1445)
+++ code/branches/network/src/util/String.cc	(revision 1446)
@@ -185,4 +185,19 @@
     else
         return str;
+}
+
+/**
+    @brief Removes enclosing {braces}.
+    @param str The string to strip
+    @return The striped string
+*/
+std::string stripEnclosingBraces(const std::string& str)
+{
+    std::string output = str;
+
+    while (output.size() >= 2 && output[0] == '{' && output[output.size() - 1] == '}')
+        output = output.substr(1, output.size() - 2);
+
+    return output;
 }
 
Index: code/branches/network/src/util/String.h
===================================================================
--- code/branches/network/src/util/String.h	(revision 1445)
+++ code/branches/network/src/util/String.h	(revision 1446)
@@ -47,4 +47,5 @@
 
 _UtilExport std::string  stripEnclosingQuotes(const std::string& str);
+_UtilExport std::string  stripEnclosingBraces(const std::string& str);
 
 _UtilExport bool         isEmpty(const std::string& str);
